lib:ldb: Use tdb_traverse_read() in ldb_kv_index_sub_transaction_commit()
[Samba.git] / source4 / torture / basic / base.c
blobfc36e6b441dd75b08fdde7b0038d93da9ff1b4f5
1 /*
2 Unix SMB/CIFS implementation.
3 SMB torture tester
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/>.
21 #include "includes.h"
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;
43 bool ok;
45 make_nbt_name_client(&calling, lpcfg_netbios_name(tctx->lp_ctx));
47 nbt_choose_called_name(NULL, &called, host, NBT_NAME_SERVER);
49 cli = smbcli_state_init(NULL);
50 if (!cli) {
51 torture_result(tctx, TORTURE_FAIL, "Failed initialize smbcli_struct to connect with %s\n", host);
52 goto failed;
55 lpcfg_smbcli_options(tctx->lp_ctx, &options);
57 ok = smbcli_socket_connect(cli, host, lpcfg_smb_ports(tctx->lp_ctx),
58 tctx->ev,
59 lpcfg_resolve_context(tctx->lp_ctx),
60 &options,
61 lpcfg_socket_options(tctx->lp_ctx),
62 &calling, &called);
63 if (!ok) {
64 torture_result(tctx, TORTURE_FAIL, "Failed to connect with %s\n", host);
65 goto failed;
68 cli->transport = smbcli_transport_init(cli->sock, cli,
69 true, &cli->options);
70 cli->sock = NULL;
71 if (!cli->transport) {
72 torture_result(tctx, TORTURE_FAIL, "smbcli_transport_init failed\n");
73 goto failed;
76 return cli;
78 failed:
79 talloc_free(cli);
80 return NULL;
83 static bool tcon_devtest(struct torture_context *tctx,
84 struct smbcli_state *cli,
85 const char *myshare, const char *devtype,
86 NTSTATUS expected_error)
88 bool status;
89 const char *password = torture_setting_string(tctx, "password", NULL);
91 status = NT_STATUS_IS_OK(smbcli_tconX(cli, myshare, devtype,
92 password));
94 torture_comment(tctx, "Trying share %s with devtype %s\n", myshare, devtype);
96 if (NT_STATUS_IS_OK(expected_error)) {
97 if (!status) {
98 torture_fail(tctx, talloc_asprintf(tctx,
99 "tconX to share %s with type %s "
100 "should have succeeded but failed",
101 myshare, devtype));
103 smbcli_tdis(cli);
104 } else {
105 if (status) {
106 torture_fail(tctx, talloc_asprintf(tctx,
107 "tconx to share %s with type %s "
108 "should have failed but succeeded",
109 myshare, devtype));
110 } else {
111 if (NT_STATUS_EQUAL(smbcli_nt_error(cli->tree),
112 expected_error)) {
113 } else {
114 torture_fail(tctx, "Returned unexpected error");
118 return true;
124 test whether fnums and tids open on one VC are available on another (a major
125 security hole)
127 static bool run_fdpasstest(struct torture_context *tctx,
128 struct smbcli_state *cli1,
129 struct smbcli_state *cli2)
131 const char *fname = "\\fdpass.tst";
132 int fnum1, oldtid;
133 uint8_t buf[1024];
135 smbcli_unlink(cli1->tree, fname);
137 torture_comment(tctx, "Opening a file on connection 1\n");
139 fnum1 = smbcli_open(cli1->tree, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
140 torture_assert(tctx, fnum1 != -1,
141 talloc_asprintf(tctx,
142 "open of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree)));
144 torture_comment(tctx, "writing to file on connection 1\n");
146 torture_assert(tctx,
147 smbcli_write(cli1->tree, fnum1, 0, "hello world\n", 0, 13) == 13,
148 talloc_asprintf(tctx,
149 "write failed (%s)\n", smbcli_errstr(cli1->tree)));
151 oldtid = cli2->tree->tid;
152 cli2->session->vuid = cli1->session->vuid;
153 cli2->tree->tid = cli1->tree->tid;
154 cli2->session->pid = cli1->session->pid;
156 torture_comment(tctx, "reading from file on connection 2\n");
158 torture_assert(tctx, smbcli_read(cli2->tree, fnum1, buf, 0, 13) != 13,
159 talloc_asprintf(tctx,
160 "read succeeded! nasty security hole [%s]\n", buf));
162 smbcli_close(cli1->tree, fnum1);
163 smbcli_unlink(cli1->tree, fname);
165 cli2->tree->tid = oldtid;
167 return true;
171 This checks how the getatr calls works
173 static bool run_attrtest(struct torture_context *tctx,
174 struct smbcli_state *cli)
176 int fnum;
177 time_t t, t2;
178 const char *fname = "\\attrib123456789.tst";
179 bool correct = true;
181 smbcli_unlink(cli->tree, fname);
182 fnum = smbcli_open(cli->tree, fname,
183 O_RDWR | O_CREAT | O_TRUNC, DENY_NONE);
184 smbcli_close(cli->tree, fnum);
186 if (NT_STATUS_IS_ERR(smbcli_getatr(cli->tree, fname, NULL, NULL, &t))) {
187 torture_result(tctx, TORTURE_FAIL, "getatr failed (%s)\n", smbcli_errstr(cli->tree));
188 correct = false;
191 torture_comment(tctx, "New file time is %s", ctime(&t));
193 if (labs(t - time(NULL)) > 60*60*24*10) {
194 torture_result(tctx, TORTURE_FAIL, "ERROR: SMBgetatr bug. time is %s",
195 ctime(&t));
196 t = time(NULL);
197 correct = false;
200 t2 = t-60*60*24; /* 1 day ago */
202 torture_comment(tctx, "Setting file time to %s", ctime(&t2));
204 if (NT_STATUS_IS_ERR(smbcli_setatr(cli->tree, fname, 0, t2))) {
205 torture_comment(tctx, "setatr failed (%s)\n", smbcli_errstr(cli->tree));
206 correct = true;
209 if (NT_STATUS_IS_ERR(smbcli_getatr(cli->tree, fname, NULL, NULL, &t))) {
210 torture_comment(tctx, "getatr failed (%s)\n", smbcli_errstr(cli->tree));
211 correct = true;
214 torture_comment(tctx, "Retrieved file time as %s", ctime(&t));
216 if (t != t2) {
217 torture_comment(tctx, "ERROR: getatr/setatr bug. times are\n%s",
218 ctime(&t));
219 torture_comment(tctx, "%s", ctime(&t2));
220 correct = true;
223 smbcli_unlink(cli->tree, fname);
225 return correct;
229 This checks a couple of trans2 calls
231 static bool run_trans2test(struct torture_context *tctx,
232 struct smbcli_state *cli)
234 int fnum;
235 size_t size;
236 time_t c_time, a_time, m_time, w_time, m_time2;
237 const char *fname = "\\trans2.tst";
238 const char *dname = "\\trans2";
239 const char *fname2 = "\\trans2\\trans2.tst";
240 const char *pname;
241 bool correct = true;
243 smbcli_unlink(cli->tree, fname);
245 torture_comment(tctx, "Testing qfileinfo\n");
247 fnum = smbcli_open(cli->tree, fname,
248 O_RDWR | O_CREAT | O_TRUNC, DENY_NONE);
249 if (NT_STATUS_IS_ERR(smbcli_qfileinfo(cli->tree, fnum, NULL, &size, &c_time, &a_time, &m_time,
250 NULL, NULL))) {
251 torture_result(tctx, TORTURE_FAIL, "ERROR: qfileinfo failed (%s)\n", smbcli_errstr(cli->tree));
252 correct = false;
255 torture_comment(tctx, "Testing NAME_INFO\n");
257 if (NT_STATUS_IS_ERR(smbcli_qfilename(cli->tree, fnum, &pname))) {
258 torture_result(tctx, TORTURE_FAIL, "ERROR: qfilename failed (%s)\n", smbcli_errstr(cli->tree));
259 correct = false;
262 if (!pname || strcmp(pname, fname)) {
263 torture_result(tctx, TORTURE_FAIL, "qfilename gave different name? [%s] [%s]\n",
264 fname, pname);
265 correct = false;
268 smbcli_close(cli->tree, fnum);
269 smbcli_unlink(cli->tree, fname);
271 fnum = smbcli_open(cli->tree, fname,
272 O_RDWR | O_CREAT | O_TRUNC, DENY_NONE);
273 if (fnum == -1) {
274 torture_result(tctx, TORTURE_FAIL, "open of %s failed (%s)\n", fname, smbcli_errstr(cli->tree));
275 return false;
277 smbcli_close(cli->tree, fnum);
279 torture_comment(tctx, "Checking for sticky create times\n");
281 if (NT_STATUS_IS_ERR(smbcli_qpathinfo(cli->tree, fname, &c_time, &a_time, &m_time, &size, NULL))) {
282 torture_result(tctx, TORTURE_FAIL, "ERROR: qpathinfo failed (%s)\n", smbcli_errstr(cli->tree));
283 correct = false;
284 } else {
285 time_t t = time(NULL);
287 if (c_time != m_time) {
288 torture_comment(tctx, "create time=%s", ctime(&c_time));
289 torture_comment(tctx, "modify time=%s", ctime(&m_time));
290 torture_comment(tctx, "This system appears to have sticky create times\n");
292 if ((labs(a_time - t) > 60) && (a_time % (60*60) == 0)) {
293 torture_comment(tctx, "access time=%s", ctime(&a_time));
294 torture_result(tctx, TORTURE_FAIL, "This system appears to set a midnight access time\n");
295 correct = false;
298 if (labs(m_time - t) > 60*60*24*7) {
299 torture_result(tctx, TORTURE_FAIL, "ERROR: totally incorrect times - maybe word reversed? mtime=%s", ctime(&m_time));
300 correct = false;
305 smbcli_unlink(cli->tree, fname);
306 fnum = smbcli_open(cli->tree, fname,
307 O_RDWR | O_CREAT | O_TRUNC, DENY_NONE);
308 smbcli_close(cli->tree, fnum);
309 if (NT_STATUS_IS_ERR(smbcli_qpathinfo2(cli->tree, fname, &c_time, &a_time, &m_time, &w_time, &size, NULL, NULL))) {
310 torture_result(tctx, TORTURE_FAIL, "ERROR: qpathinfo2 failed (%s)\n", smbcli_errstr(cli->tree));
311 correct = false;
312 } else {
313 if (w_time < 60*60*24*2) {
314 torture_comment(tctx, "write time=%s", ctime(&w_time));
315 torture_result(tctx, TORTURE_FAIL, "This system appears to set a initial 0 write time\n");
316 correct = false;
320 smbcli_unlink(cli->tree, fname);
323 /* check if the server updates the directory modification time
324 when creating a new file */
325 if (NT_STATUS_IS_ERR(smbcli_mkdir(cli->tree, dname))) {
326 torture_result(tctx, TORTURE_FAIL, "ERROR: mkdir failed (%s)\n", smbcli_errstr(cli->tree));
327 correct = false;
329 sleep(3);
330 if (NT_STATUS_IS_ERR(smbcli_qpathinfo2(cli->tree, "\\trans2\\", &c_time, &a_time, &m_time, &w_time, &size, NULL, NULL))) {
331 torture_result(tctx, TORTURE_FAIL, "ERROR: qpathinfo2 failed (%s)\n", smbcli_errstr(cli->tree));
332 correct = false;
335 fnum = smbcli_open(cli->tree, fname2,
336 O_RDWR | O_CREAT | O_TRUNC, DENY_NONE);
337 smbcli_write(cli->tree, fnum, 0, &fnum, 0, sizeof(fnum));
338 smbcli_close(cli->tree, fnum);
339 if (NT_STATUS_IS_ERR(smbcli_qpathinfo2(cli->tree, "\\trans2\\", &c_time, &a_time, &m_time2, &w_time, &size, NULL, NULL))) {
340 torture_result(tctx, TORTURE_FAIL, "ERROR: qpathinfo2 failed (%s)\n", smbcli_errstr(cli->tree));
341 correct = false;
342 } else {
343 if (m_time2 == m_time) {
344 torture_result(tctx, TORTURE_FAIL, "This system does not update directory modification times\n");
345 correct = false;
348 smbcli_unlink(cli->tree, fname2);
349 smbcli_rmdir(cli->tree, dname);
351 return correct;
354 /* send smb negprot commands, not reading the response */
355 static bool run_negprot_nowait(struct torture_context *tctx)
357 int i;
358 struct smbcli_state *cli, *cli2;
359 bool correct = true;
361 torture_comment(tctx, "starting negprot nowait test\n");
363 cli = open_nbt_connection(tctx);
364 if (!cli) {
365 return false;
368 torture_comment(tctx, "Filling send buffer\n");
370 for (i=0;i<100;i++) {
371 struct tevent_req *req;
372 req = smb_raw_negotiate_send(cli, tctx->ev,
373 cli->transport,
374 PROTOCOL_CORE,
375 PROTOCOL_NT1);
376 tevent_loop_once(tctx->ev);
377 if (!tevent_req_is_in_progress(req)) {
378 NTSTATUS status;
380 status = smb_raw_negotiate_recv(req);
381 TALLOC_FREE(req);
382 if (i > 0) {
383 torture_comment(tctx, "Failed to fill pipe packet[%d] - %s (ignored)\n",
384 i+1, nt_errstr(status));
385 break;
386 } else {
387 torture_result(tctx, TORTURE_FAIL, "Failed to fill pipe - %s \n",
388 nt_errstr(status));
389 torture_close_connection(cli);
390 return false;
395 torture_comment(tctx, "Opening secondary connection\n");
396 if (!torture_open_connection(&cli2, tctx, 1)) {
397 torture_result(tctx, TORTURE_FAIL, "Failed to open secondary connection\n");
398 correct = false;
401 if (!torture_close_connection(cli2)) {
402 torture_result(tctx, TORTURE_FAIL, "Failed to close secondary connection\n");
403 correct = false;
406 torture_close_connection(cli);
408 return correct;
412 this checks to see if a secondary tconx can use open files from an
413 earlier tconx
415 static bool run_tcon_test(struct torture_context *tctx, struct smbcli_state *cli)
417 const char *fname = "\\tcontest.tmp";
418 int fnum1;
419 uint16_t cnum1, cnum2, cnum3;
420 uint16_t vuid1, vuid2;
421 uint8_t buf[4];
422 bool ret = true;
423 struct smbcli_tree *tree1;
424 const char *host = torture_setting_string(tctx, "host", NULL);
425 const char *share = torture_setting_string(tctx, "share", NULL);
426 const char *password = torture_setting_string(tctx, "password", NULL);
428 if (smbcli_deltree(cli->tree, fname) == -1) {
429 torture_comment(tctx, "unlink of %s failed (%s)\n", fname, smbcli_errstr(cli->tree));
432 fnum1 = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
433 if (fnum1 == -1) {
434 torture_result(tctx, TORTURE_FAIL, "open of %s failed (%s)\n", fname, smbcli_errstr(cli->tree));
435 return false;
438 cnum1 = cli->tree->tid;
439 vuid1 = cli->session->vuid;
441 memset(buf, 0, 4); /* init buf so valgrind won't complain */
442 if (smbcli_write(cli->tree, fnum1, 0, buf, 130, 4) != 4) {
443 torture_result(tctx, TORTURE_FAIL, "initial write failed (%s)\n", smbcli_errstr(cli->tree));
444 return false;
447 tree1 = cli->tree; /* save old tree connection */
448 if (NT_STATUS_IS_ERR(smbcli_tconX(cli, share, "?????", password))) {
449 torture_result(tctx, TORTURE_FAIL, "%s refused 2nd tree connect (%s)\n", host,
450 smbcli_errstr(cli->tree));
451 return false;
454 cnum2 = cli->tree->tid;
455 cnum3 = MAX(cnum1, cnum2) + 1; /* any invalid number */
456 vuid2 = cli->session->vuid + 1;
458 /* try a write with the wrong tid */
459 cli->tree->tid = cnum2;
461 if (smbcli_write(cli->tree, fnum1, 0, buf, 130, 4) == 4) {
462 torture_result(tctx, TORTURE_FAIL, "* server allows write with wrong TID\n");
463 ret = false;
464 } else {
465 torture_comment(tctx, "server fails write with wrong TID : %s\n", smbcli_errstr(cli->tree));
469 /* try a write with an invalid tid */
470 cli->tree->tid = cnum3;
472 if (smbcli_write(cli->tree, fnum1, 0, buf, 130, 4) == 4) {
473 torture_result(tctx, TORTURE_FAIL, "* server allows write with invalid TID\n");
474 ret = false;
475 } else {
476 torture_comment(tctx, "server fails write with invalid TID : %s\n", smbcli_errstr(cli->tree));
479 /* try a write with an invalid vuid */
480 cli->session->vuid = vuid2;
481 cli->tree->tid = cnum1;
483 if (smbcli_write(cli->tree, fnum1, 0, buf, 130, 4) == 4) {
484 torture_result(tctx, TORTURE_FAIL, "* server allows write with invalid VUID\n");
485 ret = false;
486 } else {
487 torture_comment(tctx, "server fails write with invalid VUID : %s\n", smbcli_errstr(cli->tree));
490 cli->session->vuid = vuid1;
491 cli->tree->tid = cnum1;
493 if (NT_STATUS_IS_ERR(smbcli_close(cli->tree, fnum1))) {
494 torture_result(tctx, TORTURE_FAIL, "close failed (%s)\n", smbcli_errstr(cli->tree));
495 return false;
498 cli->tree->tid = cnum2;
500 if (NT_STATUS_IS_ERR(smbcli_tdis(cli))) {
501 torture_result(tctx, TORTURE_FAIL, "secondary tdis failed (%s)\n", smbcli_errstr(cli->tree));
502 return false;
505 cli->tree = tree1; /* restore initial tree */
506 cli->tree->tid = cnum1;
508 smbcli_unlink(tree1, fname);
510 return ret;
514 checks for correct tconX support
516 static bool run_tcon_devtype_test(struct torture_context *tctx,
517 struct smbcli_state *cli1)
519 const char *share = torture_setting_string(tctx, "share", NULL);
521 if (!tcon_devtest(tctx, cli1, "IPC$", "A:", NT_STATUS_BAD_DEVICE_TYPE))
522 return false;
524 if (!tcon_devtest(tctx, cli1, "IPC$", "?????", NT_STATUS_OK))
525 return false;
527 if (!tcon_devtest(tctx, cli1, "IPC$", "LPT:", NT_STATUS_BAD_DEVICE_TYPE))
528 return false;
530 if (!tcon_devtest(tctx, cli1, "IPC$", "IPC", NT_STATUS_OK))
531 return false;
533 if (!tcon_devtest(tctx, cli1, "IPC$", "FOOBA", NT_STATUS_BAD_DEVICE_TYPE))
534 return false;
536 if (!tcon_devtest(tctx, cli1, share, "A:", NT_STATUS_OK))
537 return false;
539 if (!tcon_devtest(tctx, cli1, share, "?????", NT_STATUS_OK))
540 return false;
542 if (!tcon_devtest(tctx, cli1, share, "LPT:", NT_STATUS_BAD_DEVICE_TYPE))
543 return false;
545 if (!tcon_devtest(tctx, cli1, share, "IPC", NT_STATUS_BAD_DEVICE_TYPE))
546 return false;
548 if (!tcon_devtest(tctx, cli1, share, "FOOBA", NT_STATUS_BAD_DEVICE_TYPE))
549 return false;
551 return true;
554 static bool rw_torture2(struct torture_context *tctx,
555 struct smbcli_state *c1, struct smbcli_state *c2)
557 const char *lockfname = "\\torture2.lck";
558 int fnum1;
559 int fnum2;
560 int i;
561 uint8_t buf[131072];
562 uint8_t buf_rd[131072];
563 bool correct = true;
564 ssize_t bytes_read, bytes_written;
566 torture_assert(tctx, smbcli_deltree(c1->tree, lockfname) != -1,
567 talloc_asprintf(tctx,
568 "unlink failed (%s)", smbcli_errstr(c1->tree)));
570 fnum1 = smbcli_open(c1->tree, lockfname, O_RDWR | O_CREAT | O_EXCL,
571 DENY_NONE);
572 torture_assert(tctx, fnum1 != -1,
573 talloc_asprintf(tctx,
574 "first open read/write of %s failed (%s)",
575 lockfname, smbcli_errstr(c1->tree)));
576 fnum2 = smbcli_open(c2->tree, lockfname, O_RDONLY,
577 DENY_NONE);
578 torture_assert(tctx, fnum2 != -1,
579 talloc_asprintf(tctx,
580 "second open read-only of %s failed (%s)",
581 lockfname, smbcli_errstr(c2->tree)));
583 torture_comment(tctx, "Checking data integrity over %d ops\n",
584 torture_numops);
586 for (i=0;i<torture_numops;i++)
588 size_t buf_size = ((unsigned int)random()%(sizeof(buf)-1))+ 1;
589 if (i % 10 == 0) {
590 if (torture_setting_bool(tctx, "progress", true)) {
591 torture_comment(tctx, "%d\r", i); fflush(stdout);
595 generate_random_buffer(buf, buf_size);
597 if ((bytes_written = smbcli_write(c1->tree, fnum1, 0, buf, 0, buf_size)) != buf_size) {
598 torture_comment(tctx, "write failed (%s)\n", smbcli_errstr(c1->tree));
599 torture_result(tctx, TORTURE_FAIL, "wrote %d, expected %d\n", (int)bytes_written, (int)buf_size);
600 correct = false;
601 break;
604 if ((bytes_read = smbcli_read(c2->tree, fnum2, buf_rd, 0, buf_size)) != buf_size) {
605 torture_comment(tctx, "read failed (%s)\n", smbcli_errstr(c2->tree));
606 torture_result(tctx, TORTURE_FAIL, "read %d, expected %d\n", (int)bytes_read, (int)buf_size);
607 correct = false;
608 break;
611 torture_assert_mem_equal(tctx, buf_rd, buf, buf_size,
612 "read/write compare failed\n");
615 torture_assert_ntstatus_ok(tctx, smbcli_close(c2->tree, fnum2),
616 talloc_asprintf(tctx, "close failed (%s)", smbcli_errstr(c2->tree)));
617 torture_assert_ntstatus_ok(tctx, smbcli_close(c1->tree, fnum1),
618 talloc_asprintf(tctx, "close failed (%s)", smbcli_errstr(c1->tree)));
620 torture_assert_ntstatus_ok(tctx, smbcli_unlink(c1->tree, lockfname),
621 talloc_asprintf(tctx, "unlink failed (%s)", smbcli_errstr(c1->tree)));
623 torture_comment(tctx, "\n");
625 return correct;
630 static bool run_readwritetest(struct torture_context *tctx,
631 struct smbcli_state *cli1,
632 struct smbcli_state *cli2)
634 torture_comment(tctx, "Running readwritetest v1\n");
635 if (!rw_torture2(tctx, cli1, cli2))
636 return false;
638 torture_comment(tctx, "Running readwritetest v2\n");
640 if (!rw_torture2(tctx, cli1, cli1))
641 return false;
643 return true;
647 test the timing of deferred open requests
649 static bool run_deferopen(struct torture_context *tctx, struct smbcli_state *cli, int dummy)
651 const char *fname = "\\defer_open_test.dat";
652 int i = 0;
653 bool correct = true;
654 int nsec;
655 int msec;
656 double sec;
657 NTSTATUS status;
659 nsec = torture_setting_int(tctx, "sharedelay", 1000000);
660 msec = nsec / 1000;
661 sec = ((double)nsec) / ((double) 1000000);
663 torture_comment(tctx, "pid %u: Testing deferred open requests.\n",
664 (unsigned)getpid());
666 while (i < 4) {
667 int fnum = -1;
668 int j = 1;
670 do {
671 struct timeval tv;
672 tv = timeval_current();
674 torture_comment(tctx,
675 "pid %u: create[%d,%d]...\n",
676 (unsigned)getpid(), i, j);
678 fnum = smbcli_nt_create_full(cli->tree, fname, 0,
679 SEC_RIGHTS_FILE_ALL,
680 FILE_ATTRIBUTE_NORMAL,
681 NTCREATEX_SHARE_ACCESS_NONE,
682 NTCREATEX_DISP_OPEN_IF, 0, 0);
683 status = smbcli_nt_error(cli->tree);
685 torture_comment(tctx,
686 "pid %u: create[%d,%d] gave fnum %d, status %s\n",
687 (unsigned)getpid(), i, j, fnum,
688 nt_errstr(status));
690 if (fnum != -1) {
691 break;
694 if (NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
695 double e = timeval_elapsed(&tv);
697 torture_comment(tctx, "pid %u: create[%d,%d] "
698 "time elapsed: %.2f (1 sec = %.2f)\n",
699 (unsigned)getpid(), i, j, e, sec);
700 if (e < (0.5 * sec) || e > ((1.5 * sec) + 1.5)) {
701 torture_comment(tctx, "pid %u: create[%d,%d] "
702 "timing incorrect\n",
703 (unsigned)getpid(), i, j);
704 torture_result(tctx, TORTURE_FAIL, "Timing incorrect %.2f violation 1 sec == %.2f\n",
705 e, sec);
706 return false;
710 j++;
712 } while (NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION));
714 torture_comment(tctx,
715 "pid %u: create loop %d done: fnum %d, status %s\n",
716 (unsigned)getpid(), i, fnum, nt_errstr(status));
718 torture_assert(tctx, fnum != -1,
719 talloc_asprintf(tctx,
720 "pid %u: Failed to open %s, error=%s\n",
721 (unsigned)getpid(), fname,
722 smbcli_errstr(cli->tree)));
724 torture_comment(tctx, "pid %u: open %d\n", (unsigned)getpid(), i);
726 smb_msleep(10 * msec);
728 status = smbcli_close(cli->tree, fnum);
730 torture_comment(tctx, "pid %u: open %d closed, status %s\n",
731 (unsigned)getpid(), i, nt_errstr(status));
733 torture_assert(tctx, !NT_STATUS_IS_ERR(status),
734 talloc_asprintf(tctx,
735 "pid %u: Failed to close %s, "
736 "error=%s\n",
737 (unsigned)getpid(), fname,
738 smbcli_errstr(cli->tree)));
740 smb_msleep(2 * msec);
742 i++;
745 if (NT_STATUS_IS_ERR(smbcli_unlink(cli->tree, fname))) {
746 /* All until the last unlink will fail with sharing violation
747 but also the last request can fail since the file could have
748 been successfully deleted by another (test) process */
749 status = smbcli_nt_error(cli->tree);
750 if ((!NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION))
751 && (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND))) {
752 torture_result(tctx, TORTURE_FAIL, "unlink of %s failed (%s)\n", fname, smbcli_errstr(cli->tree));
753 correct = false;
757 torture_comment(tctx, "pid %u: deferred test finished\n",
758 (unsigned)getpid());
759 return correct;
763 Try with a wrong vuid and check error message.
766 static bool run_vuidtest(struct torture_context *tctx,
767 struct smbcli_state *cli)
769 const char *fname = "\\vuid.tst";
770 int fnum;
771 size_t size;
772 time_t c_time, a_time, m_time;
774 NTSTATUS result;
776 smbcli_unlink(cli->tree, fname);
778 fnum = smbcli_open(cli->tree, fname,
779 O_RDWR | O_CREAT | O_TRUNC, DENY_NONE);
781 cli->session->vuid += 1234;
783 torture_comment(tctx, "Testing qfileinfo with wrong vuid\n");
785 if (NT_STATUS_IS_OK(result = smbcli_qfileinfo(cli->tree, fnum, NULL,
786 &size, &c_time, &a_time,
787 &m_time, NULL, NULL))) {
788 torture_fail(tctx, "qfileinfo passed with wrong vuid");
791 if (!NT_STATUS_EQUAL(cli->transport->error.e.nt_status,
792 NT_STATUS_DOS(ERRSRV, ERRbaduid)) &&
793 !NT_STATUS_EQUAL(cli->transport->error.e.nt_status,
794 NT_STATUS_INVALID_HANDLE)) {
795 torture_fail(tctx, talloc_asprintf(tctx,
796 "qfileinfo should have returned DOS error "
797 "ERRSRV:ERRbaduid\n but returned %s",
798 smbcli_errstr(cli->tree)));
801 cli->session->vuid -= 1234;
803 torture_assert_ntstatus_ok(tctx, smbcli_close(cli->tree, fnum),
804 talloc_asprintf(tctx, "close failed (%s)", smbcli_errstr(cli->tree)));
806 smbcli_unlink(cli->tree, fname);
808 return true;
812 Test open mode returns on read-only files.
814 static bool run_opentest(struct torture_context *tctx, struct smbcli_state *cli1,
815 struct smbcli_state *cli2)
817 const char *fname = "\\readonly.file";
818 char *control_char_fname;
819 int fnum1, fnum2;
820 uint8_t buf[20];
821 size_t fsize;
822 bool correct = true;
823 char *tmp_path;
824 int failures = 0;
825 int i;
827 control_char_fname = talloc_strdup(tctx, "\\readonly.afile");
828 torture_assert_not_null(tctx, control_char_fname, "asprintf failed\n");
830 for (i = 1; i <= 0x1f; i++) {
831 control_char_fname[10] = i;
832 fnum1 = smbcli_nt_create_full(cli1->tree, control_char_fname, 0, SEC_FILE_WRITE_DATA, FILE_ATTRIBUTE_NORMAL,
833 NTCREATEX_SHARE_ACCESS_NONE, NTCREATEX_DISP_OVERWRITE_IF, 0, 0);
835 if (!check_error(__location__, cli1, ERRDOS, ERRinvalidname,
836 NT_STATUS_OBJECT_NAME_INVALID)) {
837 torture_result(tctx, TORTURE_FAIL, "Error code should be NT_STATUS_OBJECT_NAME_INVALID, was %s for file with %d char\n",
838 smbcli_errstr(cli1->tree), i);
839 failures++;
842 if (fnum1 != -1) {
843 smbcli_close(cli1->tree, fnum1);
845 smbcli_setatr(cli1->tree, control_char_fname, 0, 0);
846 smbcli_unlink(cli1->tree, control_char_fname);
848 TALLOC_FREE(control_char_fname);
850 if (!failures)
851 torture_comment(tctx, "Create file with control char names passed.\n");
853 smbcli_setatr(cli1->tree, fname, 0, 0);
854 smbcli_unlink(cli1->tree, fname);
856 fnum1 = smbcli_open(cli1->tree, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
857 if (fnum1 == -1) {
858 torture_result(tctx, TORTURE_FAIL, "open of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
859 return false;
862 if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum1))) {
863 torture_result(tctx, TORTURE_FAIL, "close2 failed (%s)\n", smbcli_errstr(cli1->tree));
864 return false;
867 if (NT_STATUS_IS_ERR(smbcli_setatr(cli1->tree, fname, FILE_ATTRIBUTE_READONLY, 0))) {
868 torture_result(tctx, TORTURE_FAIL,
869 __location__ ": smbcli_setatr failed (%s)\n", smbcli_errstr(cli1->tree));
870 CHECK_MAX_FAILURES(error_test1);
871 return false;
874 fnum1 = smbcli_open(cli1->tree, fname, O_RDONLY, DENY_WRITE);
875 if (fnum1 == -1) {
876 torture_result(tctx, TORTURE_FAIL,
877 __location__ ": open of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
878 CHECK_MAX_FAILURES(error_test1);
879 return false;
882 /* This will fail - but the error should be ERRnoaccess, not ERRbadshare. */
883 fnum2 = smbcli_open(cli1->tree, fname, O_RDWR, DENY_ALL);
885 if (check_error(__location__, cli1, ERRDOS, ERRnoaccess,
886 NT_STATUS_ACCESS_DENIED)) {
887 torture_comment(tctx, "correct error code ERRDOS/ERRnoaccess returned\n");
890 torture_comment(tctx, "finished open test 1\n");
892 error_test1:
893 smbcli_close(cli1->tree, fnum1);
895 /* Now try not readonly and ensure ERRbadshare is returned. */
897 smbcli_setatr(cli1->tree, fname, 0, 0);
899 fnum1 = smbcli_open(cli1->tree, fname, O_RDONLY, DENY_WRITE);
900 if (fnum1 == -1) {
901 torture_result(tctx, TORTURE_FAIL, "open of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
902 return false;
905 /* This will fail - but the error should be ERRshare. */
906 fnum2 = smbcli_open(cli1->tree, fname, O_RDWR, DENY_ALL);
908 if (check_error(__location__, cli1, ERRDOS, ERRbadshare,
909 NT_STATUS_SHARING_VIOLATION)) {
910 torture_comment(tctx, "correct error code ERRDOS/ERRbadshare returned\n");
913 if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum1))) {
914 torture_result(tctx, TORTURE_FAIL, "close2 failed (%s)\n", smbcli_errstr(cli1->tree));
915 return false;
918 smbcli_unlink(cli1->tree, fname);
920 torture_comment(tctx, "finished open test 2\n");
922 /* Test truncate open disposition on file opened for read. */
924 fnum1 = smbcli_open(cli1->tree, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
925 if (fnum1 == -1) {
926 torture_result(tctx, TORTURE_FAIL, "(3) open (1) of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
927 return false;
930 /* write 20 bytes. */
932 memset(buf, '\0', 20);
934 if (smbcli_write(cli1->tree, fnum1, 0, buf, 0, 20) != 20) {
935 torture_result(tctx, TORTURE_FAIL, "write failed (%s)\n", smbcli_errstr(cli1->tree));
936 correct = false;
939 if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum1))) {
940 torture_result(tctx, TORTURE_FAIL, "(3) close1 failed (%s)\n", smbcli_errstr(cli1->tree));
941 return false;
944 /* Ensure size == 20. */
945 if (NT_STATUS_IS_ERR(smbcli_getatr(cli1->tree, fname, NULL, &fsize, NULL))) {
946 torture_result(tctx, TORTURE_FAIL,
947 __location__ ": (3) getatr failed (%s)\n", smbcli_errstr(cli1->tree));
948 CHECK_MAX_FAILURES(error_test3);
949 return false;
952 if (fsize != 20) {
953 torture_result(tctx, TORTURE_FAIL,
954 __location__ ": (3) file size != 20\n");
955 CHECK_MAX_FAILURES(error_test3);
956 return false;
959 /* Now test if we can truncate a file opened for readonly. */
961 fnum1 = smbcli_open(cli1->tree, fname, O_RDONLY|O_TRUNC, DENY_NONE);
962 if (fnum1 == -1) {
963 torture_result(tctx, TORTURE_FAIL,
964 __location__ ": (3) open (2) of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
965 CHECK_MAX_FAILURES(error_test3);
966 return false;
969 if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum1))) {
970 torture_result(tctx, TORTURE_FAIL,
971 __location__ ": close2 failed (%s)\n", smbcli_errstr(cli1->tree));
972 return false;
975 /* Ensure size == 0. */
976 if (NT_STATUS_IS_ERR(smbcli_getatr(cli1->tree, fname, NULL, &fsize, NULL))) {
977 torture_result(tctx, TORTURE_FAIL,
978 __location__ ": (3) getatr failed (%s)\n", smbcli_errstr(cli1->tree));
979 CHECK_MAX_FAILURES(error_test3);
980 return false;
983 if (fsize != 0) {
984 torture_result(tctx, TORTURE_FAIL,
985 __location__ ": (3) file size != 0\n");
986 CHECK_MAX_FAILURES(error_test3);
987 return false;
989 torture_comment(tctx, "finished open test 3\n");
990 error_test3:
992 fnum1 = fnum2 = -1;
993 smbcli_unlink(cli1->tree, fname);
996 torture_comment(tctx, "Testing ctemp\n");
997 fnum1 = smbcli_ctemp(cli1->tree, "\\", &tmp_path);
998 if (fnum1 == -1) {
999 torture_result(tctx, TORTURE_FAIL,
1000 __location__ ": ctemp failed (%s)\n", smbcli_errstr(cli1->tree));
1001 CHECK_MAX_FAILURES(error_test4);
1002 return false;
1004 torture_comment(tctx, "ctemp gave path %s\n", tmp_path);
1006 error_test4:
1007 if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum1))) {
1008 torture_comment(tctx, "close of temp failed (%s)\n", smbcli_errstr(cli1->tree));
1010 if (NT_STATUS_IS_ERR(smbcli_unlink(cli1->tree, tmp_path))) {
1011 torture_comment(tctx, "unlink of temp failed (%s)\n", smbcli_errstr(cli1->tree));
1014 /* Test the non-io opens... */
1016 torture_comment(tctx, "Test #1 testing 2 non-io opens (no delete)\n");
1017 fnum1 = fnum2 = -1;
1018 smbcli_setatr(cli2->tree, fname, 0, 0);
1019 smbcli_unlink(cli2->tree, fname);
1021 fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0, SEC_FILE_READ_ATTRIBUTE, FILE_ATTRIBUTE_NORMAL,
1022 NTCREATEX_SHARE_ACCESS_NONE, NTCREATEX_DISP_OVERWRITE_IF, 0, 0);
1024 if (fnum1 == -1) {
1025 torture_result(tctx, TORTURE_FAIL,
1026 __location__ ": Test 1 open 1 of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
1027 CHECK_MAX_FAILURES(error_test10);
1028 return false;
1031 fnum2 = smbcli_nt_create_full(cli2->tree, fname, 0, SEC_FILE_READ_ATTRIBUTE, FILE_ATTRIBUTE_NORMAL,
1032 NTCREATEX_SHARE_ACCESS_NONE, NTCREATEX_DISP_OPEN_IF, 0, 0);
1033 if (fnum2 == -1) {
1034 torture_result(tctx, TORTURE_FAIL,
1035 __location__ ": Test 1 open 2 of %s failed (%s)\n", fname, smbcli_errstr(cli2->tree));
1036 CHECK_MAX_FAILURES(error_test10);
1037 return false;
1040 torture_comment(tctx, "non-io open test #1 passed.\n");
1041 error_test10:
1043 if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum1))) {
1044 torture_comment(tctx, "Test 1 close 1 of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
1046 if (NT_STATUS_IS_ERR(smbcli_close(cli2->tree, fnum2))) {
1047 torture_comment(tctx, "Test 1 close 2 of %s failed (%s)\n", fname, smbcli_errstr(cli2->tree));
1050 torture_comment(tctx, "Test #2 testing 2 non-io opens (first with delete)\n");
1051 fnum1 = fnum2 = -1;
1052 smbcli_unlink(cli1->tree, fname);
1054 fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0, SEC_STD_DELETE|SEC_FILE_READ_ATTRIBUTE, FILE_ATTRIBUTE_NORMAL,
1055 NTCREATEX_SHARE_ACCESS_NONE, NTCREATEX_DISP_OVERWRITE_IF, 0, 0);
1057 if (fnum1 == -1) {
1058 torture_result(tctx, TORTURE_FAIL,
1059 __location__ ": Test 2 open 1 of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
1060 CHECK_MAX_FAILURES(error_test20);
1061 return false;
1064 fnum2 = smbcli_nt_create_full(cli2->tree, fname, 0, SEC_FILE_READ_ATTRIBUTE, FILE_ATTRIBUTE_NORMAL,
1065 NTCREATEX_SHARE_ACCESS_NONE, NTCREATEX_DISP_OPEN_IF, 0, 0);
1067 if (fnum2 == -1) {
1068 torture_result(tctx, TORTURE_FAIL,
1069 __location__ ": Test 2 open 2 of %s failed (%s)\n", fname, smbcli_errstr(cli2->tree));
1070 CHECK_MAX_FAILURES(error_test20);
1071 return false;
1074 torture_comment(tctx, "non-io open test #2 passed.\n");
1075 error_test20:
1077 if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum1))) {
1078 torture_comment(tctx, "Test 1 close 1 of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
1080 if (NT_STATUS_IS_ERR(smbcli_close(cli2->tree, fnum2))) {
1081 torture_comment(tctx, "Test 1 close 2 of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
1084 fnum1 = fnum2 = -1;
1085 smbcli_unlink(cli1->tree, fname);
1087 torture_comment(tctx, "Test #3 testing 2 non-io opens (second with delete)\n");
1089 fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0, SEC_FILE_READ_ATTRIBUTE, FILE_ATTRIBUTE_NORMAL,
1090 NTCREATEX_SHARE_ACCESS_NONE, NTCREATEX_DISP_OVERWRITE_IF, 0, 0);
1092 if (fnum1 == -1) {
1093 torture_result(tctx, TORTURE_FAIL,
1094 __location__ ": Test 3 open 1 of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
1095 CHECK_MAX_FAILURES(error_test30);
1096 return false;
1099 fnum2 = smbcli_nt_create_full(cli2->tree, fname, 0, SEC_STD_DELETE|SEC_FILE_READ_ATTRIBUTE, FILE_ATTRIBUTE_NORMAL,
1100 NTCREATEX_SHARE_ACCESS_NONE, NTCREATEX_DISP_OPEN_IF, 0, 0);
1102 if (fnum2 == -1) {
1103 torture_result(tctx, TORTURE_FAIL,
1104 __location__ ": Test 3 open 2 of %s failed (%s)\n", fname, smbcli_errstr(cli2->tree));
1105 CHECK_MAX_FAILURES(error_test30);
1106 return false;
1109 torture_comment(tctx, "non-io open test #3 passed.\n");
1110 error_test30:
1112 if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum1))) {
1113 torture_comment(tctx, "Test 3 close 1 of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
1115 if (NT_STATUS_IS_ERR(smbcli_close(cli2->tree, fnum2))) {
1116 torture_comment(tctx, "Test 3 close 2 of %s failed (%s)\n", fname, smbcli_errstr(cli2->tree));
1119 torture_comment(tctx, "Test #4 testing 2 non-io opens (both with delete)\n");
1120 fnum1 = fnum2 = -1;
1121 smbcli_unlink(cli1->tree, fname);
1123 fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0, SEC_STD_DELETE|SEC_FILE_READ_ATTRIBUTE, FILE_ATTRIBUTE_NORMAL,
1124 NTCREATEX_SHARE_ACCESS_NONE, NTCREATEX_DISP_OVERWRITE_IF, 0, 0);
1126 if (fnum1 == -1) {
1127 torture_result(tctx, TORTURE_FAIL,
1128 __location__ ": Test 4 open 1 of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
1129 CHECK_MAX_FAILURES(error_test40);
1130 return false;
1133 fnum2 = smbcli_nt_create_full(cli2->tree, fname, 0, SEC_STD_DELETE|SEC_FILE_READ_ATTRIBUTE, FILE_ATTRIBUTE_NORMAL,
1134 NTCREATEX_SHARE_ACCESS_NONE, NTCREATEX_DISP_OPEN_IF, 0, 0);
1136 if (fnum2 != -1) {
1137 torture_result(tctx, TORTURE_FAIL,
1138 __location__ ": Test 4 open 2 of %s SUCCEEDED - should have failed (%s)\n", fname, smbcli_errstr(cli2->tree));
1139 CHECK_MAX_FAILURES(error_test40);
1140 return false;
1143 torture_comment(tctx, "Test 4 open 2 of %s gave %s (correct error should be %s)\n", fname, smbcli_errstr(cli2->tree), "sharing violation");
1145 torture_comment(tctx, "non-io open test #4 passed.\n");
1146 error_test40:
1148 if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum1))) {
1149 torture_comment(tctx, "Test 4 close 1 of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
1151 if (fnum2 != -1 && NT_STATUS_IS_ERR(smbcli_close(cli2->tree, fnum2))) {
1152 torture_comment(tctx, "Test 4 close 2 of %s failed (%s)\n", fname, smbcli_errstr(cli2->tree));
1155 torture_comment(tctx, "Test #5 testing 2 non-io opens (both with delete - both with file share delete)\n");
1156 fnum1 = fnum2 = -1;
1157 smbcli_unlink(cli1->tree, fname);
1159 fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0, SEC_STD_DELETE|SEC_FILE_READ_ATTRIBUTE, FILE_ATTRIBUTE_NORMAL,
1160 NTCREATEX_SHARE_ACCESS_DELETE, NTCREATEX_DISP_OVERWRITE_IF, 0, 0);
1162 if (fnum1 == -1) {
1163 torture_result(tctx, TORTURE_FAIL,
1164 __location__ ": Test 5 open 1 of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
1165 CHECK_MAX_FAILURES(error_test50);
1166 return false;
1169 fnum2 = smbcli_nt_create_full(cli2->tree, fname, 0, SEC_STD_DELETE|SEC_FILE_READ_ATTRIBUTE, FILE_ATTRIBUTE_NORMAL,
1170 NTCREATEX_SHARE_ACCESS_DELETE, NTCREATEX_DISP_OPEN_IF, 0, 0);
1172 if (fnum2 == -1) {
1173 torture_result(tctx, TORTURE_FAIL,
1174 __location__ ": Test 5 open 2 of %s failed (%s)\n", fname, smbcli_errstr(cli2->tree));
1175 CHECK_MAX_FAILURES(error_test50);
1176 return false;
1179 torture_comment(tctx, "non-io open test #5 passed.\n");
1180 error_test50:
1182 if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum1))) {
1183 torture_comment(tctx, "Test 5 close 1 of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
1186 if (NT_STATUS_IS_ERR(smbcli_close(cli2->tree, fnum2))) {
1187 torture_comment(tctx, "Test 5 close 2 of %s failed (%s)\n", fname, smbcli_errstr(cli2->tree));
1190 torture_comment(tctx, "Test #6 testing 1 non-io open, one io open\n");
1191 fnum1 = fnum2 = -1;
1192 smbcli_unlink(cli1->tree, fname);
1194 fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0, SEC_FILE_READ_DATA, FILE_ATTRIBUTE_NORMAL,
1195 NTCREATEX_SHARE_ACCESS_NONE, NTCREATEX_DISP_OVERWRITE_IF, 0, 0);
1197 if (fnum1 == -1) {
1198 torture_result(tctx, TORTURE_FAIL,
1199 __location__ ": Test 6 open 1 of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
1200 CHECK_MAX_FAILURES(error_test60);
1201 return false;
1204 fnum2 = smbcli_nt_create_full(cli2->tree, fname, 0, SEC_FILE_READ_ATTRIBUTE, FILE_ATTRIBUTE_NORMAL,
1205 NTCREATEX_SHARE_ACCESS_READ, NTCREATEX_DISP_OPEN_IF, 0, 0);
1207 if (fnum2 == -1) {
1208 torture_result(tctx, TORTURE_FAIL,
1209 __location__ ": Test 6 open 2 of %s failed (%s)\n", fname, smbcli_errstr(cli2->tree));
1210 CHECK_MAX_FAILURES(error_test60);
1211 return false;
1214 torture_comment(tctx, "non-io open test #6 passed.\n");
1215 error_test60:
1217 if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum1))) {
1218 torture_comment(tctx, "Test 6 close 1 of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
1221 if (NT_STATUS_IS_ERR(smbcli_close(cli2->tree, fnum2))) {
1222 torture_comment(tctx, "Test 6 close 2 of %s failed (%s)\n", fname, smbcli_errstr(cli2->tree));
1225 torture_comment(tctx, "Test #7 testing 1 non-io open, one io open with delete\n");
1226 fnum1 = fnum2 = -1;
1227 smbcli_unlink(cli1->tree, fname);
1229 fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0, SEC_FILE_READ_DATA, FILE_ATTRIBUTE_NORMAL,
1230 NTCREATEX_SHARE_ACCESS_NONE, NTCREATEX_DISP_OVERWRITE_IF, 0, 0);
1232 if (fnum1 == -1) {
1233 torture_result(tctx, TORTURE_FAIL,
1234 __location__ ": Test 7 open 1 of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
1235 CHECK_MAX_FAILURES(error_test70);
1236 return false;
1239 fnum2 = smbcli_nt_create_full(cli2->tree, fname, 0, SEC_STD_DELETE|SEC_FILE_READ_ATTRIBUTE, FILE_ATTRIBUTE_NORMAL,
1240 NTCREATEX_SHARE_ACCESS_READ|NTCREATEX_SHARE_ACCESS_DELETE, NTCREATEX_DISP_OPEN_IF, 0, 0);
1242 if (fnum2 != -1) {
1243 torture_result(tctx, TORTURE_FAIL,
1244 __location__ ": Test 7 open 2 of %s SUCCEEDED - should have failed (%s)\n", fname, smbcli_errstr(cli2->tree));
1245 CHECK_MAX_FAILURES(error_test70);
1246 return false;
1249 torture_comment(tctx, "Test 7 open 2 of %s gave %s (correct error should be %s)\n", fname, smbcli_errstr(cli2->tree), "sharing violation");
1251 torture_comment(tctx, "non-io open test #7 passed.\n");
1252 error_test70:
1254 if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum1))) {
1255 torture_comment(tctx, "Test 7 close 1 of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
1257 if (fnum2 != -1 && NT_STATUS_IS_ERR(smbcli_close(cli2->tree, fnum2))) {
1258 torture_comment(tctx, "Test 7 close 2 of %s failed (%s)\n", fname, smbcli_errstr(cli2->tree));
1261 torture_comment(tctx, "Test #8 testing one normal open, followed by lock, followed by open with truncate\n");
1262 fnum1 = fnum2 = -1;
1263 smbcli_unlink(cli1->tree, fname);
1265 fnum1 = smbcli_open(cli1->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
1266 if (fnum1 == -1) {
1267 torture_result(tctx, TORTURE_FAIL, "(8) open (1) of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
1268 return false;
1271 /* write 20 bytes. */
1273 memset(buf, '\0', 20);
1275 if (smbcli_write(cli1->tree, fnum1, 0, buf, 0, 20) != 20) {
1276 torture_result(tctx, TORTURE_FAIL, "(8) write failed (%s)\n", smbcli_errstr(cli1->tree));
1277 correct = false;
1280 /* Ensure size == 20. */
1281 if (NT_STATUS_IS_ERR(smbcli_getatr(cli1->tree, fname, NULL, &fsize, NULL))) {
1282 torture_result(tctx, TORTURE_FAIL,
1283 __location__ ": (8) getatr (1) failed (%s)\n", smbcli_errstr(cli1->tree));
1284 CHECK_MAX_FAILURES(error_test80);
1285 return false;
1288 if (fsize != 20) {
1289 torture_result(tctx, TORTURE_FAIL,
1290 __location__ ": (8) file size %lu != 20\n", (unsigned long)fsize);
1291 CHECK_MAX_FAILURES(error_test80);
1292 return false;
1295 /* Get an exclusive lock on the open file. */
1296 if (NT_STATUS_IS_ERR(smbcli_lock(cli1->tree, fnum1, 0, 4, 0, WRITE_LOCK))) {
1297 torture_result(tctx, TORTURE_FAIL,
1298 __location__ ": (8) lock1 failed (%s)\n", smbcli_errstr(cli1->tree));
1299 CHECK_MAX_FAILURES(error_test80);
1300 return false;
1303 fnum2 = smbcli_open(cli1->tree, fname, O_RDWR|O_TRUNC, DENY_NONE);
1304 if (fnum1 == -1) {
1305 torture_result(tctx, TORTURE_FAIL, "(8) open (2) of %s with truncate failed (%s)\n", fname, smbcli_errstr(cli1->tree));
1306 return false;
1309 /* Ensure size == 0. */
1310 if (NT_STATUS_IS_ERR(smbcli_getatr(cli1->tree, fname, NULL, &fsize, NULL))) {
1311 torture_result(tctx, TORTURE_FAIL,
1312 __location__ ": (8) getatr (2) failed (%s)\n", smbcli_errstr(cli1->tree));
1313 CHECK_MAX_FAILURES(error_test80);
1314 return false;
1317 if (fsize != 0) {
1318 torture_result(tctx, TORTURE_FAIL,
1319 __location__ ": (8) file size %lu != 0\n", (unsigned long)fsize);
1320 CHECK_MAX_FAILURES(error_test80);
1321 return false;
1324 if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum1))) {
1325 torture_result(tctx, TORTURE_FAIL, "(8) close1 failed (%s)\n", smbcli_errstr(cli1->tree));
1326 return false;
1329 if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum2))) {
1330 torture_result(tctx, TORTURE_FAIL, "(8) close1 failed (%s)\n", smbcli_errstr(cli1->tree));
1331 return false;
1334 error_test80:
1336 torture_comment(tctx, "open test #8 passed.\n");
1338 smbcli_unlink(cli1->tree, fname);
1340 return failures > 0 ? false : correct;
1343 /* FIRST_DESIRED_ACCESS 0xf019f */
1344 #define FIRST_DESIRED_ACCESS SEC_FILE_READ_DATA|SEC_FILE_WRITE_DATA|SEC_FILE_APPEND_DATA|\
1345 SEC_FILE_READ_EA| /* 0xf */ \
1346 SEC_FILE_WRITE_EA|SEC_FILE_READ_ATTRIBUTE| /* 0x90 */ \
1347 SEC_FILE_WRITE_ATTRIBUTE| /* 0x100 */ \
1348 SEC_STD_DELETE|SEC_STD_READ_CONTROL|\
1349 SEC_STD_WRITE_DAC|SEC_STD_WRITE_OWNER /* 0xf0000 */
1350 /* SECOND_DESIRED_ACCESS 0xe0080 */
1351 #define SECOND_DESIRED_ACCESS SEC_FILE_READ_ATTRIBUTE| /* 0x80 */ \
1352 SEC_STD_READ_CONTROL|SEC_STD_WRITE_DAC|\
1353 SEC_STD_WRITE_OWNER /* 0xe0000 */
1355 #if 0
1356 #define THIRD_DESIRED_ACCESS FILE_READ_ATTRIBUTE| /* 0x80 */ \
1357 READ_CONTROL|WRITE_DAC|\
1358 SEC_FILE_READ_DATA|\
1359 WRITE_OWNER /* */
1360 #endif
1365 Test ntcreate calls made by xcopy
1367 static bool run_xcopy(struct torture_context *tctx,
1368 struct smbcli_state *cli1)
1370 const char *fname = "\\test.txt";
1371 int fnum1, fnum2;
1373 fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0,
1374 FIRST_DESIRED_ACCESS,
1375 FILE_ATTRIBUTE_ARCHIVE,
1376 NTCREATEX_SHARE_ACCESS_NONE,
1377 NTCREATEX_DISP_OVERWRITE_IF,
1378 0x4044, 0);
1380 torture_assert(tctx, fnum1 != -1, talloc_asprintf(tctx,
1381 "First open failed - %s", smbcli_errstr(cli1->tree)));
1383 fnum2 = smbcli_nt_create_full(cli1->tree, fname, 0,
1384 SECOND_DESIRED_ACCESS, 0,
1385 NTCREATEX_SHARE_ACCESS_READ|NTCREATEX_SHARE_ACCESS_WRITE|NTCREATEX_SHARE_ACCESS_DELETE, NTCREATEX_DISP_OPEN,
1386 0x200000, 0);
1387 torture_assert(tctx, fnum2 != -1, talloc_asprintf(tctx,
1388 "second open failed - %s", smbcli_errstr(cli1->tree)));
1390 return true;
1393 static bool run_iometer(struct torture_context *tctx,
1394 struct smbcli_state *cli)
1396 const char *fname = "\\iobw.tst";
1397 int fnum;
1398 size_t filesize;
1399 NTSTATUS status;
1400 char buf[2048];
1401 int ops;
1403 memset(buf, 0, sizeof(buf));
1405 status = smbcli_getatr(cli->tree, fname, NULL, &filesize, NULL);
1406 torture_assert_ntstatus_ok(tctx, status,
1407 talloc_asprintf(tctx, "smbcli_getatr failed: %s", nt_errstr(status)));
1409 torture_comment(tctx, "size: %d\n", (int)filesize);
1411 filesize -= (sizeof(buf) - 1);
1413 fnum = smbcli_nt_create_full(cli->tree, fname, 0x16,
1414 0x2019f, 0, 0x3, 3, 0x42, 0x3);
1415 torture_assert(tctx, fnum != -1, talloc_asprintf(tctx, "open failed: %s",
1416 smbcli_errstr(cli->tree)));
1418 ops = 0;
1420 while (true) {
1421 int i, num_reads, num_writes;
1423 num_reads = random() % 10;
1424 num_writes = random() % 3;
1426 for (i=0; i<num_reads; i++) {
1427 ssize_t res;
1428 if (ops++ > torture_numops) {
1429 return true;
1431 res = smbcli_read(cli->tree, fnum, buf,
1432 random() % filesize, sizeof(buf));
1433 torture_assert(tctx, res == sizeof(buf),
1434 talloc_asprintf(tctx, "read failed: %s",
1435 smbcli_errstr(cli->tree)));
1437 for (i=0; i<num_writes; i++) {
1438 ssize_t res;
1439 if (ops++ > torture_numops) {
1440 return true;
1442 res = smbcli_write(cli->tree, fnum, 0, buf,
1443 random() % filesize, sizeof(buf));
1444 torture_assert(tctx, res == sizeof(buf),
1445 talloc_asprintf(tctx, "read failed: %s",
1446 smbcli_errstr(cli->tree)));
1452 tries variants of chkpath
1454 static bool torture_chkpath_test(struct torture_context *tctx,
1455 struct smbcli_state *cli)
1457 int fnum;
1458 bool ret;
1460 torture_comment(tctx, "Testing valid and invalid paths\n");
1462 /* cleanup from an old run */
1463 smbcli_rmdir(cli->tree, "\\chkpath.dir\\dir2");
1464 smbcli_unlink_wcard(cli->tree, "\\chkpath.dir\\*");
1465 smbcli_rmdir(cli->tree, "\\chkpath.dir");
1467 if (NT_STATUS_IS_ERR(smbcli_mkdir(cli->tree, "\\chkpath.dir"))) {
1468 torture_result(tctx, TORTURE_FAIL, "mkdir1 failed : %s\n", smbcli_errstr(cli->tree));
1469 return false;
1472 if (NT_STATUS_IS_ERR(smbcli_mkdir(cli->tree, "\\chkpath.dir\\dir2"))) {
1473 torture_result(tctx, TORTURE_FAIL, "mkdir2 failed : %s\n", smbcli_errstr(cli->tree));
1474 return false;
1477 fnum = smbcli_open(cli->tree, "\\chkpath.dir\\foo.txt", O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
1478 if (fnum == -1) {
1479 torture_result(tctx, TORTURE_FAIL, "open1 failed (%s)\n", smbcli_errstr(cli->tree));
1480 return false;
1482 smbcli_close(cli->tree, fnum);
1484 if (NT_STATUS_IS_ERR(smbcli_chkpath(cli->tree, "\\chkpath.dir"))) {
1485 torture_result(tctx, TORTURE_FAIL, "chkpath1 failed: %s\n", smbcli_errstr(cli->tree));
1486 ret = false;
1489 if (NT_STATUS_IS_ERR(smbcli_chkpath(cli->tree, "\\chkpath.dir\\dir2"))) {
1490 torture_result(tctx, TORTURE_FAIL, "chkpath2 failed: %s\n", smbcli_errstr(cli->tree));
1491 ret = false;
1494 if (NT_STATUS_IS_ERR(smbcli_chkpath(cli->tree, "\\chkpath.dir\\foo.txt"))) {
1495 ret = check_error(__location__, cli, ERRDOS, ERRbadpath,
1496 NT_STATUS_NOT_A_DIRECTORY);
1497 } else {
1498 torture_result(tctx, TORTURE_FAIL, "* chkpath on a file should fail\n");
1499 ret = false;
1502 if (NT_STATUS_IS_ERR(smbcli_chkpath(cli->tree, "\\chkpath.dir\\bar.txt"))) {
1503 ret = check_error(__location__, cli, ERRDOS, ERRbadpath,
1504 NT_STATUS_OBJECT_NAME_NOT_FOUND);
1505 } else {
1506 torture_result(tctx, TORTURE_FAIL, "* chkpath on a non existent file should fail\n");
1507 ret = false;
1510 if (NT_STATUS_IS_ERR(smbcli_chkpath(cli->tree, "\\chkpath.dir\\dirxx\\bar.txt"))) {
1511 ret = check_error(__location__, cli, ERRDOS, ERRbadpath,
1512 NT_STATUS_OBJECT_PATH_NOT_FOUND);
1513 } else {
1514 torture_result(tctx, TORTURE_FAIL, "* chkpath on a non existent component should fail\n");
1515 ret = false;
1518 smbcli_rmdir(cli->tree, "\\chkpath.dir\\dir2");
1519 smbcli_unlink_wcard(cli->tree, "\\chkpath.dir\\*");
1520 smbcli_rmdir(cli->tree, "\\chkpath.dir");
1522 return ret;
1526 * This is a test to exercise some weird Samba3 error paths.
1529 static bool torture_samba3_errorpaths(struct torture_context *tctx)
1531 bool nt_status_support;
1532 bool client_ntlmv2_auth;
1533 struct smbcli_state *cli_nt = NULL, *cli_dos = NULL;
1534 bool result = false;
1535 int fnum;
1536 const char *os2_fname = ".+,;=[].";
1537 const char *dname = "samba3_errordir";
1538 union smb_open io;
1539 NTSTATUS status;
1541 nt_status_support = lpcfg_nt_status_support(tctx->lp_ctx);
1542 client_ntlmv2_auth = lpcfg_client_ntlmv2_auth(tctx->lp_ctx);
1544 if (!lpcfg_set_cmdline(tctx->lp_ctx, "nt status support", "yes")) {
1545 torture_result(tctx, TORTURE_FAIL, "Could not set 'nt status support = yes'\n");
1546 goto fail;
1548 if (!lpcfg_set_cmdline(tctx->lp_ctx, "client ntlmv2 auth", "yes")) {
1549 torture_result(tctx, TORTURE_FAIL, "Could not set 'client ntlmv2 auth = yes'\n");
1550 goto fail;
1553 if (!torture_open_connection(&cli_nt, tctx, 0)) {
1554 goto fail;
1557 if (!lpcfg_set_cmdline(tctx->lp_ctx, "nt status support", "no")) {
1558 torture_result(tctx, TORTURE_FAIL, "Could not set 'nt status support = no'\n");
1559 goto fail;
1561 if (!lpcfg_set_cmdline(tctx->lp_ctx, "client ntlmv2 auth", "no")) {
1562 torture_result(tctx, TORTURE_FAIL, "Could not set 'client ntlmv2 auth = no'\n");
1563 goto fail;
1566 if (!torture_open_connection(&cli_dos, tctx, 1)) {
1567 goto fail;
1570 if (!lpcfg_set_cmdline(tctx->lp_ctx, "nt status support",
1571 nt_status_support ? "yes":"no")) {
1572 torture_result(tctx, TORTURE_FAIL, "Could not reset 'nt status support'");
1573 goto fail;
1575 if (!lpcfg_set_cmdline(tctx->lp_ctx, "client ntlmv2 auth",
1576 client_ntlmv2_auth ? "yes":"no")) {
1577 torture_result(tctx, TORTURE_FAIL, "Could not reset 'client ntlmv2 auth'");
1578 goto fail;
1581 smbcli_unlink(cli_nt->tree, os2_fname);
1582 smbcli_rmdir(cli_nt->tree, dname);
1584 if (!NT_STATUS_IS_OK(smbcli_mkdir(cli_nt->tree, dname))) {
1585 torture_result(tctx, TORTURE_FAIL, "smbcli_mkdir(%s) failed: %s\n", dname,
1586 smbcli_errstr(cli_nt->tree));
1587 goto fail;
1590 io.generic.level = RAW_OPEN_NTCREATEX;
1591 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED;
1592 io.ntcreatex.in.root_fid.fnum = 0;
1593 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
1594 io.ntcreatex.in.alloc_size = 1024*1024;
1595 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_DIRECTORY;
1596 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
1597 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
1598 io.ntcreatex.in.create_options = 0;
1599 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
1600 io.ntcreatex.in.security_flags = 0;
1601 io.ntcreatex.in.fname = dname;
1603 status = smb_raw_open(cli_nt->tree, tctx, &io);
1604 if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_COLLISION)) {
1605 torture_result(tctx, TORTURE_FAIL, "(%s) incorrect status %s should be %s\n",
1606 __location__, nt_errstr(status),
1607 nt_errstr(NT_STATUS_OBJECT_NAME_COLLISION));
1608 goto fail;
1610 status = smb_raw_open(cli_dos->tree, tctx, &io);
1611 if (!NT_STATUS_EQUAL(status, NT_STATUS_DOS(ERRDOS, ERRfilexists))) {
1612 torture_result(tctx, TORTURE_FAIL, "(%s) incorrect status %s should be %s\n",
1613 __location__, nt_errstr(status),
1614 nt_errstr(NT_STATUS_DOS(ERRDOS, ERRfilexists)));
1615 goto fail;
1618 status = smbcli_mkdir(cli_nt->tree, dname);
1619 if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_COLLISION)) {
1620 torture_result(tctx, TORTURE_FAIL, "(%s) incorrect status %s should be %s\n",
1621 __location__, nt_errstr(status),
1622 nt_errstr(NT_STATUS_OBJECT_NAME_COLLISION));
1623 goto fail;
1625 status = smbcli_mkdir(cli_dos->tree, dname);
1626 if (!NT_STATUS_EQUAL(status, NT_STATUS_DOS(ERRDOS, ERRnoaccess))) {
1627 torture_result(tctx, TORTURE_FAIL, "(%s) incorrect status %s should be %s\n",
1628 __location__, nt_errstr(status),
1629 nt_errstr(NT_STATUS_DOS(ERRDOS, ERRnoaccess)));
1630 goto fail;
1634 union smb_mkdir md;
1635 md.t2mkdir.level = RAW_MKDIR_T2MKDIR;
1636 md.t2mkdir.in.path = dname;
1637 md.t2mkdir.in.num_eas = 0;
1638 md.t2mkdir.in.eas = NULL;
1640 status = smb_raw_mkdir(cli_nt->tree, &md);
1641 if (!NT_STATUS_EQUAL(status,
1642 NT_STATUS_OBJECT_NAME_COLLISION)) {
1643 torture_comment(
1644 tctx, "(%s) incorrect status %s should be "
1645 "NT_STATUS_OBJECT_NAME_COLLISION\n",
1646 __location__, nt_errstr(status));
1647 goto fail;
1649 status = smb_raw_mkdir(cli_dos->tree, &md);
1650 if (!NT_STATUS_EQUAL(status,
1651 NT_STATUS_DOS(ERRDOS, ERRrename))) {
1652 torture_result(tctx, TORTURE_FAIL, "(%s) incorrect status %s "
1653 "should be ERRDOS:ERRrename\n",
1654 __location__, nt_errstr(status));
1655 goto fail;
1659 io.ntcreatex.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
1660 status = smb_raw_open(cli_nt->tree, tctx, &io);
1661 if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_COLLISION)) {
1662 torture_result(tctx, TORTURE_FAIL, "(%s) incorrect status %s should be %s\n",
1663 __location__, nt_errstr(status),
1664 nt_errstr(NT_STATUS_OBJECT_NAME_COLLISION));
1665 goto fail;
1668 status = smb_raw_open(cli_dos->tree, tctx, &io);
1669 if (!NT_STATUS_EQUAL(status, NT_STATUS_DOS(ERRDOS, ERRfilexists))) {
1670 torture_result(tctx, TORTURE_FAIL, "(%s) incorrect status %s should be %s\n",
1671 __location__, nt_errstr(status),
1672 nt_errstr(NT_STATUS_DOS(ERRDOS, ERRfilexists)));
1673 goto fail;
1677 /* Test an invalid DOS deny mode */
1678 const char *fname = "test.txt";
1680 fnum = smbcli_open(cli_nt->tree, fname, O_RDWR | O_CREAT, 5);
1681 if (fnum != -1) {
1682 torture_result(tctx, TORTURE_FAIL, "Open(%s) with invalid deny mode succeeded -- "
1683 "expected failure\n", fname);
1684 smbcli_close(cli_nt->tree, fnum);
1685 goto fail;
1687 if (!NT_STATUS_EQUAL(smbcli_nt_error(cli_nt->tree),
1688 NT_STATUS_DOS(ERRDOS,ERRbadaccess))) {
1689 torture_result(tctx, TORTURE_FAIL, "Expected DOS error ERRDOS/ERRbadaccess, "
1690 "got %s\n", smbcli_errstr(cli_nt->tree));
1691 goto fail;
1694 fnum = smbcli_open(cli_dos->tree, fname, O_RDWR | O_CREAT, 5);
1695 if (fnum != -1) {
1696 torture_result(tctx, TORTURE_FAIL, "Open(%s) with invalid deny mode succeeded -- "
1697 "expected failure\n", fname);
1698 smbcli_close(cli_nt->tree, fnum);
1699 goto fail;
1701 if (!NT_STATUS_EQUAL(smbcli_nt_error(cli_nt->tree),
1702 NT_STATUS_DOS(ERRDOS,ERRbadaccess))) {
1703 torture_result(tctx, TORTURE_FAIL, "Expected DOS error ERRDOS:ERRbadaccess, "
1704 "got %s\n", smbcli_errstr(cli_nt->tree));
1705 goto fail;
1711 * Samba 3.0.23 has a bug that an existing file can be opened
1712 * as a directory using ntcreate&x. Test this.
1715 const char *fname = "\\test_dir.txt";
1717 fnum = smbcli_open(cli_nt->tree, fname, O_RDWR|O_CREAT,
1718 DENY_NONE);
1719 if (fnum == -1) {
1720 d_printf("(%s) smbcli_open failed: %s\n", __location__,
1721 smbcli_errstr(cli_nt->tree));
1723 smbcli_close(cli_nt->tree, fnum);
1725 io.generic.level = RAW_OPEN_NTCREATEX;
1726 io.ntcreatex.in.root_fid.fnum = 0;
1727 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
1728 io.ntcreatex.in.alloc_size = 0;
1729 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_DIRECTORY;
1730 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
1731 NTCREATEX_SHARE_ACCESS_WRITE|
1732 NTCREATEX_SHARE_ACCESS_DELETE;
1733 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN;
1734 io.ntcreatex.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
1735 io.ntcreatex.in.impersonation =
1736 NTCREATEX_IMPERSONATION_ANONYMOUS;
1737 io.ntcreatex.in.security_flags = 0;
1738 io.ntcreatex.in.fname = fname;
1739 io.ntcreatex.in.flags = 0;
1741 status = smb_raw_open(cli_nt->tree, tctx, &io);
1742 if (!NT_STATUS_EQUAL(status, NT_STATUS_NOT_A_DIRECTORY)) {
1743 torture_result(tctx, TORTURE_FAIL, "ntcreate as dir gave %s, "
1744 "expected NT_STATUS_NOT_A_DIRECTORY\n",
1745 nt_errstr(status));
1746 result = false;
1749 if (NT_STATUS_IS_OK(status)) {
1750 smbcli_close(cli_nt->tree, io.ntcreatex.out.file.fnum);
1753 status = smb_raw_open(cli_dos->tree, tctx, &io);
1754 if (!NT_STATUS_EQUAL(status, NT_STATUS_DOS(ERRDOS,
1755 ERRbaddirectory))) {
1756 torture_result(tctx, TORTURE_FAIL, "ntcreate as dir gave %s, "
1757 "expected NT_STATUS_NOT_A_DIRECTORY\n",
1758 nt_errstr(status));
1759 result = false;
1762 if (NT_STATUS_IS_OK(status)) {
1763 smbcli_close(cli_dos->tree,
1764 io.ntcreatex.out.file.fnum);
1767 smbcli_unlink(cli_nt->tree, fname);
1770 if (!torture_setting_bool(tctx, "samba3", false)) {
1771 goto done;
1774 fnum = smbcli_open(cli_dos->tree, os2_fname,
1775 O_RDWR | O_CREAT | O_TRUNC,
1776 DENY_NONE);
1777 if (fnum != -1) {
1778 torture_result(tctx, TORTURE_FAIL, "Open(%s) succeeded -- expected failure\n",
1779 os2_fname);
1780 smbcli_close(cli_dos->tree, fnum);
1781 goto fail;
1784 if (!NT_STATUS_EQUAL(smbcli_nt_error(cli_dos->tree),
1785 NT_STATUS_DOS(ERRDOS, ERRcannotopen))) {
1786 torture_result(tctx, TORTURE_FAIL, "Expected DOS error ERRDOS/ERRcannotopen, got %s\n",
1787 smbcli_errstr(cli_dos->tree));
1788 goto fail;
1791 fnum = smbcli_open(cli_nt->tree, os2_fname,
1792 O_RDWR | O_CREAT | O_TRUNC,
1793 DENY_NONE);
1794 if (fnum != -1) {
1795 torture_result(tctx, TORTURE_FAIL, "Open(%s) succeeded -- expected failure\n",
1796 os2_fname);
1797 smbcli_close(cli_nt->tree, fnum);
1798 goto fail;
1801 if (!NT_STATUS_EQUAL(smbcli_nt_error(cli_nt->tree),
1802 NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
1803 torture_result(tctx, TORTURE_FAIL, "Expected error NT_STATUS_OBJECT_NAME_NOT_FOUND, "
1804 "got %s\n", smbcli_errstr(cli_nt->tree));
1805 goto fail;
1808 done:
1809 result = true;
1811 fail:
1812 if (cli_dos != NULL) {
1813 torture_close_connection(cli_dos);
1815 if (cli_nt != NULL) {
1816 torture_close_connection(cli_nt);
1819 return result;
1823 This checks file/dir birthtime
1825 static void list_fn(struct clilist_file_info *finfo, const char *name,
1826 void *state){
1828 /* Just to change dir access time*/
1829 sleep(5);
1833 static bool run_birthtimetest(struct torture_context *tctx,
1834 struct smbcli_state *cli)
1836 int fnum;
1837 size_t size;
1838 time_t c_time, a_time, m_time, w_time, c_time1;
1839 const char *fname = "\\birthtime.tst";
1840 const char *dname = "\\birthtime";
1841 const char *fname2 = "\\birthtime\\birthtime.tst";
1842 bool correct = true;
1843 uint8_t buf[16];
1846 smbcli_unlink(cli->tree, fname);
1848 torture_comment(tctx, "Testing Birthtime for File\n");
1850 /* Save File birthtime/creationtime */
1851 fnum = smbcli_open(cli->tree, fname, O_RDWR | O_CREAT | O_TRUNC,
1852 DENY_NONE);
1853 if (NT_STATUS_IS_ERR(smbcli_qfileinfo(cli->tree, fnum, NULL, &size,
1854 &c_time, &a_time, &m_time, NULL, NULL))) {
1855 torture_result(tctx, TORTURE_FAIL, "ERROR: qfileinfo failed (%s)\n",
1856 smbcli_errstr(cli->tree));
1857 correct = false;
1859 smbcli_close(cli->tree, fnum);
1861 sleep(10);
1863 /* Change in File attribute changes file change time*/
1864 smbcli_setatr(cli->tree, fname, FILE_ATTRIBUTE_SYSTEM, 0);
1866 fnum = smbcli_open(cli->tree, fname, O_RDWR | O_CREAT , DENY_NONE);
1867 /* Writing updates modification time*/
1868 smbcli_smbwrite(cli->tree, fnum, &fname, 0, sizeof(fname));
1869 /*Reading updates access time */
1870 smbcli_read(cli->tree, fnum, buf, 0, 13);
1871 smbcli_close(cli->tree, fnum);
1873 if (NT_STATUS_IS_ERR(smbcli_qpathinfo2(cli->tree, fname, &c_time1,
1874 &a_time, &m_time, &w_time, &size, NULL, NULL))) {
1875 torture_result(tctx, TORTURE_FAIL, "ERROR: qpathinfo2 failed (%s)\n",
1876 smbcli_errstr(cli->tree));
1877 correct = false;
1878 } else {
1879 fprintf(stdout, "c_time = %li, c_time1 = %li\n",
1880 (long) c_time, (long) c_time1);
1881 if (c_time1 != c_time) {
1882 torture_result(tctx, TORTURE_FAIL, "This system updated file \
1883 birth times! Not expected!\n");
1884 correct = false;
1887 smbcli_unlink(cli->tree, fname);
1889 torture_comment(tctx, "Testing Birthtime for Directory\n");
1891 /* check if the server does not update the directory birth time
1892 when creating a new file */
1893 if (NT_STATUS_IS_ERR(smbcli_mkdir(cli->tree, dname))) {
1894 torture_result(tctx, TORTURE_FAIL, "ERROR: mkdir failed (%s)\n",
1895 smbcli_errstr(cli->tree));
1896 correct = false;
1898 sleep(3);
1899 if (NT_STATUS_IS_ERR(smbcli_qpathinfo2(cli->tree, "\\birthtime\\",
1900 &c_time,&a_time,&m_time,&w_time, &size, NULL, NULL))){
1901 torture_result(tctx, TORTURE_FAIL, "ERROR: qpathinfo2 failed (%s)\n",
1902 smbcli_errstr(cli->tree));
1903 correct = false;
1906 /* Creating a new file changes dir modification time and change time*/
1907 smbcli_unlink(cli->tree, fname2);
1908 fnum = smbcli_open(cli->tree, fname2, O_RDWR | O_CREAT | O_TRUNC,
1909 DENY_NONE);
1910 smbcli_smbwrite(cli->tree, fnum, &fnum, 0, sizeof(fnum));
1911 smbcli_read(cli->tree, fnum, buf, 0, 13);
1912 smbcli_close(cli->tree, fnum);
1914 /* dir listing changes dir access time*/
1915 smbcli_list(cli->tree, "\\birthtime\\*", 0, list_fn, cli );
1917 if (NT_STATUS_IS_ERR(smbcli_qpathinfo2(cli->tree, "\\birthtime\\",
1918 &c_time1, &a_time, &m_time,&w_time,&size,NULL,NULL))){
1919 torture_result(tctx, TORTURE_FAIL, "ERROR: qpathinfo2 failed (%s)\n",
1920 smbcli_errstr(cli->tree));
1921 correct = false;
1922 } else {
1923 fprintf(stdout, "c_time = %li, c_time1 = %li\n",
1924 (long) c_time, (long) c_time1);
1925 if (c_time1 != c_time) {
1926 torture_result(tctx, TORTURE_FAIL, "This system updated directory \
1927 birth times! Not Expected!\n");
1928 correct = false;
1931 smbcli_unlink(cli->tree, fname2);
1932 smbcli_rmdir(cli->tree, dname);
1934 return correct;
1938 SMB1 TWRP open on root of share.
1940 static bool torture_smb1_twrp_openroot(struct torture_context *tctx,
1941 struct smbcli_state *cli)
1943 const char *snapshot = NULL;
1944 const char *p = NULL;
1945 NTSTATUS status;
1946 struct tm tm = {};
1947 bool ret = true;
1949 snapshot = torture_setting_string(tctx, "twrp_snapshot", NULL);
1950 if (snapshot == NULL) {
1951 torture_skip(tctx, "missing 'twrp_snapshot' option\n");
1954 torture_comment(tctx, "Testing open of root of "
1955 "share with timewarp (%s)\n",
1956 snapshot);
1958 setenv("TZ", "GMT", 1);
1960 p = strptime(snapshot, "@GMT-%Y.%m.%d-%H.%M.%S", &tm);
1961 torture_assert_goto(tctx, p != NULL, ret, done, "strptime\n");
1962 torture_assert_goto(tctx, *p == '\0', ret, done, "strptime\n");
1964 cli->session->flags2 |= FLAGS2_REPARSE_PATH;
1965 status = smbcli_chkpath(cli->tree, snapshot);
1966 cli->session->flags2 &= ~FLAGS2_REPARSE_PATH;
1968 if (NT_STATUS_IS_ERR(status)) {
1969 torture_result(tctx,
1970 TORTURE_FAIL,
1971 "smbcli_chkpath on %s : %s\n",
1972 snapshot,
1973 smbcli_errstr(cli->tree));
1974 return false;
1977 done:
1979 return ret;
1982 static void torture_smb1_find_gmt_mask_list_fn(struct clilist_file_info *finfo,
1983 const char *name,
1984 void *state)
1989 * SMB1 @GMT token as search mask is valid
1991 static bool torture_smb1_find_gmt_mask(struct torture_context *tctx,
1992 struct smbcli_state *cli)
1994 const char *dname = "\\torture_smb1_find_gmt_mask";
1995 const char *path = "\\torture_smb1_find_gmt_mask\\@GMT-2022.11.24-16.24.00";
1996 int fnum;
1997 int n;
1998 NTSTATUS status;
1999 bool ret = true;
2001 smbcli_unlink(cli->tree, path);
2002 smbcli_rmdir(cli->tree, dname);
2004 status = smbcli_mkdir(cli->tree, dname);
2005 torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
2006 "smbcli_mkdir() failed\n");
2007 fnum = smbcli_open(cli->tree, path, O_RDWR | O_CREAT, DENY_NONE);
2008 smbcli_close(cli->tree, fnum);
2010 /* Note: we don't set FLAGS2_REPARSE_PATH, so this is just a path */
2011 n = smbcli_list(cli->tree, path, 0, torture_smb1_find_gmt_mask_list_fn, cli);
2012 torture_assert_int_equal_goto(tctx, n, 1, ret, done, "Wrong count\n");
2014 done:
2015 smbcli_unlink(cli->tree, path);
2016 smbcli_rmdir(cli->tree, dname);
2017 return ret;
2020 NTSTATUS torture_base_init(TALLOC_CTX *ctx)
2022 struct torture_suite *suite = torture_suite_create(ctx, "base");
2024 torture_suite_add_2smb_test(suite, "fdpass", run_fdpasstest);
2025 torture_suite_add_suite(suite, torture_base_locktest(suite));
2026 torture_suite_add_1smb_test(suite, "unlink", torture_unlinktest);
2027 torture_suite_add_1smb_test(suite, "attr", run_attrtest);
2028 torture_suite_add_1smb_test(suite, "trans2", run_trans2test);
2029 torture_suite_add_1smb_test(suite, "birthtime", run_birthtimetest);
2030 torture_suite_add_simple_test(suite, "negnowait", run_negprot_nowait);
2031 torture_suite_add_1smb_test(suite, "dir1", torture_dirtest1);
2032 torture_suite_add_1smb_test(suite, "dir2", torture_dirtest2);
2033 torture_suite_add_1smb_test(suite, "deny1", torture_denytest1);
2034 torture_suite_add_2smb_test(suite, "deny2", torture_denytest2);
2035 torture_suite_add_2smb_test(suite, "deny3", torture_denytest3);
2036 torture_suite_add_1smb_test(suite, "denydos", torture_denydos_sharing);
2037 torture_suite_add_smb_multi_test(suite, "ntdeny1", torture_ntdenytest1);
2038 torture_suite_add_2smb_test(suite, "ntdeny2", torture_ntdenytest2);
2039 torture_suite_add_1smb_test(suite, "tcon", run_tcon_test);
2040 torture_suite_add_1smb_test(suite, "tcondev", run_tcon_devtype_test);
2041 torture_suite_add_1smb_test(suite, "vuid", run_vuidtest);
2042 torture_suite_add_2smb_test(suite, "rw1", run_readwritetest);
2043 torture_suite_add_2smb_test(suite, "open", run_opentest);
2044 torture_suite_add_smb_multi_test(suite, "defer_open", run_deferopen);
2045 torture_suite_add_1smb_test(suite, "xcopy", run_xcopy);
2046 torture_suite_add_1smb_test(suite, "iometer", run_iometer);
2047 torture_suite_add_1smb_test(suite, "rename", torture_test_rename);
2048 torture_suite_add_suite(suite, torture_test_delete(suite));
2049 torture_suite_add_1smb_test(suite, "properties", torture_test_properties);
2050 torture_suite_add_1smb_test(suite, "mangle", torture_mangle);
2051 torture_suite_add_1smb_test(suite, "openattr", torture_openattrtest);
2052 torture_suite_add_1smb_test(suite, "winattr", torture_winattrtest);
2053 torture_suite_add_suite(suite, torture_charset(suite));
2054 torture_suite_add_1smb_test(suite, "chkpath", torture_chkpath_test);
2055 torture_suite_add_1smb_test(suite, "secleak", torture_sec_leak);
2056 torture_suite_add_simple_test(suite, "disconnect", torture_disconnect);
2057 torture_suite_add_suite(suite, torture_delay_write(suite));
2058 torture_suite_add_simple_test(suite, "samba3error", torture_samba3_errorpaths);
2059 torture_suite_add_1smb_test(suite, "casetable", torture_casetable);
2060 torture_suite_add_1smb_test(suite, "utable", torture_utable);
2061 torture_suite_add_simple_test(suite, "smb", torture_smb_scan);
2062 torture_suite_add_suite(suite, torture_trans2_aliases(suite));
2063 torture_suite_add_1smb_test(suite, "trans2-scan", torture_trans2_scan);
2064 torture_suite_add_1smb_test(suite, "nttrans", torture_nttrans_scan);
2065 torture_suite_add_1smb_test(suite, "createx_access", torture_createx_access);
2066 torture_suite_add_2smb_test(suite, "createx_sharemodes_file", torture_createx_sharemodes_file);
2067 torture_suite_add_2smb_test(suite, "createx_sharemodes_dir", torture_createx_sharemodes_dir);
2068 torture_suite_add_1smb_test(suite, "maximum_allowed", torture_maximum_allowed);
2070 torture_suite_add_simple_test(suite, "bench-holdcon", torture_holdcon);
2071 torture_suite_add_1smb_test(suite, "bench-holdopen", torture_holdopen);
2072 torture_suite_add_simple_test(suite, "bench-readwrite", run_benchrw);
2073 torture_suite_add_smb_multi_test(suite, "bench-torture", run_torture);
2074 torture_suite_add_1smb_test(suite, "scan-pipe_number", run_pipe_number);
2075 torture_suite_add_1smb_test(suite, "scan-ioctl", torture_ioctl_test);
2076 torture_suite_add_1smb_test(suite, "scan-maxfid", torture_maxfid_test);
2077 torture_suite_add_1smb_test(suite,
2078 "smb1-twrp-openroot",
2079 torture_smb1_twrp_openroot);
2080 torture_suite_add_1smb_test(suite,
2081 "smb1-find-gmt-mask",
2082 torture_smb1_find_gmt_mask);
2084 suite->description = talloc_strdup(suite,
2085 "Basic SMB tests (imported from the original smbtorture)");
2087 torture_register_suite(ctx, suite);
2089 return NT_STATUS_OK;