Move waf into third_party/.
[Samba.git] / source4 / torture / basic / base.c
blob6a792b2781f8499e2f5d326dc7b57c43dea5787c
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 (abs(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 ((abs(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 (abs(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_NT1);
375 tevent_loop_once(tctx->ev);
376 if (!tevent_req_is_in_progress(req)) {
377 NTSTATUS status;
379 status = smb_raw_negotiate_recv(req);
380 TALLOC_FREE(req);
381 if (i > 0) {
382 torture_comment(tctx, "Failed to fill pipe packet[%d] - %s (ignored)\n",
383 i+1, nt_errstr(status));
384 break;
385 } else {
386 torture_result(tctx, TORTURE_FAIL, "Failed to fill pipe - %s \n",
387 nt_errstr(status));
388 torture_close_connection(cli);
389 return false;
394 torture_comment(tctx, "Opening secondary connection\n");
395 if (!torture_open_connection(&cli2, tctx, 1)) {
396 torture_result(tctx, TORTURE_FAIL, "Failed to open secondary connection\n");
397 correct = false;
400 if (!torture_close_connection(cli2)) {
401 torture_result(tctx, TORTURE_FAIL, "Failed to close secondary connection\n");
402 correct = false;
405 torture_close_connection(cli);
407 return correct;
411 this checks to see if a secondary tconx can use open files from an
412 earlier tconx
414 static bool run_tcon_test(struct torture_context *tctx, struct smbcli_state *cli)
416 const char *fname = "\\tcontest.tmp";
417 int fnum1;
418 uint16_t cnum1, cnum2, cnum3;
419 uint16_t vuid1, vuid2;
420 uint8_t buf[4];
421 bool ret = true;
422 struct smbcli_tree *tree1;
423 const char *host = torture_setting_string(tctx, "host", NULL);
424 const char *share = torture_setting_string(tctx, "share", NULL);
425 const char *password = torture_setting_string(tctx, "password", NULL);
427 if (smbcli_deltree(cli->tree, fname) == -1) {
428 torture_comment(tctx, "unlink of %s failed (%s)\n", fname, smbcli_errstr(cli->tree));
431 fnum1 = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
432 if (fnum1 == -1) {
433 torture_result(tctx, TORTURE_FAIL, "open of %s failed (%s)\n", fname, smbcli_errstr(cli->tree));
434 return false;
437 cnum1 = cli->tree->tid;
438 vuid1 = cli->session->vuid;
440 memset(buf, 0, 4); /* init buf so valgrind won't complain */
441 if (smbcli_write(cli->tree, fnum1, 0, buf, 130, 4) != 4) {
442 torture_result(tctx, TORTURE_FAIL, "initial write failed (%s)\n", smbcli_errstr(cli->tree));
443 return false;
446 tree1 = cli->tree; /* save old tree connection */
447 if (NT_STATUS_IS_ERR(smbcli_tconX(cli, share, "?????", password))) {
448 torture_result(tctx, TORTURE_FAIL, "%s refused 2nd tree connect (%s)\n", host,
449 smbcli_errstr(cli->tree));
450 talloc_free(cli);
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 asprintf(&control_char_fname, "\\readonly.afile");
828 for (i = 1; i <= 0x1f; i++) {
829 control_char_fname[10] = i;
830 fnum1 = smbcli_nt_create_full(cli1->tree, control_char_fname, 0, SEC_FILE_WRITE_DATA, FILE_ATTRIBUTE_NORMAL,
831 NTCREATEX_SHARE_ACCESS_NONE, NTCREATEX_DISP_OVERWRITE_IF, 0, 0);
833 if (!check_error(__location__, cli1, ERRDOS, ERRinvalidname,
834 NT_STATUS_OBJECT_NAME_INVALID)) {
835 torture_result(tctx, TORTURE_FAIL, "Error code should be NT_STATUS_OBJECT_NAME_INVALID, was %s for file with %d char\n",
836 smbcli_errstr(cli1->tree), i);
837 failures++;
840 if (fnum1 != -1) {
841 smbcli_close(cli1->tree, fnum1);
843 smbcli_setatr(cli1->tree, control_char_fname, 0, 0);
844 smbcli_unlink(cli1->tree, control_char_fname);
846 free(control_char_fname);
848 if (!failures)
849 torture_comment(tctx, "Create file with control char names passed.\n");
851 smbcli_setatr(cli1->tree, fname, 0, 0);
852 smbcli_unlink(cli1->tree, fname);
854 fnum1 = smbcli_open(cli1->tree, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
855 if (fnum1 == -1) {
856 torture_result(tctx, TORTURE_FAIL, "open of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
857 return false;
860 if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum1))) {
861 torture_result(tctx, TORTURE_FAIL, "close2 failed (%s)\n", smbcli_errstr(cli1->tree));
862 return false;
865 if (NT_STATUS_IS_ERR(smbcli_setatr(cli1->tree, fname, FILE_ATTRIBUTE_READONLY, 0))) {
866 torture_result(tctx, TORTURE_FAIL,
867 __location__ ": smbcli_setatr failed (%s)\n", smbcli_errstr(cli1->tree));
868 CHECK_MAX_FAILURES(error_test1);
869 return false;
872 fnum1 = smbcli_open(cli1->tree, fname, O_RDONLY, DENY_WRITE);
873 if (fnum1 == -1) {
874 torture_result(tctx, TORTURE_FAIL,
875 __location__ ": open of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
876 CHECK_MAX_FAILURES(error_test1);
877 return false;
880 /* This will fail - but the error should be ERRnoaccess, not ERRbadshare. */
881 fnum2 = smbcli_open(cli1->tree, fname, O_RDWR, DENY_ALL);
883 if (check_error(__location__, cli1, ERRDOS, ERRnoaccess,
884 NT_STATUS_ACCESS_DENIED)) {
885 torture_comment(tctx, "correct error code ERRDOS/ERRnoaccess returned\n");
888 torture_comment(tctx, "finished open test 1\n");
890 error_test1:
891 smbcli_close(cli1->tree, fnum1);
893 /* Now try not readonly and ensure ERRbadshare is returned. */
895 smbcli_setatr(cli1->tree, fname, 0, 0);
897 fnum1 = smbcli_open(cli1->tree, fname, O_RDONLY, DENY_WRITE);
898 if (fnum1 == -1) {
899 torture_result(tctx, TORTURE_FAIL, "open of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
900 return false;
903 /* This will fail - but the error should be ERRshare. */
904 fnum2 = smbcli_open(cli1->tree, fname, O_RDWR, DENY_ALL);
906 if (check_error(__location__, cli1, ERRDOS, ERRbadshare,
907 NT_STATUS_SHARING_VIOLATION)) {
908 torture_comment(tctx, "correct error code ERRDOS/ERRbadshare returned\n");
911 if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum1))) {
912 torture_result(tctx, TORTURE_FAIL, "close2 failed (%s)\n", smbcli_errstr(cli1->tree));
913 return false;
916 smbcli_unlink(cli1->tree, fname);
918 torture_comment(tctx, "finished open test 2\n");
920 /* Test truncate open disposition on file opened for read. */
922 fnum1 = smbcli_open(cli1->tree, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
923 if (fnum1 == -1) {
924 torture_result(tctx, TORTURE_FAIL, "(3) open (1) of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
925 return false;
928 /* write 20 bytes. */
930 memset(buf, '\0', 20);
932 if (smbcli_write(cli1->tree, fnum1, 0, buf, 0, 20) != 20) {
933 torture_result(tctx, TORTURE_FAIL, "write failed (%s)\n", smbcli_errstr(cli1->tree));
934 correct = false;
937 if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum1))) {
938 torture_result(tctx, TORTURE_FAIL, "(3) close1 failed (%s)\n", smbcli_errstr(cli1->tree));
939 return false;
942 /* Ensure size == 20. */
943 if (NT_STATUS_IS_ERR(smbcli_getatr(cli1->tree, fname, NULL, &fsize, NULL))) {
944 torture_result(tctx, TORTURE_FAIL,
945 __location__ ": (3) getatr failed (%s)\n", smbcli_errstr(cli1->tree));
946 CHECK_MAX_FAILURES(error_test3);
947 return false;
950 if (fsize != 20) {
951 torture_result(tctx, TORTURE_FAIL,
952 __location__ ": (3) file size != 20\n");
953 CHECK_MAX_FAILURES(error_test3);
954 return false;
957 /* Now test if we can truncate a file opened for readonly. */
959 fnum1 = smbcli_open(cli1->tree, fname, O_RDONLY|O_TRUNC, DENY_NONE);
960 if (fnum1 == -1) {
961 torture_result(tctx, TORTURE_FAIL,
962 __location__ ": (3) open (2) of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
963 CHECK_MAX_FAILURES(error_test3);
964 return false;
967 if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum1))) {
968 torture_result(tctx, TORTURE_FAIL,
969 __location__ ": close2 failed (%s)\n", smbcli_errstr(cli1->tree));
970 return false;
973 /* Ensure size == 0. */
974 if (NT_STATUS_IS_ERR(smbcli_getatr(cli1->tree, fname, NULL, &fsize, NULL))) {
975 torture_result(tctx, TORTURE_FAIL,
976 __location__ ": (3) getatr failed (%s)\n", smbcli_errstr(cli1->tree));
977 CHECK_MAX_FAILURES(error_test3);
978 return false;
981 if (fsize != 0) {
982 torture_result(tctx, TORTURE_FAIL,
983 __location__ ": (3) file size != 0\n");
984 CHECK_MAX_FAILURES(error_test3);
985 return false;
987 torture_comment(tctx, "finished open test 3\n");
988 error_test3:
990 fnum1 = fnum2 = -1;
991 smbcli_unlink(cli1->tree, fname);
994 torture_comment(tctx, "Testing ctemp\n");
995 fnum1 = smbcli_ctemp(cli1->tree, "\\", &tmp_path);
996 if (fnum1 == -1) {
997 torture_result(tctx, TORTURE_FAIL,
998 __location__ ": ctemp failed (%s)\n", smbcli_errstr(cli1->tree));
999 CHECK_MAX_FAILURES(error_test4);
1000 return false;
1002 torture_comment(tctx, "ctemp gave path %s\n", tmp_path);
1004 error_test4:
1005 if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum1))) {
1006 torture_comment(tctx, "close of temp failed (%s)\n", smbcli_errstr(cli1->tree));
1008 if (NT_STATUS_IS_ERR(smbcli_unlink(cli1->tree, tmp_path))) {
1009 torture_comment(tctx, "unlink of temp failed (%s)\n", smbcli_errstr(cli1->tree));
1012 /* Test the non-io opens... */
1014 torture_comment(tctx, "Test #1 testing 2 non-io opens (no delete)\n");
1015 fnum1 = fnum2 = -1;
1016 smbcli_setatr(cli2->tree, fname, 0, 0);
1017 smbcli_unlink(cli2->tree, fname);
1019 fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0, SEC_FILE_READ_ATTRIBUTE, FILE_ATTRIBUTE_NORMAL,
1020 NTCREATEX_SHARE_ACCESS_NONE, NTCREATEX_DISP_OVERWRITE_IF, 0, 0);
1022 if (fnum1 == -1) {
1023 torture_result(tctx, TORTURE_FAIL,
1024 __location__ ": Test 1 open 1 of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
1025 CHECK_MAX_FAILURES(error_test10);
1026 return false;
1029 fnum2 = smbcli_nt_create_full(cli2->tree, fname, 0, SEC_FILE_READ_ATTRIBUTE, FILE_ATTRIBUTE_NORMAL,
1030 NTCREATEX_SHARE_ACCESS_NONE, NTCREATEX_DISP_OPEN_IF, 0, 0);
1031 if (fnum2 == -1) {
1032 torture_result(tctx, TORTURE_FAIL,
1033 __location__ ": Test 1 open 2 of %s failed (%s)\n", fname, smbcli_errstr(cli2->tree));
1034 CHECK_MAX_FAILURES(error_test10);
1035 return false;
1038 torture_comment(tctx, "non-io open test #1 passed.\n");
1039 error_test10:
1041 if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum1))) {
1042 torture_comment(tctx, "Test 1 close 1 of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
1044 if (NT_STATUS_IS_ERR(smbcli_close(cli2->tree, fnum2))) {
1045 torture_comment(tctx, "Test 1 close 2 of %s failed (%s)\n", fname, smbcli_errstr(cli2->tree));
1048 torture_comment(tctx, "Test #2 testing 2 non-io opens (first with delete)\n");
1049 fnum1 = fnum2 = -1;
1050 smbcli_unlink(cli1->tree, fname);
1052 fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0, SEC_STD_DELETE|SEC_FILE_READ_ATTRIBUTE, FILE_ATTRIBUTE_NORMAL,
1053 NTCREATEX_SHARE_ACCESS_NONE, NTCREATEX_DISP_OVERWRITE_IF, 0, 0);
1055 if (fnum1 == -1) {
1056 torture_result(tctx, TORTURE_FAIL,
1057 __location__ ": Test 2 open 1 of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
1058 CHECK_MAX_FAILURES(error_test20);
1059 return false;
1062 fnum2 = smbcli_nt_create_full(cli2->tree, fname, 0, SEC_FILE_READ_ATTRIBUTE, FILE_ATTRIBUTE_NORMAL,
1063 NTCREATEX_SHARE_ACCESS_NONE, NTCREATEX_DISP_OPEN_IF, 0, 0);
1065 if (fnum2 == -1) {
1066 torture_result(tctx, TORTURE_FAIL,
1067 __location__ ": Test 2 open 2 of %s failed (%s)\n", fname, smbcli_errstr(cli2->tree));
1068 CHECK_MAX_FAILURES(error_test20);
1069 return false;
1072 torture_comment(tctx, "non-io open test #2 passed.\n");
1073 error_test20:
1075 if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum1))) {
1076 torture_comment(tctx, "Test 1 close 1 of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
1078 if (NT_STATUS_IS_ERR(smbcli_close(cli2->tree, fnum2))) {
1079 torture_comment(tctx, "Test 1 close 2 of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
1082 fnum1 = fnum2 = -1;
1083 smbcli_unlink(cli1->tree, fname);
1085 torture_comment(tctx, "Test #3 testing 2 non-io opens (second with delete)\n");
1087 fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0, SEC_FILE_READ_ATTRIBUTE, FILE_ATTRIBUTE_NORMAL,
1088 NTCREATEX_SHARE_ACCESS_NONE, NTCREATEX_DISP_OVERWRITE_IF, 0, 0);
1090 if (fnum1 == -1) {
1091 torture_result(tctx, TORTURE_FAIL,
1092 __location__ ": Test 3 open 1 of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
1093 CHECK_MAX_FAILURES(error_test30);
1094 return false;
1097 fnum2 = smbcli_nt_create_full(cli2->tree, fname, 0, SEC_STD_DELETE|SEC_FILE_READ_ATTRIBUTE, FILE_ATTRIBUTE_NORMAL,
1098 NTCREATEX_SHARE_ACCESS_NONE, NTCREATEX_DISP_OPEN_IF, 0, 0);
1100 if (fnum2 == -1) {
1101 torture_result(tctx, TORTURE_FAIL,
1102 __location__ ": Test 3 open 2 of %s failed (%s)\n", fname, smbcli_errstr(cli2->tree));
1103 CHECK_MAX_FAILURES(error_test30);
1104 return false;
1107 torture_comment(tctx, "non-io open test #3 passed.\n");
1108 error_test30:
1110 if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum1))) {
1111 torture_comment(tctx, "Test 3 close 1 of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
1113 if (NT_STATUS_IS_ERR(smbcli_close(cli2->tree, fnum2))) {
1114 torture_comment(tctx, "Test 3 close 2 of %s failed (%s)\n", fname, smbcli_errstr(cli2->tree));
1117 torture_comment(tctx, "Test #4 testing 2 non-io opens (both with delete)\n");
1118 fnum1 = fnum2 = -1;
1119 smbcli_unlink(cli1->tree, fname);
1121 fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0, SEC_STD_DELETE|SEC_FILE_READ_ATTRIBUTE, FILE_ATTRIBUTE_NORMAL,
1122 NTCREATEX_SHARE_ACCESS_NONE, NTCREATEX_DISP_OVERWRITE_IF, 0, 0);
1124 if (fnum1 == -1) {
1125 torture_result(tctx, TORTURE_FAIL,
1126 __location__ ": Test 4 open 1 of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
1127 CHECK_MAX_FAILURES(error_test40);
1128 return false;
1131 fnum2 = smbcli_nt_create_full(cli2->tree, fname, 0, SEC_STD_DELETE|SEC_FILE_READ_ATTRIBUTE, FILE_ATTRIBUTE_NORMAL,
1132 NTCREATEX_SHARE_ACCESS_NONE, NTCREATEX_DISP_OPEN_IF, 0, 0);
1134 if (fnum2 != -1) {
1135 torture_result(tctx, TORTURE_FAIL,
1136 __location__ ": Test 4 open 2 of %s SUCCEEDED - should have failed (%s)\n", fname, smbcli_errstr(cli2->tree));
1137 CHECK_MAX_FAILURES(error_test40);
1138 return false;
1141 torture_comment(tctx, "Test 4 open 2 of %s gave %s (correct error should be %s)\n", fname, smbcli_errstr(cli2->tree), "sharing violation");
1143 torture_comment(tctx, "non-io open test #4 passed.\n");
1144 error_test40:
1146 if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum1))) {
1147 torture_comment(tctx, "Test 4 close 1 of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
1149 if (fnum2 != -1 && NT_STATUS_IS_ERR(smbcli_close(cli2->tree, fnum2))) {
1150 torture_comment(tctx, "Test 4 close 2 of %s failed (%s)\n", fname, smbcli_errstr(cli2->tree));
1153 torture_comment(tctx, "Test #5 testing 2 non-io opens (both with delete - both with file share delete)\n");
1154 fnum1 = fnum2 = -1;
1155 smbcli_unlink(cli1->tree, fname);
1157 fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0, SEC_STD_DELETE|SEC_FILE_READ_ATTRIBUTE, FILE_ATTRIBUTE_NORMAL,
1158 NTCREATEX_SHARE_ACCESS_DELETE, NTCREATEX_DISP_OVERWRITE_IF, 0, 0);
1160 if (fnum1 == -1) {
1161 torture_result(tctx, TORTURE_FAIL,
1162 __location__ ": Test 5 open 1 of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
1163 CHECK_MAX_FAILURES(error_test50);
1164 return false;
1167 fnum2 = smbcli_nt_create_full(cli2->tree, fname, 0, SEC_STD_DELETE|SEC_FILE_READ_ATTRIBUTE, FILE_ATTRIBUTE_NORMAL,
1168 NTCREATEX_SHARE_ACCESS_DELETE, NTCREATEX_DISP_OPEN_IF, 0, 0);
1170 if (fnum2 == -1) {
1171 torture_result(tctx, TORTURE_FAIL,
1172 __location__ ": Test 5 open 2 of %s failed (%s)\n", fname, smbcli_errstr(cli2->tree));
1173 CHECK_MAX_FAILURES(error_test50);
1174 return false;
1177 torture_comment(tctx, "non-io open test #5 passed.\n");
1178 error_test50:
1180 if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum1))) {
1181 torture_comment(tctx, "Test 5 close 1 of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
1184 if (NT_STATUS_IS_ERR(smbcli_close(cli2->tree, fnum2))) {
1185 torture_comment(tctx, "Test 5 close 2 of %s failed (%s)\n", fname, smbcli_errstr(cli2->tree));
1188 torture_comment(tctx, "Test #6 testing 1 non-io open, one io open\n");
1189 fnum1 = fnum2 = -1;
1190 smbcli_unlink(cli1->tree, fname);
1192 fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0, SEC_FILE_READ_DATA, FILE_ATTRIBUTE_NORMAL,
1193 NTCREATEX_SHARE_ACCESS_NONE, NTCREATEX_DISP_OVERWRITE_IF, 0, 0);
1195 if (fnum1 == -1) {
1196 torture_result(tctx, TORTURE_FAIL,
1197 __location__ ": Test 6 open 1 of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
1198 CHECK_MAX_FAILURES(error_test60);
1199 return false;
1202 fnum2 = smbcli_nt_create_full(cli2->tree, fname, 0, SEC_FILE_READ_ATTRIBUTE, FILE_ATTRIBUTE_NORMAL,
1203 NTCREATEX_SHARE_ACCESS_READ, NTCREATEX_DISP_OPEN_IF, 0, 0);
1205 if (fnum2 == -1) {
1206 torture_result(tctx, TORTURE_FAIL,
1207 __location__ ": Test 6 open 2 of %s failed (%s)\n", fname, smbcli_errstr(cli2->tree));
1208 CHECK_MAX_FAILURES(error_test60);
1209 return false;
1212 torture_comment(tctx, "non-io open test #6 passed.\n");
1213 error_test60:
1215 if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum1))) {
1216 torture_comment(tctx, "Test 6 close 1 of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
1219 if (NT_STATUS_IS_ERR(smbcli_close(cli2->tree, fnum2))) {
1220 torture_comment(tctx, "Test 6 close 2 of %s failed (%s)\n", fname, smbcli_errstr(cli2->tree));
1223 torture_comment(tctx, "Test #7 testing 1 non-io open, one io open with delete\n");
1224 fnum1 = fnum2 = -1;
1225 smbcli_unlink(cli1->tree, fname);
1227 fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0, SEC_FILE_READ_DATA, FILE_ATTRIBUTE_NORMAL,
1228 NTCREATEX_SHARE_ACCESS_NONE, NTCREATEX_DISP_OVERWRITE_IF, 0, 0);
1230 if (fnum1 == -1) {
1231 torture_result(tctx, TORTURE_FAIL,
1232 __location__ ": Test 7 open 1 of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
1233 CHECK_MAX_FAILURES(error_test70);
1234 return false;
1237 fnum2 = smbcli_nt_create_full(cli2->tree, fname, 0, SEC_STD_DELETE|SEC_FILE_READ_ATTRIBUTE, FILE_ATTRIBUTE_NORMAL,
1238 NTCREATEX_SHARE_ACCESS_READ|NTCREATEX_SHARE_ACCESS_DELETE, NTCREATEX_DISP_OPEN_IF, 0, 0);
1240 if (fnum2 != -1) {
1241 torture_result(tctx, TORTURE_FAIL,
1242 __location__ ": Test 7 open 2 of %s SUCCEEDED - should have failed (%s)\n", fname, smbcli_errstr(cli2->tree));
1243 CHECK_MAX_FAILURES(error_test70);
1244 return false;
1247 torture_comment(tctx, "Test 7 open 2 of %s gave %s (correct error should be %s)\n", fname, smbcli_errstr(cli2->tree), "sharing violation");
1249 torture_comment(tctx, "non-io open test #7 passed.\n");
1250 error_test70:
1252 if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum1))) {
1253 torture_comment(tctx, "Test 7 close 1 of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
1255 if (fnum2 != -1 && NT_STATUS_IS_ERR(smbcli_close(cli2->tree, fnum2))) {
1256 torture_comment(tctx, "Test 7 close 2 of %s failed (%s)\n", fname, smbcli_errstr(cli2->tree));
1259 torture_comment(tctx, "Test #8 testing one normal open, followed by lock, followed by open with truncate\n");
1260 fnum1 = fnum2 = -1;
1261 smbcli_unlink(cli1->tree, fname);
1263 fnum1 = smbcli_open(cli1->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
1264 if (fnum1 == -1) {
1265 torture_result(tctx, TORTURE_FAIL, "(8) open (1) of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
1266 return false;
1269 /* write 20 bytes. */
1271 memset(buf, '\0', 20);
1273 if (smbcli_write(cli1->tree, fnum1, 0, buf, 0, 20) != 20) {
1274 torture_result(tctx, TORTURE_FAIL, "(8) write failed (%s)\n", smbcli_errstr(cli1->tree));
1275 correct = false;
1278 /* Ensure size == 20. */
1279 if (NT_STATUS_IS_ERR(smbcli_getatr(cli1->tree, fname, NULL, &fsize, NULL))) {
1280 torture_result(tctx, TORTURE_FAIL,
1281 __location__ ": (8) getatr (1) failed (%s)\n", smbcli_errstr(cli1->tree));
1282 CHECK_MAX_FAILURES(error_test80);
1283 return false;
1286 if (fsize != 20) {
1287 torture_result(tctx, TORTURE_FAIL,
1288 __location__ ": (8) file size %lu != 20\n", (unsigned long)fsize);
1289 CHECK_MAX_FAILURES(error_test80);
1290 return false;
1293 /* Get an exclusive lock on the open file. */
1294 if (NT_STATUS_IS_ERR(smbcli_lock(cli1->tree, fnum1, 0, 4, 0, WRITE_LOCK))) {
1295 torture_result(tctx, TORTURE_FAIL,
1296 __location__ ": (8) lock1 failed (%s)\n", smbcli_errstr(cli1->tree));
1297 CHECK_MAX_FAILURES(error_test80);
1298 return false;
1301 fnum2 = smbcli_open(cli1->tree, fname, O_RDWR|O_TRUNC, DENY_NONE);
1302 if (fnum1 == -1) {
1303 torture_result(tctx, TORTURE_FAIL, "(8) open (2) of %s with truncate failed (%s)\n", fname, smbcli_errstr(cli1->tree));
1304 return false;
1307 /* Ensure size == 0. */
1308 if (NT_STATUS_IS_ERR(smbcli_getatr(cli1->tree, fname, NULL, &fsize, NULL))) {
1309 torture_result(tctx, TORTURE_FAIL,
1310 __location__ ": (8) getatr (2) failed (%s)\n", smbcli_errstr(cli1->tree));
1311 CHECK_MAX_FAILURES(error_test80);
1312 return false;
1315 if (fsize != 0) {
1316 torture_result(tctx, TORTURE_FAIL,
1317 __location__ ": (8) file size %lu != 0\n", (unsigned long)fsize);
1318 CHECK_MAX_FAILURES(error_test80);
1319 return false;
1322 if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum1))) {
1323 torture_result(tctx, TORTURE_FAIL, "(8) close1 failed (%s)\n", smbcli_errstr(cli1->tree));
1324 return false;
1327 if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum2))) {
1328 torture_result(tctx, TORTURE_FAIL, "(8) close1 failed (%s)\n", smbcli_errstr(cli1->tree));
1329 return false;
1332 error_test80:
1334 torture_comment(tctx, "open test #8 passed.\n");
1336 smbcli_unlink(cli1->tree, fname);
1338 return failures > 0 ? false : correct;
1341 /* FIRST_DESIRED_ACCESS 0xf019f */
1342 #define FIRST_DESIRED_ACCESS SEC_FILE_READ_DATA|SEC_FILE_WRITE_DATA|SEC_FILE_APPEND_DATA|\
1343 SEC_FILE_READ_EA| /* 0xf */ \
1344 SEC_FILE_WRITE_EA|SEC_FILE_READ_ATTRIBUTE| /* 0x90 */ \
1345 SEC_FILE_WRITE_ATTRIBUTE| /* 0x100 */ \
1346 SEC_STD_DELETE|SEC_STD_READ_CONTROL|\
1347 SEC_STD_WRITE_DAC|SEC_STD_WRITE_OWNER /* 0xf0000 */
1348 /* SECOND_DESIRED_ACCESS 0xe0080 */
1349 #define SECOND_DESIRED_ACCESS SEC_FILE_READ_ATTRIBUTE| /* 0x80 */ \
1350 SEC_STD_READ_CONTROL|SEC_STD_WRITE_DAC|\
1351 SEC_STD_WRITE_OWNER /* 0xe0000 */
1353 #if 0
1354 #define THIRD_DESIRED_ACCESS FILE_READ_ATTRIBUTE| /* 0x80 */ \
1355 READ_CONTROL|WRITE_DAC|\
1356 SEC_FILE_READ_DATA|\
1357 WRITE_OWNER /* */
1358 #endif
1363 Test ntcreate calls made by xcopy
1365 static bool run_xcopy(struct torture_context *tctx,
1366 struct smbcli_state *cli1)
1368 const char *fname = "\\test.txt";
1369 int fnum1, fnum2;
1371 fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0,
1372 FIRST_DESIRED_ACCESS,
1373 FILE_ATTRIBUTE_ARCHIVE,
1374 NTCREATEX_SHARE_ACCESS_NONE,
1375 NTCREATEX_DISP_OVERWRITE_IF,
1376 0x4044, 0);
1378 torture_assert(tctx, fnum1 != -1, talloc_asprintf(tctx,
1379 "First open failed - %s", smbcli_errstr(cli1->tree)));
1381 fnum2 = smbcli_nt_create_full(cli1->tree, fname, 0,
1382 SECOND_DESIRED_ACCESS, 0,
1383 NTCREATEX_SHARE_ACCESS_READ|NTCREATEX_SHARE_ACCESS_WRITE|NTCREATEX_SHARE_ACCESS_DELETE, NTCREATEX_DISP_OPEN,
1384 0x200000, 0);
1385 torture_assert(tctx, fnum2 != -1, talloc_asprintf(tctx,
1386 "second open failed - %s", smbcli_errstr(cli1->tree)));
1388 return true;
1391 static bool run_iometer(struct torture_context *tctx,
1392 struct smbcli_state *cli)
1394 const char *fname = "\\iobw.tst";
1395 int fnum;
1396 size_t filesize;
1397 NTSTATUS status;
1398 char buf[2048];
1399 int ops;
1401 memset(buf, 0, sizeof(buf));
1403 status = smbcli_getatr(cli->tree, fname, NULL, &filesize, NULL);
1404 torture_assert_ntstatus_ok(tctx, status,
1405 talloc_asprintf(tctx, "smbcli_getatr failed: %s", nt_errstr(status)));
1407 torture_comment(tctx, "size: %d\n", (int)filesize);
1409 filesize -= (sizeof(buf) - 1);
1411 fnum = smbcli_nt_create_full(cli->tree, fname, 0x16,
1412 0x2019f, 0, 0x3, 3, 0x42, 0x3);
1413 torture_assert(tctx, fnum != -1, talloc_asprintf(tctx, "open failed: %s",
1414 smbcli_errstr(cli->tree)));
1416 ops = 0;
1418 while (true) {
1419 int i, num_reads, num_writes;
1421 num_reads = random() % 10;
1422 num_writes = random() % 3;
1424 for (i=0; i<num_reads; i++) {
1425 ssize_t res;
1426 if (ops++ > torture_numops) {
1427 return true;
1429 res = smbcli_read(cli->tree, fnum, buf,
1430 random() % filesize, sizeof(buf));
1431 torture_assert(tctx, res == sizeof(buf),
1432 talloc_asprintf(tctx, "read failed: %s",
1433 smbcli_errstr(cli->tree)));
1435 for (i=0; i<num_writes; i++) {
1436 ssize_t res;
1437 if (ops++ > torture_numops) {
1438 return true;
1440 res = smbcli_write(cli->tree, fnum, 0, buf,
1441 random() % filesize, sizeof(buf));
1442 torture_assert(tctx, res == sizeof(buf),
1443 talloc_asprintf(tctx, "read failed: %s",
1444 smbcli_errstr(cli->tree)));
1450 tries variants of chkpath
1452 static bool torture_chkpath_test(struct torture_context *tctx,
1453 struct smbcli_state *cli)
1455 int fnum;
1456 bool ret;
1458 torture_comment(tctx, "Testing valid and invalid paths\n");
1460 /* cleanup from an old run */
1461 smbcli_rmdir(cli->tree, "\\chkpath.dir\\dir2");
1462 smbcli_unlink(cli->tree, "\\chkpath.dir\\*");
1463 smbcli_rmdir(cli->tree, "\\chkpath.dir");
1465 if (NT_STATUS_IS_ERR(smbcli_mkdir(cli->tree, "\\chkpath.dir"))) {
1466 torture_result(tctx, TORTURE_FAIL, "mkdir1 failed : %s\n", smbcli_errstr(cli->tree));
1467 return false;
1470 if (NT_STATUS_IS_ERR(smbcli_mkdir(cli->tree, "\\chkpath.dir\\dir2"))) {
1471 torture_result(tctx, TORTURE_FAIL, "mkdir2 failed : %s\n", smbcli_errstr(cli->tree));
1472 return false;
1475 fnum = smbcli_open(cli->tree, "\\chkpath.dir\\foo.txt", O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
1476 if (fnum == -1) {
1477 torture_result(tctx, TORTURE_FAIL, "open1 failed (%s)\n", smbcli_errstr(cli->tree));
1478 return false;
1480 smbcli_close(cli->tree, fnum);
1482 if (NT_STATUS_IS_ERR(smbcli_chkpath(cli->tree, "\\chkpath.dir"))) {
1483 torture_result(tctx, TORTURE_FAIL, "chkpath1 failed: %s\n", smbcli_errstr(cli->tree));
1484 ret = false;
1487 if (NT_STATUS_IS_ERR(smbcli_chkpath(cli->tree, "\\chkpath.dir\\dir2"))) {
1488 torture_result(tctx, TORTURE_FAIL, "chkpath2 failed: %s\n", smbcli_errstr(cli->tree));
1489 ret = false;
1492 if (NT_STATUS_IS_ERR(smbcli_chkpath(cli->tree, "\\chkpath.dir\\foo.txt"))) {
1493 ret = check_error(__location__, cli, ERRDOS, ERRbadpath,
1494 NT_STATUS_NOT_A_DIRECTORY);
1495 } else {
1496 torture_result(tctx, TORTURE_FAIL, "* chkpath on a file should fail\n");
1497 ret = false;
1500 if (NT_STATUS_IS_ERR(smbcli_chkpath(cli->tree, "\\chkpath.dir\\bar.txt"))) {
1501 ret = check_error(__location__, cli, ERRDOS, ERRbadpath,
1502 NT_STATUS_OBJECT_NAME_NOT_FOUND);
1503 } else {
1504 torture_result(tctx, TORTURE_FAIL, "* chkpath on a non existent file should fail\n");
1505 ret = false;
1508 if (NT_STATUS_IS_ERR(smbcli_chkpath(cli->tree, "\\chkpath.dir\\dirxx\\bar.txt"))) {
1509 ret = check_error(__location__, cli, ERRDOS, ERRbadpath,
1510 NT_STATUS_OBJECT_PATH_NOT_FOUND);
1511 } else {
1512 torture_result(tctx, TORTURE_FAIL, "* chkpath on a non existent component should fail\n");
1513 ret = false;
1516 smbcli_rmdir(cli->tree, "\\chkpath.dir\\dir2");
1517 smbcli_unlink(cli->tree, "\\chkpath.dir\\*");
1518 smbcli_rmdir(cli->tree, "\\chkpath.dir");
1520 return ret;
1524 * This is a test to excercise some weird Samba3 error paths.
1527 static bool torture_samba3_errorpaths(struct torture_context *tctx)
1529 bool nt_status_support;
1530 struct smbcli_state *cli_nt = NULL, *cli_dos = NULL;
1531 bool result = false;
1532 int fnum;
1533 const char *os2_fname = ".+,;=[].";
1534 const char *dname = "samba3_errordir";
1535 union smb_open io;
1536 NTSTATUS status;
1538 nt_status_support = lpcfg_nt_status_support(tctx->lp_ctx);
1540 if (!lpcfg_set_cmdline(tctx->lp_ctx, "nt status support", "yes")) {
1541 torture_result(tctx, TORTURE_FAIL, "Could not set 'nt status support = yes'\n");
1542 goto fail;
1545 if (!torture_open_connection(&cli_nt, tctx, 0)) {
1546 goto fail;
1549 if (!lpcfg_set_cmdline(tctx->lp_ctx, "nt status support", "no")) {
1550 torture_result(tctx, TORTURE_FAIL, "Could not set 'nt status support = yes'\n");
1551 goto fail;
1554 if (!torture_open_connection(&cli_dos, tctx, 1)) {
1555 goto fail;
1558 if (!lpcfg_set_cmdline(tctx->lp_ctx, "nt status support",
1559 nt_status_support ? "yes":"no")) {
1560 torture_result(tctx, TORTURE_FAIL, "Could not reset 'nt status support = yes'");
1561 goto fail;
1564 smbcli_unlink(cli_nt->tree, os2_fname);
1565 smbcli_rmdir(cli_nt->tree, dname);
1567 if (!NT_STATUS_IS_OK(smbcli_mkdir(cli_nt->tree, dname))) {
1568 torture_result(tctx, TORTURE_FAIL, "smbcli_mkdir(%s) failed: %s\n", dname,
1569 smbcli_errstr(cli_nt->tree));
1570 goto fail;
1573 io.generic.level = RAW_OPEN_NTCREATEX;
1574 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED;
1575 io.ntcreatex.in.root_fid.fnum = 0;
1576 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
1577 io.ntcreatex.in.alloc_size = 1024*1024;
1578 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_DIRECTORY;
1579 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
1580 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
1581 io.ntcreatex.in.create_options = 0;
1582 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
1583 io.ntcreatex.in.security_flags = 0;
1584 io.ntcreatex.in.fname = dname;
1586 status = smb_raw_open(cli_nt->tree, tctx, &io);
1587 if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_COLLISION)) {
1588 torture_result(tctx, TORTURE_FAIL, "(%s) incorrect status %s should be %s\n",
1589 __location__, nt_errstr(status),
1590 nt_errstr(NT_STATUS_OBJECT_NAME_COLLISION));
1591 goto fail;
1593 status = smb_raw_open(cli_dos->tree, tctx, &io);
1594 if (!NT_STATUS_EQUAL(status, NT_STATUS_DOS(ERRDOS, ERRfilexists))) {
1595 torture_result(tctx, TORTURE_FAIL, "(%s) incorrect status %s should be %s\n",
1596 __location__, nt_errstr(status),
1597 nt_errstr(NT_STATUS_DOS(ERRDOS, ERRfilexists)));
1598 goto fail;
1601 status = smbcli_mkdir(cli_nt->tree, dname);
1602 if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_COLLISION)) {
1603 torture_result(tctx, TORTURE_FAIL, "(%s) incorrect status %s should be %s\n",
1604 __location__, nt_errstr(status),
1605 nt_errstr(NT_STATUS_OBJECT_NAME_COLLISION));
1606 goto fail;
1608 status = smbcli_mkdir(cli_dos->tree, dname);
1609 if (!NT_STATUS_EQUAL(status, NT_STATUS_DOS(ERRDOS, ERRnoaccess))) {
1610 torture_result(tctx, TORTURE_FAIL, "(%s) incorrect status %s should be %s\n",
1611 __location__, nt_errstr(status),
1612 nt_errstr(NT_STATUS_DOS(ERRDOS, ERRnoaccess)));
1613 goto fail;
1617 union smb_mkdir md;
1618 md.t2mkdir.level = RAW_MKDIR_T2MKDIR;
1619 md.t2mkdir.in.path = dname;
1620 md.t2mkdir.in.num_eas = 0;
1621 md.t2mkdir.in.eas = NULL;
1623 status = smb_raw_mkdir(cli_nt->tree, &md);
1624 if (!NT_STATUS_EQUAL(status,
1625 NT_STATUS_OBJECT_NAME_COLLISION)) {
1626 torture_comment(
1627 tctx, "(%s) incorrect status %s should be "
1628 "NT_STATUS_OBJECT_NAME_COLLISION\n",
1629 __location__, nt_errstr(status));
1630 goto fail;
1632 status = smb_raw_mkdir(cli_dos->tree, &md);
1633 if (!NT_STATUS_EQUAL(status,
1634 NT_STATUS_DOS(ERRDOS, ERRrename))) {
1635 torture_result(tctx, TORTURE_FAIL, "(%s) incorrect status %s "
1636 "should be ERRDOS:ERRrename\n",
1637 __location__, nt_errstr(status));
1638 goto fail;
1642 io.ntcreatex.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
1643 status = smb_raw_open(cli_nt->tree, tctx, &io);
1644 if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_COLLISION)) {
1645 torture_result(tctx, TORTURE_FAIL, "(%s) incorrect status %s should be %s\n",
1646 __location__, nt_errstr(status),
1647 nt_errstr(NT_STATUS_OBJECT_NAME_COLLISION));
1648 goto fail;
1651 status = smb_raw_open(cli_dos->tree, tctx, &io);
1652 if (!NT_STATUS_EQUAL(status, NT_STATUS_DOS(ERRDOS, ERRfilexists))) {
1653 torture_result(tctx, TORTURE_FAIL, "(%s) incorrect status %s should be %s\n",
1654 __location__, nt_errstr(status),
1655 nt_errstr(NT_STATUS_DOS(ERRDOS, ERRfilexists)));
1656 goto fail;
1660 /* Test an invalid DOS deny mode */
1661 const char *fname = "test.txt";
1663 fnum = smbcli_open(cli_nt->tree, fname, O_RDWR | O_CREAT, 5);
1664 if (fnum != -1) {
1665 torture_result(tctx, TORTURE_FAIL, "Open(%s) with invalid deny mode succeeded -- "
1666 "expected failure\n", fname);
1667 smbcli_close(cli_nt->tree, fnum);
1668 goto fail;
1670 if (!NT_STATUS_EQUAL(smbcli_nt_error(cli_nt->tree),
1671 NT_STATUS_DOS(ERRDOS,ERRbadaccess))) {
1672 torture_result(tctx, TORTURE_FAIL, "Expected DOS error ERRDOS/ERRbadaccess, "
1673 "got %s\n", smbcli_errstr(cli_nt->tree));
1674 goto fail;
1677 fnum = smbcli_open(cli_dos->tree, fname, O_RDWR | O_CREAT, 5);
1678 if (fnum != -1) {
1679 torture_result(tctx, TORTURE_FAIL, "Open(%s) with invalid deny mode succeeded -- "
1680 "expected failure\n", fname);
1681 smbcli_close(cli_nt->tree, fnum);
1682 goto fail;
1684 if (!NT_STATUS_EQUAL(smbcli_nt_error(cli_nt->tree),
1685 NT_STATUS_DOS(ERRDOS,ERRbadaccess))) {
1686 torture_result(tctx, TORTURE_FAIL, "Expected DOS error ERRDOS:ERRbadaccess, "
1687 "got %s\n", smbcli_errstr(cli_nt->tree));
1688 goto fail;
1694 * Samba 3.0.23 has a bug that an existing file can be opened
1695 * as a directory using ntcreate&x. Test this.
1698 const char *fname = "\\test_dir.txt";
1700 fnum = smbcli_open(cli_nt->tree, fname, O_RDWR|O_CREAT,
1701 DENY_NONE);
1702 if (fnum == -1) {
1703 d_printf("(%s) smbcli_open failed: %s\n", __location__,
1704 smbcli_errstr(cli_nt->tree));
1706 smbcli_close(cli_nt->tree, fnum);
1708 io.generic.level = RAW_OPEN_NTCREATEX;
1709 io.ntcreatex.in.root_fid.fnum = 0;
1710 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
1711 io.ntcreatex.in.alloc_size = 0;
1712 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_DIRECTORY;
1713 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
1714 NTCREATEX_SHARE_ACCESS_WRITE|
1715 NTCREATEX_SHARE_ACCESS_DELETE;
1716 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN;
1717 io.ntcreatex.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
1718 io.ntcreatex.in.impersonation =
1719 NTCREATEX_IMPERSONATION_ANONYMOUS;
1720 io.ntcreatex.in.security_flags = 0;
1721 io.ntcreatex.in.fname = fname;
1722 io.ntcreatex.in.flags = 0;
1724 status = smb_raw_open(cli_nt->tree, tctx, &io);
1725 if (!NT_STATUS_EQUAL(status, NT_STATUS_NOT_A_DIRECTORY)) {
1726 torture_result(tctx, TORTURE_FAIL, "ntcreate as dir gave %s, "
1727 "expected NT_STATUS_NOT_A_DIRECTORY\n",
1728 nt_errstr(status));
1729 result = false;
1732 if (NT_STATUS_IS_OK(status)) {
1733 smbcli_close(cli_nt->tree, io.ntcreatex.out.file.fnum);
1736 status = smb_raw_open(cli_dos->tree, tctx, &io);
1737 if (!NT_STATUS_EQUAL(status, NT_STATUS_DOS(ERRDOS,
1738 ERRbaddirectory))) {
1739 torture_result(tctx, TORTURE_FAIL, "ntcreate as dir gave %s, "
1740 "expected NT_STATUS_NOT_A_DIRECTORY\n",
1741 nt_errstr(status));
1742 result = false;
1745 if (NT_STATUS_IS_OK(status)) {
1746 smbcli_close(cli_dos->tree,
1747 io.ntcreatex.out.file.fnum);
1750 smbcli_unlink(cli_nt->tree, fname);
1753 if (!torture_setting_bool(tctx, "samba3", false)) {
1754 goto done;
1757 fnum = smbcli_open(cli_dos->tree, os2_fname,
1758 O_RDWR | O_CREAT | O_TRUNC,
1759 DENY_NONE);
1760 if (fnum != -1) {
1761 torture_result(tctx, TORTURE_FAIL, "Open(%s) succeeded -- expected failure\n",
1762 os2_fname);
1763 smbcli_close(cli_dos->tree, fnum);
1764 goto fail;
1767 if (!NT_STATUS_EQUAL(smbcli_nt_error(cli_dos->tree),
1768 NT_STATUS_DOS(ERRDOS, ERRcannotopen))) {
1769 torture_result(tctx, TORTURE_FAIL, "Expected DOS error ERRDOS/ERRcannotopen, got %s\n",
1770 smbcli_errstr(cli_dos->tree));
1771 goto fail;
1774 fnum = smbcli_open(cli_nt->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_nt->tree, fnum);
1781 goto fail;
1784 if (!NT_STATUS_EQUAL(smbcli_nt_error(cli_nt->tree),
1785 NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
1786 torture_result(tctx, TORTURE_FAIL, "Expected error NT_STATUS_OBJECT_NAME_NOT_FOUND, "
1787 "got %s\n", smbcli_errstr(cli_nt->tree));
1788 goto fail;
1791 done:
1792 result = true;
1794 fail:
1795 if (cli_dos != NULL) {
1796 torture_close_connection(cli_dos);
1798 if (cli_nt != NULL) {
1799 torture_close_connection(cli_nt);
1802 return result;
1806 This checks file/dir birthtime
1808 static void list_fn(struct clilist_file_info *finfo, const char *name,
1809 void *state){
1811 /* Just to change dir access time*/
1812 sleep(5);
1816 static bool run_birthtimetest(struct torture_context *tctx,
1817 struct smbcli_state *cli)
1819 int fnum;
1820 size_t size;
1821 time_t c_time, a_time, m_time, w_time, c_time1;
1822 const char *fname = "\\birthtime.tst";
1823 const char *dname = "\\birthtime";
1824 const char *fname2 = "\\birthtime\\birthtime.tst";
1825 bool correct = true;
1826 uint8_t buf[16];
1829 smbcli_unlink(cli->tree, fname);
1831 torture_comment(tctx, "Testing Birthtime for File\n");
1833 /* Save File birthtime/creationtime */
1834 fnum = smbcli_open(cli->tree, fname, O_RDWR | O_CREAT | O_TRUNC,
1835 DENY_NONE);
1836 if (NT_STATUS_IS_ERR(smbcli_qfileinfo(cli->tree, fnum, NULL, &size,
1837 &c_time, &a_time, &m_time, NULL, NULL))) {
1838 torture_result(tctx, TORTURE_FAIL, "ERROR: qfileinfo failed (%s)\n",
1839 smbcli_errstr(cli->tree));
1840 correct = false;
1842 smbcli_close(cli->tree, fnum);
1844 sleep(10);
1846 /* Change in File attribute changes file change time*/
1847 smbcli_setatr(cli->tree, fname, FILE_ATTRIBUTE_SYSTEM, 0);
1849 fnum = smbcli_open(cli->tree, fname, O_RDWR | O_CREAT , DENY_NONE);
1850 /* Writing updates modification time*/
1851 smbcli_smbwrite(cli->tree, fnum, &fname, 0, sizeof(fname));
1852 /*Reading updates access time */
1853 smbcli_read(cli->tree, fnum, buf, 0, 13);
1854 smbcli_close(cli->tree, fnum);
1856 if (NT_STATUS_IS_ERR(smbcli_qpathinfo2(cli->tree, fname, &c_time1,
1857 &a_time, &m_time, &w_time, &size, NULL, NULL))) {
1858 torture_result(tctx, TORTURE_FAIL, "ERROR: qpathinfo2 failed (%s)\n",
1859 smbcli_errstr(cli->tree));
1860 correct = false;
1861 } else {
1862 fprintf(stdout, "c_time = %li, c_time1 = %li\n",
1863 (long) c_time, (long) c_time1);
1864 if (c_time1 != c_time) {
1865 torture_result(tctx, TORTURE_FAIL, "This system updated file \
1866 birth times! Not expected!\n");
1867 correct = false;
1870 smbcli_unlink(cli->tree, fname);
1872 torture_comment(tctx, "Testing Birthtime for Directory\n");
1874 /* check if the server does not update the directory birth time
1875 when creating a new file */
1876 if (NT_STATUS_IS_ERR(smbcli_mkdir(cli->tree, dname))) {
1877 torture_result(tctx, TORTURE_FAIL, "ERROR: mkdir failed (%s)\n",
1878 smbcli_errstr(cli->tree));
1879 correct = false;
1881 sleep(3);
1882 if (NT_STATUS_IS_ERR(smbcli_qpathinfo2(cli->tree, "\\birthtime\\",
1883 &c_time,&a_time,&m_time,&w_time, &size, NULL, NULL))){
1884 torture_result(tctx, TORTURE_FAIL, "ERROR: qpathinfo2 failed (%s)\n",
1885 smbcli_errstr(cli->tree));
1886 correct = false;
1889 /* Creating a new file changes dir modification time and change time*/
1890 smbcli_unlink(cli->tree, fname2);
1891 fnum = smbcli_open(cli->tree, fname2, O_RDWR | O_CREAT | O_TRUNC,
1892 DENY_NONE);
1893 smbcli_smbwrite(cli->tree, fnum, &fnum, 0, sizeof(fnum));
1894 smbcli_read(cli->tree, fnum, buf, 0, 13);
1895 smbcli_close(cli->tree, fnum);
1897 /* dir listing changes dir access time*/
1898 smbcli_list(cli->tree, "\\birthtime\\*", 0, list_fn, cli );
1900 if (NT_STATUS_IS_ERR(smbcli_qpathinfo2(cli->tree, "\\birthtime\\",
1901 &c_time1, &a_time, &m_time,&w_time,&size,NULL,NULL))){
1902 torture_result(tctx, TORTURE_FAIL, "ERROR: qpathinfo2 failed (%s)\n",
1903 smbcli_errstr(cli->tree));
1904 correct = false;
1905 } else {
1906 fprintf(stdout, "c_time = %li, c_time1 = %li\n",
1907 (long) c_time, (long) c_time1);
1908 if (c_time1 != c_time) {
1909 torture_result(tctx, TORTURE_FAIL, "This system updated directory \
1910 birth times! Not Expected!\n");
1911 correct = false;
1914 smbcli_unlink(cli->tree, fname2);
1915 smbcli_rmdir(cli->tree, dname);
1917 return correct;
1921 NTSTATUS torture_base_init(void)
1923 struct torture_suite *suite = torture_suite_create(talloc_autofree_context(), "base");
1925 torture_suite_add_2smb_test(suite, "fdpass", run_fdpasstest);
1926 torture_suite_add_suite(suite, torture_base_locktest(suite));
1927 torture_suite_add_1smb_test(suite, "unlink", torture_unlinktest);
1928 torture_suite_add_1smb_test(suite, "attr", run_attrtest);
1929 torture_suite_add_1smb_test(suite, "trans2", run_trans2test);
1930 torture_suite_add_1smb_test(suite, "birthtime", run_birthtimetest);
1931 torture_suite_add_simple_test(suite, "negnowait", run_negprot_nowait);
1932 torture_suite_add_1smb_test(suite, "dir1", torture_dirtest1);
1933 torture_suite_add_1smb_test(suite, "dir2", torture_dirtest2);
1934 torture_suite_add_1smb_test(suite, "deny1", torture_denytest1);
1935 torture_suite_add_2smb_test(suite, "deny2", torture_denytest2);
1936 torture_suite_add_2smb_test(suite, "deny3", torture_denytest3);
1937 torture_suite_add_1smb_test(suite, "denydos", torture_denydos_sharing);
1938 torture_suite_add_smb_multi_test(suite, "ntdeny1", torture_ntdenytest1);
1939 torture_suite_add_2smb_test(suite, "ntdeny2", torture_ntdenytest2);
1940 torture_suite_add_1smb_test(suite, "tcon", run_tcon_test);
1941 torture_suite_add_1smb_test(suite, "tcondev", run_tcon_devtype_test);
1942 torture_suite_add_1smb_test(suite, "vuid", run_vuidtest);
1943 torture_suite_add_2smb_test(suite, "rw1", run_readwritetest);
1944 torture_suite_add_2smb_test(suite, "open", run_opentest);
1945 torture_suite_add_smb_multi_test(suite, "defer_open", run_deferopen);
1946 torture_suite_add_1smb_test(suite, "xcopy", run_xcopy);
1947 torture_suite_add_1smb_test(suite, "iometer", run_iometer);
1948 torture_suite_add_1smb_test(suite, "rename", torture_test_rename);
1949 torture_suite_add_suite(suite, torture_test_delete());
1950 torture_suite_add_1smb_test(suite, "properties", torture_test_properties);
1951 torture_suite_add_1smb_test(suite, "mangle", torture_mangle);
1952 torture_suite_add_1smb_test(suite, "openattr", torture_openattrtest);
1953 torture_suite_add_1smb_test(suite, "winattr", torture_winattrtest);
1954 torture_suite_add_suite(suite, torture_charset(suite));
1955 torture_suite_add_1smb_test(suite, "chkpath", torture_chkpath_test);
1956 torture_suite_add_1smb_test(suite, "secleak", torture_sec_leak);
1957 torture_suite_add_simple_test(suite, "disconnect", torture_disconnect);
1958 torture_suite_add_suite(suite, torture_delay_write());
1959 torture_suite_add_simple_test(suite, "samba3error", torture_samba3_errorpaths);
1960 torture_suite_add_1smb_test(suite, "casetable", torture_casetable);
1961 torture_suite_add_1smb_test(suite, "utable", torture_utable);
1962 torture_suite_add_simple_test(suite, "smb", torture_smb_scan);
1963 torture_suite_add_suite(suite, torture_trans2_aliases(suite));
1964 torture_suite_add_1smb_test(suite, "trans2-scan", torture_trans2_scan);
1965 torture_suite_add_1smb_test(suite, "nttrans", torture_nttrans_scan);
1966 torture_suite_add_1smb_test(suite, "createx_access", torture_createx_access);
1967 torture_suite_add_2smb_test(suite, "createx_sharemodes_file", torture_createx_sharemodes_file);
1968 torture_suite_add_2smb_test(suite, "createx_sharemodes_dir", torture_createx_sharemodes_dir);
1969 torture_suite_add_1smb_test(suite, "maximum_allowed", torture_maximum_allowed);
1971 torture_suite_add_simple_test(suite, "bench-holdcon", torture_holdcon);
1972 torture_suite_add_1smb_test(suite, "bench-holdopen", torture_holdopen);
1973 torture_suite_add_simple_test(suite, "bench-readwrite", run_benchrw);
1974 torture_suite_add_smb_multi_test(suite, "bench-torture", run_torture);
1975 torture_suite_add_1smb_test(suite, "scan-pipe_number", run_pipe_number);
1976 torture_suite_add_1smb_test(suite, "scan-ioctl", torture_ioctl_test);
1977 torture_suite_add_1smb_test(suite, "scan-maxfid", torture_maxfid_test);
1979 suite->description = talloc_strdup(suite,
1980 "Basic SMB tests (imported from the original smbtorture)");
1982 torture_register_suite(suite);
1984 return NT_STATUS_OK;