2 Unix SMB/CIFS implementation.
4 Copyright (C) Andrew Tridgell 1997-2003
5 Copyright (C) Jelmer Vernooij 2006
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 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, write to the Free Software
19 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 #include "lib/cmdline/popt_common.h"
24 #include "libcli/raw/libcliraw.h"
25 #include "system/time.h"
26 #include "system/wait.h"
27 #include "system/filesys.h"
28 #include "libcli/raw/ioctl.h"
29 #include "libcli/libcli.h"
30 #include "lib/ldb/include/ldb.h"
31 #include "lib/events/events.h"
32 #include "libcli/resolve/resolve.h"
33 #include "auth/credentials/credentials.h"
34 #include "librpc/rpc/dcerpc_table.h"
35 #include "libcli/ldap/ldap_client.h"
36 #include "librpc/gen_ndr/ndr_nbt.h"
38 #include "torture/basic/proto.h"
39 #include "torture/raw/proto.h"
40 #include "torture/smb2/proto.h"
41 #include "torture/rap/proto.h"
42 #include "torture/auth/proto.h"
43 #include "torture/local/proto.h"
44 #include "torture/nbench/proto.h"
45 #include "torture/ldap/proto.h"
46 #include "torture/com/proto.h"
47 #include "torture/nbt/proto.h"
48 #include "torture/libnet/proto.h"
49 #include "torture/torture.h"
51 #include "dlinklist.h"
54 int torture_numops=10;
55 int torture_entries=1000;
56 int torture_failures=1;
58 static int procnum; /* records process count number when forking */
59 static struct smbcli_state *current_cli;
60 static BOOL use_oplocks;
61 static BOOL use_level_II_oplocks;
62 #define MAX_COLS 80 /* FIXME: Determine this at run-time */
64 BOOL torture_showall = False;
66 #define CHECK_MAX_FAILURES(label) do { if (++failures >= torture_failures) goto label; } while (0)
68 static struct smbcli_state *open_nbt_connection(void)
70 struct nbt_name called, calling;
71 struct smbcli_state *cli;
72 const char *host = lp_parm_string(-1, "torture", "host");
74 make_nbt_name_client(&calling, lp_netbios_name());
76 nbt_choose_called_name(NULL, &called, host, NBT_NAME_SERVER);
78 cli = smbcli_state_init(NULL);
80 printf("Failed initialize smbcli_struct to connect with %s\n", host);
84 if (!smbcli_socket_connect(cli, host)) {
85 printf("Failed to connect with %s\n", host);
89 if (!smbcli_transport_establish(cli, &calling, &called)) {
90 printf("%s rejected the session\n",host);
101 BOOL torture_open_connection_share(TALLOC_CTX *mem_ctx,
102 struct smbcli_state **c,
103 const char *hostname,
104 const char *sharename,
105 struct event_context *ev)
109 status = smbcli_full_connection(mem_ctx, c, hostname,
111 cmdline_credentials, ev);
112 if (!NT_STATUS_IS_OK(status)) {
113 printf("Failed to open connection - %s\n", nt_errstr(status));
117 (*c)->transport->options.use_oplocks = use_oplocks;
118 (*c)->transport->options.use_level2_oplocks = use_level_II_oplocks;
123 BOOL torture_open_connection(struct smbcli_state **c)
125 const char *host = lp_parm_string(-1, "torture", "host");
126 const char *share = lp_parm_string(-1, "torture", "share");
128 return torture_open_connection_share(NULL, c, host, share, NULL);
133 BOOL torture_close_connection(struct smbcli_state *c)
137 if (NT_STATUS_IS_ERR(smbcli_tdis(c))) {
138 printf("tdis failed (%s)\n", smbcli_errstr(c->tree));
146 /* check if the server produced the expected error code */
147 BOOL check_error(const char *location, struct smbcli_state *c,
148 uint8_t eclass, uint32_t ecode, NTSTATUS nterr)
152 status = smbcli_nt_error(c->tree);
153 if (NT_STATUS_IS_DOS(status)) {
155 class = NT_STATUS_DOS_CLASS(status);
156 num = NT_STATUS_DOS_CODE(status);
157 if (eclass != class || ecode != num) {
158 printf("unexpected error code %s\n", nt_errstr(status));
159 printf(" expected %s or %s (at %s)\n",
160 nt_errstr(NT_STATUS_DOS(eclass, ecode)),
161 nt_errstr(nterr), location);
165 if (!NT_STATUS_EQUAL(nterr, status)) {
166 printf("unexpected error code %s\n", nt_errstr(status));
167 printf(" expected %s (at %s)\n", nt_errstr(nterr), location);
176 static BOOL wait_lock(struct smbcli_state *c, int fnum, uint32_t offset, uint32_t len)
178 while (NT_STATUS_IS_ERR(smbcli_lock(c->tree, fnum, offset, len, -1, WRITE_LOCK))) {
179 if (!check_error(__location__, c, ERRDOS, ERRlock, NT_STATUS_LOCK_NOT_GRANTED)) return False;
185 static BOOL rw_torture(struct smbcli_state *c)
187 const char *lockfname = "\\torture.lck";
191 pid_t pid2, pid = getpid();
196 fnum2 = smbcli_open(c->tree, lockfname, O_RDWR | O_CREAT | O_EXCL,
199 fnum2 = smbcli_open(c->tree, lockfname, O_RDWR, DENY_NONE);
201 printf("open of %s failed (%s)\n", lockfname, smbcli_errstr(c->tree));
206 for (i=0;i<torture_numops;i++) {
207 uint_t n = (uint_t)random()%10;
209 printf("%d\r", i); fflush(stdout);
211 asprintf(&fname, "\\torture.%u", n);
213 if (!wait_lock(c, fnum2, n*sizeof(int), sizeof(int))) {
217 fnum = smbcli_open(c->tree, fname, O_RDWR | O_CREAT | O_TRUNC, DENY_ALL);
219 printf("open failed (%s)\n", smbcli_errstr(c->tree));
224 if (smbcli_write(c->tree, fnum, 0, &pid, 0, sizeof(pid)) != sizeof(pid)) {
225 printf("write failed (%s)\n", smbcli_errstr(c->tree));
230 if (smbcli_write(c->tree, fnum, 0, buf,
231 sizeof(pid)+(j*sizeof(buf)),
232 sizeof(buf)) != sizeof(buf)) {
233 printf("write failed (%s)\n", smbcli_errstr(c->tree));
240 if (smbcli_read(c->tree, fnum, &pid2, 0, sizeof(pid)) != sizeof(pid)) {
241 printf("read failed (%s)\n", smbcli_errstr(c->tree));
246 printf("data corruption!\n");
250 if (NT_STATUS_IS_ERR(smbcli_close(c->tree, fnum))) {
251 printf("close failed (%s)\n", smbcli_errstr(c->tree));
255 if (NT_STATUS_IS_ERR(smbcli_unlink(c->tree, fname))) {
256 printf("unlink failed (%s)\n", smbcli_errstr(c->tree));
260 if (NT_STATUS_IS_ERR(smbcli_unlock(c->tree, fnum2, n*sizeof(int), sizeof(int)))) {
261 printf("unlock failed (%s)\n", smbcli_errstr(c->tree));
267 smbcli_close(c->tree, fnum2);
268 smbcli_unlink(c->tree, lockfname);
275 static BOOL run_torture(struct smbcli_state *cli, int dummy)
279 ret = rw_torture(cli);
281 if (!torture_close_connection(cli)) {
289 static BOOL rw_torture2(struct smbcli_state *c1, struct smbcli_state *c2)
291 const char *lockfname = "\\torture2.lck";
296 uint8_t buf_rd[131072];
298 ssize_t bytes_read, bytes_written;
300 if (smbcli_deltree(c1->tree, lockfname) == -1) {
301 printf("unlink failed (%s)\n", smbcli_errstr(c1->tree));
304 fnum1 = smbcli_open(c1->tree, lockfname, O_RDWR | O_CREAT | O_EXCL,
307 printf("first open read/write of %s failed (%s)\n",
308 lockfname, smbcli_errstr(c1->tree));
311 fnum2 = smbcli_open(c2->tree, lockfname, O_RDONLY,
314 printf("second open read-only of %s failed (%s)\n",
315 lockfname, smbcli_errstr(c2->tree));
316 smbcli_close(c1->tree, fnum1);
320 printf("Checking data integrity over %d ops\n", torture_numops);
322 for (i=0;i<torture_numops;i++)
324 size_t buf_size = ((uint_t)random()%(sizeof(buf)-1))+ 1;
326 printf("%d\r", i); fflush(stdout);
329 generate_random_buffer(buf, buf_size);
331 if ((bytes_written = smbcli_write(c1->tree, fnum1, 0, buf, 0, buf_size)) != buf_size) {
332 printf("write failed (%s)\n", smbcli_errstr(c1->tree));
333 printf("wrote %d, expected %d\n", (int)bytes_written, (int)buf_size);
338 if ((bytes_read = smbcli_read(c2->tree, fnum2, buf_rd, 0, buf_size)) != buf_size) {
339 printf("read failed (%s)\n", smbcli_errstr(c2->tree));
340 printf("read %d, expected %d\n", (int)bytes_read, (int)buf_size);
345 if (memcmp(buf_rd, buf, buf_size) != 0)
347 printf("read/write compare failed\n");
353 if (NT_STATUS_IS_ERR(smbcli_close(c2->tree, fnum2))) {
354 printf("close failed (%s)\n", smbcli_errstr(c2->tree));
357 if (NT_STATUS_IS_ERR(smbcli_close(c1->tree, fnum1))) {
358 printf("close failed (%s)\n", smbcli_errstr(c1->tree));
362 if (NT_STATUS_IS_ERR(smbcli_unlink(c1->tree, lockfname))) {
363 printf("unlink failed (%s)\n", smbcli_errstr(c1->tree));
370 #define BOOLSTR(b) ((b) ? "Yes" : "No")
372 static BOOL run_readwritetest(void)
374 struct smbcli_state *cli1, *cli2;
375 BOOL test1, test2 = True;
377 if (!torture_open_connection(&cli1) || !torture_open_connection(&cli2)) {
381 printf("starting readwritetest\n");
383 test1 = rw_torture2(cli1, cli2);
384 printf("Passed readwritetest v1: %s\n", BOOLSTR(test1));
387 test2 = rw_torture2(cli1, cli1);
388 printf("Passed readwritetest v2: %s\n", BOOLSTR(test2));
391 if (!torture_close_connection(cli1)) {
395 if (!torture_close_connection(cli2)) {
399 return (test1 && test2);
403 this checks to see if a secondary tconx can use open files from an
406 static BOOL run_tcon_test(void)
408 struct smbcli_state *cli;
409 const char *fname = "\\tcontest.tmp";
411 uint16_t cnum1, cnum2, cnum3;
412 uint16_t vuid1, vuid2;
415 struct smbcli_tree *tree1;
416 const char *host = lp_parm_string(-1, "torture", "host");
417 const char *share = lp_parm_string(-1, "torture", "share");
418 const char *password = lp_parm_string(-1, "torture", "password");
420 if (!torture_open_connection(&cli)) {
424 printf("starting tcontest\n");
426 if (smbcli_deltree(cli->tree, fname) == -1) {
427 printf("unlink of %s failed (%s)\n", fname, smbcli_errstr(cli->tree));
430 fnum1 = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
432 printf("open of %s failed (%s)\n", fname, smbcli_errstr(cli->tree));
436 cnum1 = cli->tree->tid;
437 vuid1 = cli->session->vuid;
439 memset(&buf, 0, 4); /* init buf so valgrind won't complain */
440 if (smbcli_write(cli->tree, fnum1, 0, buf, 130, 4) != 4) {
441 printf("initial write failed (%s)\n", smbcli_errstr(cli->tree));
445 tree1 = cli->tree; /* save old tree connection */
446 if (NT_STATUS_IS_ERR(smbcli_tconX(cli, share, "?????", password))) {
447 printf("%s refused 2nd tree connect (%s)\n", host,
448 smbcli_errstr(cli->tree));
453 cnum2 = cli->tree->tid;
454 cnum3 = MAX(cnum1, cnum2) + 1; /* any invalid number */
455 vuid2 = cli->session->vuid + 1;
457 /* try a write with the wrong tid */
458 cli->tree->tid = cnum2;
460 if (smbcli_write(cli->tree, fnum1, 0, buf, 130, 4) == 4) {
461 printf("* server allows write with wrong TID\n");
464 printf("server fails write with wrong TID : %s\n", smbcli_errstr(cli->tree));
468 /* try a write with an invalid tid */
469 cli->tree->tid = cnum3;
471 if (smbcli_write(cli->tree, fnum1, 0, buf, 130, 4) == 4) {
472 printf("* server allows write with invalid TID\n");
475 printf("server fails write with invalid TID : %s\n", smbcli_errstr(cli->tree));
478 /* try a write with an invalid vuid */
479 cli->session->vuid = vuid2;
480 cli->tree->tid = cnum1;
482 if (smbcli_write(cli->tree, fnum1, 0, buf, 130, 4) == 4) {
483 printf("* server allows write with invalid VUID\n");
486 printf("server fails write with invalid VUID : %s\n", smbcli_errstr(cli->tree));
489 cli->session->vuid = vuid1;
490 cli->tree->tid = cnum1;
492 if (NT_STATUS_IS_ERR(smbcli_close(cli->tree, fnum1))) {
493 printf("close failed (%s)\n", smbcli_errstr(cli->tree));
497 cli->tree->tid = cnum2;
499 if (NT_STATUS_IS_ERR(smbcli_tdis(cli))) {
500 printf("secondary tdis failed (%s)\n", smbcli_errstr(cli->tree));
504 cli->tree = tree1; /* restore initial tree */
505 cli->tree->tid = cnum1;
507 smbcli_unlink(tree1, fname);
509 if (!torture_close_connection(cli)) {
518 static BOOL tcon_devtest(struct smbcli_state *cli,
519 const char *myshare, const char *devtype,
520 NTSTATUS expected_error)
524 const char *password = lp_parm_string(-1, "torture", "password");
526 status = NT_STATUS_IS_OK(smbcli_tconX(cli, myshare, devtype,
529 printf("Trying share %s with devtype %s\n", myshare, devtype);
531 if (NT_STATUS_IS_OK(expected_error)) {
535 printf("tconX to share %s with type %s "
536 "should have succeeded but failed\n",
543 printf("tconx to share %s with type %s "
544 "should have failed but succeeded\n",
548 if (NT_STATUS_EQUAL(smbcli_nt_error(cli->tree),
552 printf("Returned unexpected error\n");
561 checks for correct tconX support
563 static BOOL run_tcon_devtype_test(void)
565 struct smbcli_state *cli1 = NULL;
568 const char *host = lp_parm_string(-1, "torture", "host");
569 const char *share = lp_parm_string(-1, "torture", "share");
571 status = smbcli_full_connection(NULL,
574 cmdline_credentials, NULL);
576 if (!NT_STATUS_IS_OK(status)) {
577 printf("could not open connection\n");
581 if (!tcon_devtest(cli1, "IPC$", "A:", NT_STATUS_BAD_DEVICE_TYPE))
584 if (!tcon_devtest(cli1, "IPC$", "?????", NT_STATUS_OK))
587 if (!tcon_devtest(cli1, "IPC$", "LPT:", NT_STATUS_BAD_DEVICE_TYPE))
590 if (!tcon_devtest(cli1, "IPC$", "IPC", NT_STATUS_OK))
593 if (!tcon_devtest(cli1, "IPC$", "FOOBA", NT_STATUS_BAD_DEVICE_TYPE))
596 if (!tcon_devtest(cli1, share, "A:", NT_STATUS_OK))
599 if (!tcon_devtest(cli1, share, "?????", NT_STATUS_OK))
602 if (!tcon_devtest(cli1, share, "LPT:", NT_STATUS_BAD_DEVICE_TYPE))
605 if (!tcon_devtest(cli1, share, "IPC", NT_STATUS_BAD_DEVICE_TYPE))
608 if (!tcon_devtest(cli1, share, "FOOBA", NT_STATUS_BAD_DEVICE_TYPE))
614 printf("Passed tcondevtest\n");
621 test whether fnums and tids open on one VC are available on another (a major
624 static BOOL run_fdpasstest(void)
626 struct smbcli_state *cli1, *cli2;
627 const char *fname = "\\fdpass.tst";
631 if (!torture_open_connection(&cli1) || !torture_open_connection(&cli2)) {
635 printf("starting fdpasstest\n");
637 smbcli_unlink(cli1->tree, fname);
639 printf("Opening a file on connection 1\n");
641 fnum1 = smbcli_open(cli1->tree, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
643 printf("open of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
647 printf("writing to file on connection 1\n");
649 if (smbcli_write(cli1->tree, fnum1, 0, "hello world\n", 0, 13) != 13) {
650 printf("write failed (%s)\n", smbcli_errstr(cli1->tree));
654 oldtid = cli2->tree->tid;
655 cli2->session->vuid = cli1->session->vuid;
656 cli2->tree->tid = cli1->tree->tid;
657 cli2->session->pid = cli1->session->pid;
659 printf("reading from file on connection 2\n");
661 if (smbcli_read(cli2->tree, fnum1, buf, 0, 13) == 13) {
662 printf("read succeeded! nasty security hole [%s]\n",
667 smbcli_close(cli1->tree, fnum1);
668 smbcli_unlink(cli1->tree, fname);
670 cli2->tree->tid = oldtid;
672 torture_close_connection(cli1);
673 torture_close_connection(cli2);
675 printf("finished fdpasstest\n");
681 test the timing of deferred open requests
683 static BOOL run_deferopen(struct smbcli_state *cli, int dummy)
685 const char *fname = "\\defer_open_test.dat";
691 printf("failed to connect\n");
695 printf("Testing deferred open requests.\n");
702 tv = timeval_current();
703 fnum = smbcli_nt_create_full(cli->tree, fname, 0,
705 FILE_ATTRIBUTE_NORMAL,
706 NTCREATEX_SHARE_ACCESS_NONE,
707 NTCREATEX_DISP_OPEN_IF, 0, 0);
711 if (NT_STATUS_EQUAL(smbcli_nt_error(cli->tree),NT_STATUS_SHARING_VIOLATION)) {
712 double e = timeval_elapsed(&tv);
713 if (e < 0.5 || e > 1.5) {
714 fprintf(stderr,"Timing incorrect %.2f violation\n",
718 } while (NT_STATUS_EQUAL(smbcli_nt_error(cli->tree),NT_STATUS_SHARING_VIOLATION));
721 fprintf(stderr,"Failed to open %s, error=%s\n", fname, smbcli_errstr(cli->tree));
725 printf("pid %u open %d\n", getpid(), i);
729 if (NT_STATUS_IS_ERR(smbcli_close(cli->tree, fnum))) {
730 fprintf(stderr,"Failed to close %s, error=%s\n", fname, smbcli_errstr(cli->tree));
736 if (NT_STATUS_IS_ERR(smbcli_unlink(cli->tree, fname))) {
737 /* All until the last unlink will fail with sharing violation. */
738 if (!NT_STATUS_EQUAL(smbcli_nt_error(cli->tree),NT_STATUS_SHARING_VIOLATION)) {
739 printf("unlink of %s failed (%s)\n", fname, smbcli_errstr(cli->tree));
744 printf("deferred test finished\n");
745 if (!torture_close_connection(cli)) {
752 test how many open files this server supports on the one socket
754 static BOOL run_maxfidtest(struct smbcli_state *cli, int dummy)
756 #define MAXFID_TEMPLATE "\\maxfid\\fid%d\\maxfid.%d.%d"
758 int fnums[0x11000], i;
759 int retries=4, maxfid;
763 printf("failed to connect\n");
767 if (smbcli_deltree(cli->tree, "\\maxfid") == -1) {
768 printf("Failed to deltree \\maxfid - %s\n",
769 smbcli_errstr(cli->tree));
772 if (NT_STATUS_IS_ERR(smbcli_mkdir(cli->tree, "\\maxfid"))) {
773 printf("Failed to mkdir \\maxfid, error=%s\n",
774 smbcli_errstr(cli->tree));
778 printf("Testing maximum number of open files\n");
780 for (i=0; i<0x11000; i++) {
782 asprintf(&fname, "\\maxfid\\fid%d", i/1000);
783 if (NT_STATUS_IS_ERR(smbcli_mkdir(cli->tree, fname))) {
784 printf("Failed to mkdir %s, error=%s\n",
785 fname, smbcli_errstr(cli->tree));
790 asprintf(&fname, MAXFID_TEMPLATE, i/1000, i,(int)getpid());
791 if ((fnums[i] = smbcli_open(cli->tree, fname,
792 O_RDWR|O_CREAT|O_TRUNC, DENY_NONE)) ==
794 printf("open of %s failed (%s)\n",
795 fname, smbcli_errstr(cli->tree));
796 printf("maximum fnum is %d\n", i);
807 printf("cleaning up\n");
808 for (i=0;i<maxfid/2;i++) {
809 asprintf(&fname, MAXFID_TEMPLATE, i/1000, i,(int)getpid());
810 if (NT_STATUS_IS_ERR(smbcli_close(cli->tree, fnums[i]))) {
811 printf("Close of fnum %d failed - %s\n", fnums[i], smbcli_errstr(cli->tree));
813 if (NT_STATUS_IS_ERR(smbcli_unlink(cli->tree, fname))) {
814 printf("unlink of %s failed (%s)\n",
815 fname, smbcli_errstr(cli->tree));
820 asprintf(&fname, MAXFID_TEMPLATE, (maxfid-i)/1000, maxfid-i,(int)getpid());
821 if (NT_STATUS_IS_ERR(smbcli_close(cli->tree, fnums[maxfid-i]))) {
822 printf("Close of fnum %d failed - %s\n", fnums[maxfid-i], smbcli_errstr(cli->tree));
824 if (NT_STATUS_IS_ERR(smbcli_unlink(cli->tree, fname))) {
825 printf("unlink of %s failed (%s)\n",
826 fname, smbcli_errstr(cli->tree));
831 printf("%6d %6d\r", i, maxfid-i);
835 if (smbcli_deltree(cli->tree, "\\maxfid") == -1) {
836 printf("Failed to deltree \\maxfid - %s\n",
837 smbcli_errstr(cli->tree));
841 printf("maxfid test finished\n");
842 if (!torture_close_connection(cli)) {
846 #undef MAXFID_TEMPLATE
849 /* send smb negprot commands, not reading the response */
850 static BOOL run_negprot_nowait(void)
853 struct smbcli_state *cli, *cli2;
856 printf("starting negprot nowait test\n");
858 cli = open_nbt_connection();
863 printf("Filling send buffer\n");
865 for (i=0;i<100;i++) {
866 struct smbcli_request *req;
867 req = smb_raw_negotiate_send(cli->transport, PROTOCOL_NT1);
868 event_loop_once(cli->transport->socket->event.ctx);
869 if (req->state == SMBCLI_REQUEST_ERROR) {
871 printf("Failed to fill pipe packet[%d] - %s (ignored)\n", i+1, nt_errstr(req->status));
874 printf("Failed to fill pipe - %s \n", nt_errstr(req->status));
875 torture_close_connection(cli);
881 printf("Opening secondary connection\n");
882 if (!torture_open_connection(&cli2)) {
883 printf("Failed to open secondary connection\n");
887 if (!torture_close_connection(cli2)) {
888 printf("Failed to close secondary connection\n");
892 torture_close_connection(cli);
894 printf("finished negprot nowait test\n");
901 This checks how the getatr calls works
903 static BOOL run_attrtest(void)
905 struct smbcli_state *cli;
908 const char *fname = "\\attrib123456789.tst";
911 printf("starting attrib test\n");
913 if (!torture_open_connection(&cli)) {
917 smbcli_unlink(cli->tree, fname);
918 fnum = smbcli_open(cli->tree, fname,
919 O_RDWR | O_CREAT | O_TRUNC, DENY_NONE);
920 smbcli_close(cli->tree, fnum);
922 if (NT_STATUS_IS_ERR(smbcli_getatr(cli->tree, fname, NULL, NULL, &t))) {
923 printf("getatr failed (%s)\n", smbcli_errstr(cli->tree));
927 printf("New file time is %s", ctime(&t));
929 if (abs(t - time(NULL)) > 60*60*24*10) {
930 printf("ERROR: SMBgetatr bug. time is %s",
936 t2 = t-60*60*24; /* 1 day ago */
938 printf("Setting file time to %s", ctime(&t2));
940 if (NT_STATUS_IS_ERR(smbcli_setatr(cli->tree, fname, 0, t2))) {
941 printf("setatr failed (%s)\n", smbcli_errstr(cli->tree));
945 if (NT_STATUS_IS_ERR(smbcli_getatr(cli->tree, fname, NULL, NULL, &t))) {
946 printf("getatr failed (%s)\n", smbcli_errstr(cli->tree));
950 printf("Retrieved file time as %s", ctime(&t));
953 printf("ERROR: getatr/setatr bug. times are\n%s",
955 printf("%s", ctime(&t2));
959 smbcli_unlink(cli->tree, fname);
961 if (!torture_close_connection(cli)) {
965 printf("attrib test finished\n");
972 This checks a couple of trans2 calls
974 static BOOL run_trans2test(void)
976 struct smbcli_state *cli;
979 time_t c_time, a_time, m_time, w_time, m_time2;
980 const char *fname = "\\trans2.tst";
981 const char *dname = "\\trans2";
982 const char *fname2 = "\\trans2\\trans2.tst";
986 printf("starting trans2 test\n");
988 if (!torture_open_connection(&cli)) {
992 smbcli_unlink(cli->tree, fname);
994 printf("Testing qfileinfo\n");
996 fnum = smbcli_open(cli->tree, fname,
997 O_RDWR | O_CREAT | O_TRUNC, DENY_NONE);
998 if (NT_STATUS_IS_ERR(smbcli_qfileinfo(cli->tree, fnum, NULL, &size, &c_time, &a_time, &m_time,
1000 printf("ERROR: qfileinfo failed (%s)\n", smbcli_errstr(cli->tree));
1004 printf("Testing NAME_INFO\n");
1006 if (NT_STATUS_IS_ERR(smbcli_qfilename(cli->tree, fnum, &pname))) {
1007 printf("ERROR: qfilename failed (%s)\n", smbcli_errstr(cli->tree));
1011 if (!pname || strcmp(pname, fname)) {
1012 printf("qfilename gave different name? [%s] [%s]\n",
1017 smbcli_close(cli->tree, fnum);
1018 smbcli_unlink(cli->tree, fname);
1020 fnum = smbcli_open(cli->tree, fname,
1021 O_RDWR | O_CREAT | O_TRUNC, DENY_NONE);
1023 printf("open of %s failed (%s)\n", fname, smbcli_errstr(cli->tree));
1026 smbcli_close(cli->tree, fnum);
1028 printf("Checking for sticky create times\n");
1030 if (NT_STATUS_IS_ERR(smbcli_qpathinfo(cli->tree, fname, &c_time, &a_time, &m_time, &size, NULL))) {
1031 printf("ERROR: qpathinfo failed (%s)\n", smbcli_errstr(cli->tree));
1034 if (c_time != m_time) {
1035 printf("create time=%s", ctime(&c_time));
1036 printf("modify time=%s", ctime(&m_time));
1037 printf("This system appears to have sticky create times\n");
1039 if (a_time % (60*60) == 0) {
1040 printf("access time=%s", ctime(&a_time));
1041 printf("This system appears to set a midnight access time\n");
1045 if (abs(m_time - time(NULL)) > 60*60*24*7) {
1046 printf("ERROR: totally incorrect times - maybe word reversed? mtime=%s", ctime(&m_time));
1052 smbcli_unlink(cli->tree, fname);
1053 fnum = smbcli_open(cli->tree, fname,
1054 O_RDWR | O_CREAT | O_TRUNC, DENY_NONE);
1055 smbcli_close(cli->tree, fnum);
1056 if (NT_STATUS_IS_ERR(smbcli_qpathinfo2(cli->tree, fname, &c_time, &a_time, &m_time, &w_time, &size, NULL, NULL))) {
1057 printf("ERROR: qpathinfo2 failed (%s)\n", smbcli_errstr(cli->tree));
1060 if (w_time < 60*60*24*2) {
1061 printf("write time=%s", ctime(&w_time));
1062 printf("This system appears to set a initial 0 write time\n");
1067 smbcli_unlink(cli->tree, fname);
1070 /* check if the server updates the directory modification time
1071 when creating a new file */
1072 if (NT_STATUS_IS_ERR(smbcli_mkdir(cli->tree, dname))) {
1073 printf("ERROR: mkdir failed (%s)\n", smbcli_errstr(cli->tree));
1077 if (NT_STATUS_IS_ERR(smbcli_qpathinfo2(cli->tree, "\\trans2\\", &c_time, &a_time, &m_time, &w_time, &size, NULL, NULL))) {
1078 printf("ERROR: qpathinfo2 failed (%s)\n", smbcli_errstr(cli->tree));
1082 fnum = smbcli_open(cli->tree, fname2,
1083 O_RDWR | O_CREAT | O_TRUNC, DENY_NONE);
1084 smbcli_write(cli->tree, fnum, 0, &fnum, 0, sizeof(fnum));
1085 smbcli_close(cli->tree, fnum);
1086 if (NT_STATUS_IS_ERR(smbcli_qpathinfo2(cli->tree, "\\trans2\\", &c_time, &a_time, &m_time2, &w_time, &size, NULL, NULL))) {
1087 printf("ERROR: qpathinfo2 failed (%s)\n", smbcli_errstr(cli->tree));
1090 if (m_time2 == m_time) {
1091 printf("This system does not update directory modification times\n");
1095 smbcli_unlink(cli->tree, fname2);
1096 smbcli_rmdir(cli->tree, dname);
1098 if (!torture_close_connection(cli)) {
1102 printf("trans2 test finished\n");
1109 /* FIRST_DESIRED_ACCESS 0xf019f */
1110 #define FIRST_DESIRED_ACCESS SEC_FILE_READ_DATA|SEC_FILE_WRITE_DATA|SEC_FILE_APPEND_DATA|\
1111 SEC_FILE_READ_EA| /* 0xf */ \
1112 SEC_FILE_WRITE_EA|SEC_FILE_READ_ATTRIBUTE| /* 0x90 */ \
1113 SEC_FILE_WRITE_ATTRIBUTE| /* 0x100 */ \
1114 SEC_STD_DELETE|SEC_STD_READ_CONTROL|\
1115 SEC_STD_WRITE_DAC|SEC_STD_WRITE_OWNER /* 0xf0000 */
1116 /* SECOND_DESIRED_ACCESS 0xe0080 */
1117 #define SECOND_DESIRED_ACCESS SEC_FILE_READ_ATTRIBUTE| /* 0x80 */ \
1118 SEC_STD_READ_CONTROL|SEC_STD_WRITE_DAC|\
1119 SEC_STD_WRITE_OWNER /* 0xe0000 */
1122 #define THIRD_DESIRED_ACCESS FILE_READ_ATTRIBUTE| /* 0x80 */ \
1123 READ_CONTROL|WRITE_DAC|\
1124 SEC_FILE_READ_DATA|\
1129 Test ntcreate calls made by xcopy
1131 static BOOL run_xcopy(void)
1133 struct smbcli_state *cli1;
1134 const char *fname = "\\test.txt";
1135 BOOL correct = True;
1138 printf("starting xcopy test\n");
1140 if (!torture_open_connection(&cli1)) {
1144 fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0,
1145 FIRST_DESIRED_ACCESS,
1146 FILE_ATTRIBUTE_ARCHIVE,
1147 NTCREATEX_SHARE_ACCESS_NONE,
1148 NTCREATEX_DISP_OVERWRITE_IF,
1152 printf("First open failed - %s\n", smbcli_errstr(cli1->tree));
1156 fnum2 = smbcli_nt_create_full(cli1->tree, fname, 0,
1157 SECOND_DESIRED_ACCESS, 0,
1158 NTCREATEX_SHARE_ACCESS_READ|NTCREATEX_SHARE_ACCESS_WRITE|NTCREATEX_SHARE_ACCESS_DELETE, NTCREATEX_DISP_OPEN,
1161 printf("second open failed - %s\n", smbcli_errstr(cli1->tree));
1165 if (!torture_close_connection(cli1)) {
1174 see how many RPC pipes we can open at once
1176 static BOOL run_pipe_number(void)
1178 struct smbcli_state *cli1;
1179 const char *pipe_name = "\\WKSSVC";
1183 printf("starting pipenumber test\n");
1184 if (!torture_open_connection(&cli1)) {
1189 fnum = smbcli_nt_create_full(cli1->tree, pipe_name, 0, SEC_FILE_READ_DATA, FILE_ATTRIBUTE_NORMAL,
1190 NTCREATEX_SHARE_ACCESS_READ|NTCREATEX_SHARE_ACCESS_WRITE, NTCREATEX_DISP_OPEN_IF, 0, 0);
1193 printf("Open of pipe %s failed with error (%s)\n", pipe_name, smbcli_errstr(cli1->tree));
1197 printf("%d\r", num_pipes);
1201 printf("pipe_number test - we can open %d %s pipes.\n", num_pipes, pipe_name );
1202 torture_close_connection(cli1);
1210 open N connections to the server and just hold them open
1211 used for testing performance when there are N idle users
1214 static BOOL torture_holdcon(void)
1217 struct smbcli_state **cli;
1220 printf("Opening %d connections\n", torture_numops);
1222 cli = malloc_array_p(struct smbcli_state *, torture_numops);
1224 for (i=0;i<torture_numops;i++) {
1225 if (!torture_open_connection(&cli[i])) {
1228 printf("opened %d connections\r", i);
1232 printf("\nStarting pings\n");
1235 for (i=0;i<torture_numops;i++) {
1238 status = smbcli_chkpath(cli[i]->tree, "\\");
1239 if (!NT_STATUS_IS_OK(status)) {
1240 printf("Connection %d is dead\n", i);
1248 if (num_dead == torture_numops) {
1249 printf("All connections dead - finishing\n");
1261 Try with a wrong vuid and check error message.
1264 static BOOL run_vuidtest(void)
1266 struct smbcli_state *cli;
1267 const char *fname = "\\vuid.tst";
1270 time_t c_time, a_time, m_time;
1271 BOOL correct = True;
1276 printf("starting vuid test\n");
1278 if (!torture_open_connection(&cli)) {
1282 smbcli_unlink(cli->tree, fname);
1284 fnum = smbcli_open(cli->tree, fname,
1285 O_RDWR | O_CREAT | O_TRUNC, DENY_NONE);
1287 orig_vuid = cli->session->vuid;
1289 cli->session->vuid += 1234;
1291 printf("Testing qfileinfo with wrong vuid\n");
1293 if (NT_STATUS_IS_OK(result = smbcli_qfileinfo(cli->tree, fnum, NULL,
1294 &size, &c_time, &a_time,
1295 &m_time, NULL, NULL))) {
1296 printf("ERROR: qfileinfo passed with wrong vuid\n");
1300 if (!NT_STATUS_EQUAL(cli->transport->error.e.nt_status,
1301 NT_STATUS_DOS(ERRSRV, ERRbaduid)) &&
1302 !NT_STATUS_EQUAL(cli->transport->error.e.nt_status,
1303 NT_STATUS_INVALID_HANDLE)) {
1304 printf("ERROR: qfileinfo should have returned DOS error "
1305 "ERRSRV:ERRbaduid\n but returned %s\n",
1306 smbcli_errstr(cli->tree));
1310 cli->session->vuid -= 1234;
1312 if (NT_STATUS_IS_ERR(smbcli_close(cli->tree, fnum))) {
1313 printf("close failed (%s)\n", smbcli_errstr(cli->tree));
1317 smbcli_unlink(cli->tree, fname);
1319 if (!torture_close_connection(cli)) {
1323 printf("vuid test finished\n");
1329 Test open mode returns on read-only files.
1331 static BOOL run_opentest(void)
1333 static struct smbcli_state *cli1;
1334 static struct smbcli_state *cli2;
1335 const char *fname = "\\readonly.file";
1336 char *control_char_fname;
1340 BOOL correct = True;
1345 printf("starting open test\n");
1347 if (!torture_open_connection(&cli1)) {
1351 asprintf(&control_char_fname, "\\readonly.afile");
1352 for (i = 1; i <= 0x1f; i++) {
1353 control_char_fname[10] = i;
1354 fnum1 = smbcli_nt_create_full(cli1->tree, control_char_fname, 0, SEC_FILE_WRITE_DATA, FILE_ATTRIBUTE_NORMAL,
1355 NTCREATEX_SHARE_ACCESS_NONE, NTCREATEX_DISP_OVERWRITE_IF, 0, 0);
1357 if (!check_error(__location__, cli1, ERRDOS, ERRinvalidname,
1358 NT_STATUS_OBJECT_NAME_INVALID)) {
1359 printf("Error code should be NT_STATUS_OBJECT_NAME_INVALID, was %s for file with %d char\n",
1360 smbcli_errstr(cli1->tree), i);
1365 smbcli_close(cli1->tree, fnum1);
1367 smbcli_setatr(cli1->tree, control_char_fname, 0, 0);
1368 smbcli_unlink(cli1->tree, control_char_fname);
1370 free(control_char_fname);
1373 printf("Create file with control char names passed.\n");
1375 smbcli_setatr(cli1->tree, fname, 0, 0);
1376 smbcli_unlink(cli1->tree, fname);
1378 fnum1 = smbcli_open(cli1->tree, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
1380 printf("open of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
1384 if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum1))) {
1385 printf("close2 failed (%s)\n", smbcli_errstr(cli1->tree));
1389 if (NT_STATUS_IS_ERR(smbcli_setatr(cli1->tree, fname, FILE_ATTRIBUTE_READONLY, 0))) {
1390 printf("smbcli_setatr failed (%s)\n", smbcli_errstr(cli1->tree));
1391 CHECK_MAX_FAILURES(error_test1);
1395 fnum1 = smbcli_open(cli1->tree, fname, O_RDONLY, DENY_WRITE);
1397 printf("open of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
1398 CHECK_MAX_FAILURES(error_test1);
1402 /* This will fail - but the error should be ERRnoaccess, not ERRbadshare. */
1403 fnum2 = smbcli_open(cli1->tree, fname, O_RDWR, DENY_ALL);
1405 if (check_error(__location__, cli1, ERRDOS, ERRnoaccess,
1406 NT_STATUS_ACCESS_DENIED)) {
1407 printf("correct error code ERRDOS/ERRnoaccess returned\n");
1410 printf("finished open test 1\n");
1412 smbcli_close(cli1->tree, fnum1);
1414 /* Now try not readonly and ensure ERRbadshare is returned. */
1416 smbcli_setatr(cli1->tree, fname, 0, 0);
1418 fnum1 = smbcli_open(cli1->tree, fname, O_RDONLY, DENY_WRITE);
1420 printf("open of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
1424 /* This will fail - but the error should be ERRshare. */
1425 fnum2 = smbcli_open(cli1->tree, fname, O_RDWR, DENY_ALL);
1427 if (check_error(__location__, cli1, ERRDOS, ERRbadshare,
1428 NT_STATUS_SHARING_VIOLATION)) {
1429 printf("correct error code ERRDOS/ERRbadshare returned\n");
1432 if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum1))) {
1433 printf("close2 failed (%s)\n", smbcli_errstr(cli1->tree));
1437 smbcli_unlink(cli1->tree, fname);
1439 printf("finished open test 2\n");
1441 /* Test truncate open disposition on file opened for read. */
1443 fnum1 = smbcli_open(cli1->tree, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
1445 printf("(3) open (1) of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
1449 /* write 20 bytes. */
1451 memset(buf, '\0', 20);
1453 if (smbcli_write(cli1->tree, fnum1, 0, buf, 0, 20) != 20) {
1454 printf("write failed (%s)\n", smbcli_errstr(cli1->tree));
1458 if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum1))) {
1459 printf("(3) close1 failed (%s)\n", smbcli_errstr(cli1->tree));
1463 /* Ensure size == 20. */
1464 if (NT_STATUS_IS_ERR(smbcli_getatr(cli1->tree, fname, NULL, &fsize, NULL))) {
1465 printf("(3) getatr failed (%s)\n", smbcli_errstr(cli1->tree));
1466 CHECK_MAX_FAILURES(error_test3);
1471 printf("(3) file size != 20\n");
1472 CHECK_MAX_FAILURES(error_test3);
1476 /* Now test if we can truncate a file opened for readonly. */
1478 fnum1 = smbcli_open(cli1->tree, fname, O_RDONLY|O_TRUNC, DENY_NONE);
1480 printf("(3) open (2) of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
1481 CHECK_MAX_FAILURES(error_test3);
1485 if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum1))) {
1486 printf("close2 failed (%s)\n", smbcli_errstr(cli1->tree));
1490 /* Ensure size == 0. */
1491 if (NT_STATUS_IS_ERR(smbcli_getatr(cli1->tree, fname, NULL, &fsize, NULL))) {
1492 printf("(3) getatr failed (%s)\n", smbcli_errstr(cli1->tree));
1493 CHECK_MAX_FAILURES(error_test3);
1498 printf("(3) file size != 0\n");
1499 CHECK_MAX_FAILURES(error_test3);
1502 printf("finished open test 3\n");
1504 smbcli_unlink(cli1->tree, fname);
1507 printf("testing ctemp\n");
1508 fnum1 = smbcli_ctemp(cli1->tree, "\\", &tmp_path);
1510 printf("ctemp failed (%s)\n", smbcli_errstr(cli1->tree));
1511 CHECK_MAX_FAILURES(error_test4);
1514 printf("ctemp gave path %s\n", tmp_path);
1515 if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum1))) {
1516 printf("close of temp failed (%s)\n", smbcli_errstr(cli1->tree));
1518 if (NT_STATUS_IS_ERR(smbcli_unlink(cli1->tree, tmp_path))) {
1519 printf("unlink of temp failed (%s)\n", smbcli_errstr(cli1->tree));
1522 /* Test the non-io opens... */
1524 if (!torture_open_connection(&cli2)) {
1528 smbcli_setatr(cli2->tree, fname, 0, 0);
1529 smbcli_unlink(cli2->tree, fname);
1531 printf("TEST #1 testing 2 non-io opens (no delete)\n");
1533 fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0, SEC_FILE_READ_ATTRIBUTE, FILE_ATTRIBUTE_NORMAL,
1534 NTCREATEX_SHARE_ACCESS_NONE, NTCREATEX_DISP_OVERWRITE_IF, 0, 0);
1537 printf("test 1 open 1 of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
1538 CHECK_MAX_FAILURES(error_test10);
1542 fnum2 = smbcli_nt_create_full(cli2->tree, fname, 0, SEC_FILE_READ_ATTRIBUTE, FILE_ATTRIBUTE_NORMAL,
1543 NTCREATEX_SHARE_ACCESS_NONE, NTCREATEX_DISP_OPEN_IF, 0, 0);
1545 printf("test 1 open 2 of %s failed (%s)\n", fname, smbcli_errstr(cli2->tree));
1546 CHECK_MAX_FAILURES(error_test10);
1550 if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum1))) {
1551 printf("test 1 close 1 of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
1554 if (NT_STATUS_IS_ERR(smbcli_close(cli2->tree, fnum2))) {
1555 printf("test 1 close 2 of %s failed (%s)\n", fname, smbcli_errstr(cli2->tree));
1559 printf("non-io open test #1 passed.\n");
1561 smbcli_unlink(cli1->tree, fname);
1563 printf("TEST #2 testing 2 non-io opens (first with delete)\n");
1565 fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0, SEC_STD_DELETE|SEC_FILE_READ_ATTRIBUTE, FILE_ATTRIBUTE_NORMAL,
1566 NTCREATEX_SHARE_ACCESS_NONE, NTCREATEX_DISP_OVERWRITE_IF, 0, 0);
1569 printf("test 2 open 1 of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
1570 CHECK_MAX_FAILURES(error_test20);
1574 fnum2 = smbcli_nt_create_full(cli2->tree, fname, 0, SEC_FILE_READ_ATTRIBUTE, FILE_ATTRIBUTE_NORMAL,
1575 NTCREATEX_SHARE_ACCESS_NONE, NTCREATEX_DISP_OPEN_IF, 0, 0);
1578 printf("test 2 open 2 of %s failed (%s)\n", fname, smbcli_errstr(cli2->tree));
1579 CHECK_MAX_FAILURES(error_test20);
1583 if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum1))) {
1584 printf("test 1 close 1 of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
1587 if (NT_STATUS_IS_ERR(smbcli_close(cli2->tree, fnum2))) {
1588 printf("test 1 close 2 of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
1592 printf("non-io open test #2 passed.\n");
1594 smbcli_unlink(cli1->tree, fname);
1596 printf("TEST #3 testing 2 non-io opens (second with delete)\n");
1598 fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0, SEC_FILE_READ_ATTRIBUTE, FILE_ATTRIBUTE_NORMAL,
1599 NTCREATEX_SHARE_ACCESS_NONE, NTCREATEX_DISP_OVERWRITE_IF, 0, 0);
1602 printf("test 3 open 1 of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
1603 CHECK_MAX_FAILURES(error_test30);
1607 fnum2 = smbcli_nt_create_full(cli2->tree, fname, 0, SEC_STD_DELETE|SEC_FILE_READ_ATTRIBUTE, FILE_ATTRIBUTE_NORMAL,
1608 NTCREATEX_SHARE_ACCESS_NONE, NTCREATEX_DISP_OPEN_IF, 0, 0);
1611 printf("test 3 open 2 of %s failed (%s)\n", fname, smbcli_errstr(cli2->tree));
1612 CHECK_MAX_FAILURES(error_test30);
1616 if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum1))) {
1617 printf("test 3 close 1 of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
1620 if (NT_STATUS_IS_ERR(smbcli_close(cli2->tree, fnum2))) {
1621 printf("test 3 close 2 of %s failed (%s)\n", fname, smbcli_errstr(cli2->tree));
1625 printf("non-io open test #3 passed.\n");
1627 smbcli_unlink(cli1->tree, fname);
1629 printf("TEST #4 testing 2 non-io opens (both with delete)\n");
1631 fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0, SEC_STD_DELETE|SEC_FILE_READ_ATTRIBUTE, FILE_ATTRIBUTE_NORMAL,
1632 NTCREATEX_SHARE_ACCESS_NONE, NTCREATEX_DISP_OVERWRITE_IF, 0, 0);
1635 printf("test 4 open 1 of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
1636 CHECK_MAX_FAILURES(error_test40);
1640 fnum2 = smbcli_nt_create_full(cli2->tree, fname, 0, SEC_STD_DELETE|SEC_FILE_READ_ATTRIBUTE, FILE_ATTRIBUTE_NORMAL,
1641 NTCREATEX_SHARE_ACCESS_NONE, NTCREATEX_DISP_OPEN_IF, 0, 0);
1644 printf("test 4 open 2 of %s SUCCEEDED - should have failed (%s)\n", fname, smbcli_errstr(cli2->tree));
1645 CHECK_MAX_FAILURES(error_test40);
1649 printf("test 4 open 2 of %s gave %s (correct error should be %s)\n", fname, smbcli_errstr(cli2->tree), "sharing violation");
1651 if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum1))) {
1652 printf("test 4 close 1 of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
1656 printf("non-io open test #4 passed.\n");
1658 smbcli_unlink(cli1->tree, fname);
1660 printf("TEST #5 testing 2 non-io opens (both with delete - both with file share delete)\n");
1662 fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0, SEC_STD_DELETE|SEC_FILE_READ_ATTRIBUTE, FILE_ATTRIBUTE_NORMAL,
1663 NTCREATEX_SHARE_ACCESS_DELETE, NTCREATEX_DISP_OVERWRITE_IF, 0, 0);
1666 printf("test 5 open 1 of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
1667 CHECK_MAX_FAILURES(error_test50);
1671 fnum2 = smbcli_nt_create_full(cli2->tree, fname, 0, SEC_STD_DELETE|SEC_FILE_READ_ATTRIBUTE, FILE_ATTRIBUTE_NORMAL,
1672 NTCREATEX_SHARE_ACCESS_DELETE, NTCREATEX_DISP_OPEN_IF, 0, 0);
1675 printf("test 5 open 2 of %s failed (%s)\n", fname, smbcli_errstr(cli2->tree));
1676 CHECK_MAX_FAILURES(error_test50);
1680 if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum1))) {
1681 printf("test 5 close 1 of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
1685 if (NT_STATUS_IS_ERR(smbcli_close(cli2->tree, fnum2))) {
1686 printf("test 5 close 2 of %s failed (%s)\n", fname, smbcli_errstr(cli2->tree));
1690 printf("non-io open test #5 passed.\n");
1692 printf("TEST #6 testing 1 non-io open, one io open\n");
1694 smbcli_unlink(cli1->tree, fname);
1696 fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0, SEC_FILE_READ_DATA, FILE_ATTRIBUTE_NORMAL,
1697 NTCREATEX_SHARE_ACCESS_NONE, NTCREATEX_DISP_OVERWRITE_IF, 0, 0);
1700 printf("test 6 open 1 of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
1701 CHECK_MAX_FAILURES(error_test60);
1705 fnum2 = smbcli_nt_create_full(cli2->tree, fname, 0, SEC_FILE_READ_ATTRIBUTE, FILE_ATTRIBUTE_NORMAL,
1706 NTCREATEX_SHARE_ACCESS_READ, NTCREATEX_DISP_OPEN_IF, 0, 0);
1709 printf("test 6 open 2 of %s failed (%s)\n", fname, smbcli_errstr(cli2->tree));
1710 CHECK_MAX_FAILURES(error_test60);
1714 if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum1))) {
1715 printf("test 6 close 1 of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
1719 if (NT_STATUS_IS_ERR(smbcli_close(cli2->tree, fnum2))) {
1720 printf("test 6 close 2 of %s failed (%s)\n", fname, smbcli_errstr(cli2->tree));
1724 printf("non-io open test #6 passed.\n");
1726 printf("TEST #7 testing 1 non-io open, one io open with delete\n");
1728 smbcli_unlink(cli1->tree, fname);
1730 fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0, SEC_FILE_READ_DATA, FILE_ATTRIBUTE_NORMAL,
1731 NTCREATEX_SHARE_ACCESS_NONE, NTCREATEX_DISP_OVERWRITE_IF, 0, 0);
1734 printf("test 7 open 1 of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
1735 CHECK_MAX_FAILURES(error_test70);
1739 fnum2 = smbcli_nt_create_full(cli2->tree, fname, 0, SEC_STD_DELETE|SEC_FILE_READ_ATTRIBUTE, FILE_ATTRIBUTE_NORMAL,
1740 NTCREATEX_SHARE_ACCESS_READ|NTCREATEX_SHARE_ACCESS_DELETE, NTCREATEX_DISP_OPEN_IF, 0, 0);
1743 printf("test 7 open 2 of %s SUCCEEDED - should have failed (%s)\n", fname, smbcli_errstr(cli2->tree));
1744 CHECK_MAX_FAILURES(error_test70);
1748 printf("test 7 open 2 of %s gave %s (correct error should be %s)\n", fname, smbcli_errstr(cli2->tree), "sharing violation");
1750 if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum1))) {
1751 printf("test 7 close 1 of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
1755 printf("non-io open test #7 passed.\n");
1759 printf("TEST #8 testing one normal open, followed by lock, followed by open with truncate\n");
1761 smbcli_unlink(cli1->tree, fname);
1763 fnum1 = smbcli_open(cli1->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
1765 printf("(8) open (1) of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
1769 /* write 20 bytes. */
1771 memset(buf, '\0', 20);
1773 if (smbcli_write(cli1->tree, fnum1, 0, buf, 0, 20) != 20) {
1774 printf("(8) write failed (%s)\n", smbcli_errstr(cli1->tree));
1778 /* Ensure size == 20. */
1779 if (NT_STATUS_IS_ERR(smbcli_getatr(cli1->tree, fname, NULL, &fsize, NULL))) {
1780 printf("(8) getatr (1) failed (%s)\n", smbcli_errstr(cli1->tree));
1781 CHECK_MAX_FAILURES(error_test80);
1786 printf("(8) file size != 20\n");
1787 CHECK_MAX_FAILURES(error_test80);
1791 /* Get an exclusive lock on the open file. */
1792 if (NT_STATUS_IS_ERR(smbcli_lock(cli1->tree, fnum1, 0, 4, 0, WRITE_LOCK))) {
1793 printf("(8) lock1 failed (%s)\n", smbcli_errstr(cli1->tree));
1794 CHECK_MAX_FAILURES(error_test80);
1798 fnum2 = smbcli_open(cli1->tree, fname, O_RDWR|O_TRUNC, DENY_NONE);
1800 printf("(8) open (2) of %s with truncate failed (%s)\n", fname, smbcli_errstr(cli1->tree));
1804 /* Ensure size == 0. */
1805 if (NT_STATUS_IS_ERR(smbcli_getatr(cli1->tree, fname, NULL, &fsize, NULL))) {
1806 printf("(8) getatr (2) failed (%s)\n", smbcli_errstr(cli1->tree));
1807 CHECK_MAX_FAILURES(error_test80);
1812 printf("(8) file size != 0\n");
1813 CHECK_MAX_FAILURES(error_test80);
1817 if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum1))) {
1818 printf("(8) close1 failed (%s)\n", smbcli_errstr(cli1->tree));
1822 if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum2))) {
1823 printf("(8) close1 failed (%s)\n", smbcli_errstr(cli1->tree));
1829 printf("open test #8 passed.\n");
1831 smbcli_unlink(cli1->tree, fname);
1833 if (!torture_close_connection(cli1)) {
1836 if (!torture_close_connection(cli2)) {
1845 sees what IOCTLs are supported
1847 BOOL torture_ioctl_test(void)
1849 struct smbcli_state *cli;
1850 uint16_t device, function;
1852 const char *fname = "\\ioctl.dat";
1854 union smb_ioctl parms;
1855 TALLOC_CTX *mem_ctx;
1857 if (!torture_open_connection(&cli)) {
1861 mem_ctx = talloc_init("ioctl_test");
1863 printf("starting ioctl test\n");
1865 smbcli_unlink(cli->tree, fname);
1867 fnum = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
1869 printf("open of %s failed (%s)\n", fname, smbcli_errstr(cli->tree));
1873 parms.ioctl.level = RAW_IOCTL_IOCTL;
1874 parms.ioctl.in.file.fnum = fnum;
1875 parms.ioctl.in.request = IOCTL_QUERY_JOB_INFO;
1876 status = smb_raw_ioctl(cli->tree, mem_ctx, &parms);
1877 printf("ioctl job info: %s\n", smbcli_errstr(cli->tree));
1879 for (device=0;device<0x100;device++) {
1880 printf("testing device=0x%x\n", device);
1881 for (function=0;function<0x100;function++) {
1882 parms.ioctl.in.request = (device << 16) | function;
1883 status = smb_raw_ioctl(cli->tree, mem_ctx, &parms);
1885 if (NT_STATUS_IS_OK(status)) {
1886 printf("ioctl device=0x%x function=0x%x OK : %d bytes\n",
1887 device, function, (int)parms.ioctl.out.blob.length);
1892 if (!torture_close_connection(cli)) {
1901 tries variants of chkpath
1903 BOOL torture_chkpath_test(void)
1905 struct smbcli_state *cli;
1909 if (!torture_open_connection(&cli)) {
1913 printf("starting chkpath test\n");
1915 printf("Testing valid and invalid paths\n");
1917 /* cleanup from an old run */
1918 smbcli_rmdir(cli->tree, "\\chkpath.dir\\dir2");
1919 smbcli_unlink(cli->tree, "\\chkpath.dir\\*");
1920 smbcli_rmdir(cli->tree, "\\chkpath.dir");
1922 if (NT_STATUS_IS_ERR(smbcli_mkdir(cli->tree, "\\chkpath.dir"))) {
1923 printf("mkdir1 failed : %s\n", smbcli_errstr(cli->tree));
1927 if (NT_STATUS_IS_ERR(smbcli_mkdir(cli->tree, "\\chkpath.dir\\dir2"))) {
1928 printf("mkdir2 failed : %s\n", smbcli_errstr(cli->tree));
1932 fnum = smbcli_open(cli->tree, "\\chkpath.dir\\foo.txt", O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
1934 printf("open1 failed (%s)\n", smbcli_errstr(cli->tree));
1937 smbcli_close(cli->tree, fnum);
1939 if (NT_STATUS_IS_ERR(smbcli_chkpath(cli->tree, "\\chkpath.dir"))) {
1940 printf("chkpath1 failed: %s\n", smbcli_errstr(cli->tree));
1944 if (NT_STATUS_IS_ERR(smbcli_chkpath(cli->tree, "\\chkpath.dir\\dir2"))) {
1945 printf("chkpath2 failed: %s\n", smbcli_errstr(cli->tree));
1949 if (NT_STATUS_IS_ERR(smbcli_chkpath(cli->tree, "\\chkpath.dir\\foo.txt"))) {
1950 ret = check_error(__location__, cli, ERRDOS, ERRbadpath,
1951 NT_STATUS_NOT_A_DIRECTORY);
1953 printf("* chkpath on a file should fail\n");
1957 if (NT_STATUS_IS_ERR(smbcli_chkpath(cli->tree, "\\chkpath.dir\\bar.txt"))) {
1958 ret = check_error(__location__, cli, ERRDOS, ERRbadpath,
1959 NT_STATUS_OBJECT_NAME_NOT_FOUND);
1961 printf("* chkpath on a non existent file should fail\n");
1965 if (NT_STATUS_IS_ERR(smbcli_chkpath(cli->tree, "\\chkpath.dir\\dirxx\\bar.txt"))) {
1966 ret = check_error(__location__, cli, ERRDOS, ERRbadpath,
1967 NT_STATUS_OBJECT_PATH_NOT_FOUND);
1969 printf("* chkpath on a non existent component should fail\n");
1973 smbcli_rmdir(cli->tree, "\\chkpath.dir\\dir2");
1974 smbcli_unlink(cli->tree, "\\chkpath.dir\\*");
1975 smbcli_rmdir(cli->tree, "\\chkpath.dir");
1977 if (!torture_close_connection(cli)) {
1985 static void sigcont(int sig)
1989 double torture_create_procs(BOOL (*fn)(struct smbcli_state *, int), BOOL *result)
1992 volatile pid_t *child_status;
1993 volatile BOOL *child_status_out;
1996 double start_time_limit = 10 + (torture_nprocs * 1.5);
1997 char **unc_list = NULL;
1999 int num_unc_names = 0;
2006 signal(SIGCONT, sigcont);
2008 child_status = (volatile pid_t *)shm_setup(sizeof(pid_t)*torture_nprocs);
2009 if (!child_status) {
2010 printf("Failed to setup shared memory\n");
2014 child_status_out = (volatile BOOL *)shm_setup(sizeof(BOOL)*torture_nprocs);
2015 if (!child_status_out) {
2016 printf("Failed to setup result status shared memory\n");
2020 p = lp_parm_string(-1, "torture", "unclist");
2022 unc_list = file_lines_load(p, &num_unc_names, NULL);
2023 if (!unc_list || num_unc_names <= 0) {
2024 printf("Failed to load unc names list from '%s'\n", p);
2029 for (i = 0; i < torture_nprocs; i++) {
2030 child_status[i] = 0;
2031 child_status_out[i] = True;
2034 tv = timeval_current();
2036 for (i=0;i<torture_nprocs;i++) {
2040 char *hostname=NULL, *sharename;
2042 pid_t mypid = getpid();
2043 srandom(((int)mypid) ^ ((int)time(NULL)));
2045 asprintf(&myname, "CLIENT%d", i);
2046 lp_set_cmdline("netbios name", myname);
2051 if (!smbcli_parse_unc(unc_list[i % num_unc_names],
2052 NULL, &hostname, &sharename)) {
2053 printf("Failed to parse UNC name %s\n",
2054 unc_list[i % num_unc_names]);
2061 if (torture_open_connection_share(NULL,
2068 } else if (torture_open_connection(¤t_cli)) {
2072 printf("pid %d failed to start\n", (int)getpid());
2078 child_status[i] = getpid();
2082 if (child_status[i]) {
2083 printf("Child %d failed to start!\n", i);
2084 child_status_out[i] = 1;
2088 child_status_out[i] = fn(current_cli, i);
2095 for (i=0;i<torture_nprocs;i++) {
2096 if (child_status[i]) synccount++;
2098 if (synccount == torture_nprocs) break;
2100 } while (timeval_elapsed(&tv) < start_time_limit);
2102 if (synccount != torture_nprocs) {
2103 printf("FAILED TO START %d CLIENTS (started %d)\n", torture_nprocs, synccount);
2105 return timeval_elapsed(&tv);
2108 printf("Starting %d clients\n", torture_nprocs);
2110 /* start the client load */
2111 tv = timeval_current();
2112 for (i=0;i<torture_nprocs;i++) {
2113 child_status[i] = 0;
2116 printf("%d clients started\n", torture_nprocs);
2120 for (i=0;i<torture_nprocs;i++) {
2122 while ((ret=waitpid(0, &status, 0)) == -1 && errno == EINTR) /* noop */ ;
2123 if (ret == -1 || WEXITSTATUS(status) != 0) {
2130 for (i=0;i<torture_nprocs;i++) {
2131 if (!child_status_out[i]) {
2135 return timeval_elapsed(&tv);
2138 #define FLAG_MULTIPROC 1
2143 BOOL (*multi_fn)(struct smbcli_state *, int );
2144 } builtin_torture_ops[] = {
2146 {"BASE-FDPASS", run_fdpasstest, 0},
2147 {"BASE-LOCK1", torture_locktest1, 0},
2148 {"BASE-LOCK2", torture_locktest2, 0},
2149 {"BASE-LOCK3", torture_locktest3, 0},
2150 {"BASE-LOCK4", torture_locktest4, 0},
2151 {"BASE-LOCK5", torture_locktest5, 0},
2152 {"BASE-LOCK6", torture_locktest6, 0},
2153 {"BASE-LOCK7", torture_locktest7, 0},
2154 {"BASE-UNLINK", torture_unlinktest, 0},
2155 {"BASE-ATTR", run_attrtest, 0},
2156 {"BASE-TRANS2", run_trans2test, 0},
2157 {"BASE-NEGNOWAIT", run_negprot_nowait, 0},
2158 {"BASE-DIR1", torture_dirtest1, 0},
2159 {"BASE-DIR2", torture_dirtest2, 0},
2160 {"BASE-DENY1", torture_denytest1, 0},
2161 {"BASE-DENY2", torture_denytest2, 0},
2162 {"BASE-DENY3", torture_denytest3, 0},
2163 {"BASE-DENYDOS", torture_denydos_sharing, 0},
2164 {"BASE-NTDENY1", NULL, torture_ntdenytest1},
2165 {"BASE-NTDENY2", torture_ntdenytest2, 0},
2166 {"BASE-TCON", run_tcon_test, 0},
2167 {"BASE-TCONDEV", run_tcon_devtype_test, 0},
2168 {"BASE-VUID", run_vuidtest, 0},
2169 {"BASE-RW1", run_readwritetest, 0},
2170 {"BASE-OPEN", run_opentest, 0},
2171 {"BASE-DEFER_OPEN", NULL, run_deferopen},
2172 {"BASE-XCOPY", run_xcopy, 0},
2173 {"BASE-RENAME", torture_test_rename, 0},
2174 {"BASE-DELETE", torture_test_delete, 0},
2175 {"BASE-PROPERTIES", torture_test_properties, 0},
2176 {"BASE-MANGLE", torture_mangle, 0},
2177 {"BASE-OPENATTR", torture_openattrtest, 0},
2178 {"BASE-CHARSET", torture_charset, 0},
2179 {"BASE-CHKPATH", torture_chkpath_test, 0},
2180 {"BASE-SECLEAK", torture_sec_leak, 0},
2181 {"BASE-DISCONNECT", torture_disconnect, 0},
2182 {"BASE-DELAYWRITE", torture_delay_write, 0},
2184 /* benchmarking tests */
2185 {"BENCH-HOLDCON", torture_holdcon, 0},
2186 {"BENCH-NBENCH", torture_nbench, 0},
2187 {"BENCH-TORTURE", NULL, run_torture},
2188 {"BENCH-NBT", torture_bench_nbt, 0},
2189 {"BENCH-WINS", torture_bench_wins, 0},
2190 {"BENCH-CLDAP", torture_bench_cldap, 0},
2193 {"RAW-QFSINFO", torture_raw_qfsinfo, 0},
2194 {"RAW-QFILEINFO", torture_raw_qfileinfo, 0},
2195 {"RAW-SFILEINFO", torture_raw_sfileinfo, 0},
2196 {"RAW-SFILEINFO-BUG", torture_raw_sfileinfo_bug, 0},
2197 {"RAW-SEARCH", torture_raw_search, 0},
2198 {"RAW-CLOSE", torture_raw_close, 0},
2199 {"RAW-OPEN", torture_raw_open, 0},
2200 {"RAW-MKDIR", torture_raw_mkdir, 0},
2201 {"RAW-OPLOCK", torture_raw_oplock, 0},
2202 {"RAW-NOTIFY", torture_raw_notify, 0},
2203 {"RAW-MUX", torture_raw_mux, 0},
2204 {"RAW-IOCTL", torture_raw_ioctl, 0},
2205 {"RAW-CHKPATH", torture_raw_chkpath, 0},
2206 {"RAW-UNLINK", torture_raw_unlink, 0},
2207 {"RAW-READ", torture_raw_read, 0},
2208 {"RAW-WRITE", torture_raw_write, 0},
2209 {"RAW-LOCK", torture_raw_lock, 0},
2210 {"RAW-CONTEXT", torture_raw_context, 0},
2211 {"RAW-RENAME", torture_raw_rename, 0},
2212 {"RAW-SEEK", torture_raw_seek, 0},
2213 {"RAW-EAS", torture_raw_eas, 0},
2214 {"RAW-EAMAX", torture_max_eas, 0},
2215 {"RAW-STREAMS", torture_raw_streams, 0},
2216 {"RAW-ACLS", torture_raw_acls, 0},
2217 {"RAW-RAP", torture_raw_rap, 0},
2218 {"RAW-COMPOSITE", torture_raw_composite, 0},
2221 {"SMB2-CONNECT", torture_smb2_connect, 0},
2222 {"SMB2-SCAN", torture_smb2_scan, 0},
2223 {"SMB2-SCANGETINFO", torture_smb2_getinfo_scan, 0},
2224 {"SMB2-SCANSETINFO", torture_smb2_setinfo_scan, 0},
2225 {"SMB2-SCANFIND", torture_smb2_find_scan, 0},
2226 {"SMB2-GETINFO", torture_smb2_getinfo, 0},
2227 {"SMB2-SETINFO", torture_smb2_setinfo, 0},
2228 {"SMB2-FIND", torture_smb2_find, 0},
2230 /* protocol scanners */
2231 {"SCAN-TRANS2", torture_trans2_scan, 0},
2232 {"SCAN-NTTRANS", torture_nttrans_scan, 0},
2233 {"SCAN-ALIASES", torture_trans2_aliases, 0},
2234 {"SCAN-SMB", torture_smb_scan, 0},
2235 {"SCAN-MAXFID", NULL, run_maxfidtest},
2236 {"SCAN-UTABLE", torture_utable, 0},
2237 {"SCAN-CASETABLE", torture_casetable, 0},
2238 {"SCAN-PIPE_NUMBER", run_pipe_number, 0},
2239 {"SCAN-IOCTL", torture_ioctl_test, 0},
2240 {"SCAN-RAP", torture_rap_scan, 0},
2242 /* local (no server) testers */
2243 {"LOCAL-NTLMSSP", torture_ntlmssp_self_check, 0},
2244 {"LOCAL-ICONV", torture_local_iconv, 0},
2245 {"LOCAL-TALLOC", torture_local_talloc, 0},
2246 {"LOCAL-MESSAGING", torture_local_messaging, 0},
2247 {"LOCAL-IRPC", torture_local_irpc, 0},
2248 {"LOCAL-BINDING", torture_local_binding_string, 0},
2249 {"LOCAL-STRLIST", torture_local_util_strlist, 0},
2250 {"LOCAL-FILE", torture_local_util_file, 0},
2251 {"LOCAL-IDTREE", torture_local_idtree, 0},
2252 {"LOCAL-SOCKET", torture_local_socket, 0},
2253 {"LOCAL-PAC", torture_pac, 0},
2254 {"LOCAL-REGISTRY", torture_registry, 0},
2255 {"LOCAL-RESOLVE", torture_local_resolve, 0},
2256 {"LOCAL-SDDL", torture_local_sddl, 0},
2257 {"LOCAL-NDR", torture_local_ndr, 0},
2260 {"LDAP-BASIC", torture_ldap_basic, 0},
2261 {"LDAP-CLDAP", torture_cldap, 0},
2264 {"NBT-REGISTER", torture_nbt_register, 0},
2265 {"NBT-WINS", torture_nbt_wins, 0},
2266 {"NBT-DGRAM", torture_nbt_dgram, 0},
2267 {"NBT-BROWSE", torture_nbt_browse, 0},
2268 {"NBT-WINSREPLICATION-SIMPLE", torture_nbt_winsreplication_simple, 0},
2269 {"NBT-WINSREPLICATION-REPLICA", torture_nbt_winsreplication_replica, 0},
2270 {"NBT-WINSREPLICATION-OWNED", torture_nbt_winsreplication_owned, 0},
2273 {"NET-USERINFO", torture_userinfo, 0},
2274 {"NET-USERADD", torture_useradd, 0},
2275 {"NET-USERDEL", torture_userdel, 0},
2276 {"NET-USERMOD", torture_usermod, 0},
2277 {"NET-DOMOPEN", torture_domainopen, 0},
2278 {"NET-API-LOOKUP", torture_lookup, 0},
2279 {"NET-API-LOOKUPHOST", torture_lookup_host, 0},
2280 {"NET-API-LOOKUPPDC", torture_lookup_pdc, 0},
2281 {"NET-API-CREATEUSER", torture_createuser, 0},
2282 {"NET-API-RPCCONNECT", torture_rpc_connect, 0},
2283 {"NET-API-LISTSHARES", torture_listshares, 0},
2284 {"NET-API-DELSHARE", torture_delshare, 0},
2288 static void register_builtin_ops(void)
2291 for (i = 0; builtin_torture_ops[i].name; i++) {
2292 register_torture_op(builtin_torture_ops[i].name,
2293 builtin_torture_ops[i].fn,
2294 builtin_torture_ops[i].multi_fn);
2299 static struct torture_op {
2302 BOOL (*multi_fn)(struct smbcli_state *, int );
2303 struct torture_op *prev, *next;
2304 }* torture_ops = NULL;;
2306 static struct torture_op *find_torture_op(const char *name)
2308 struct torture_op *o;
2309 for (o = torture_ops; o; o = o->next) {
2310 if (strcmp(name, o->name) == 0)
2317 NTSTATUS register_torture_op(const char *name, BOOL (*fn)(void), BOOL (*multi_fn)(struct smbcli_state *, int ))
2319 struct torture_op *op;
2321 /* Check for duplicates */
2322 if (find_torture_op(name) != NULL) {
2323 DEBUG(0,("There already is a torture op registered with the name %s!\n", name));
2324 return NT_STATUS_OBJECT_NAME_COLLISION;
2327 op = talloc(talloc_autofree_context(), struct torture_op);
2329 op->name = talloc_strdup(op, name);
2331 op->multi_fn = multi_fn;
2333 DLIST_ADD(torture_ops, op);
2335 return NT_STATUS_OK;
2338 /****************************************************************************
2339 run a specified test or "ALL"
2340 ****************************************************************************/
2341 static BOOL run_test(const char *name)
2344 struct torture_op *o;
2345 BOOL matched = False;
2347 if (strequal(name,"ALL")) {
2348 for (o = torture_ops; o; o = o->next) {
2349 if (!run_test(o->name)) {
2356 for (o = torture_ops; o; o = o->next) {
2357 if (gen_fnmatch(name, o->name) == 0) {
2361 printf("Running %s\n", o->name);
2363 BOOL result = False;
2364 t = torture_create_procs(o->multi_fn,
2368 printf("TEST %s FAILED!\n", o->name);
2372 struct timeval tv = timeval_current();
2375 printf("TEST %s FAILED!\n", o->name);
2377 t = timeval_elapsed(&tv);
2379 printf("%s took %g secs\n\n", o->name, t);
2384 printf("Unknown torture operation '%s'\n", name);
2391 static void parse_dns(const char *dns)
2393 char *userdn, *basedn, *secret;
2396 /* retrievieng the userdn */
2397 p = strchr_m(dns, '#');
2399 lp_set_cmdline("torture:ldap_userdn", "");
2400 lp_set_cmdline("torture:ldap_basedn", "");
2401 lp_set_cmdline("torture:ldap_secret", "");
2404 userdn = strndup(dns, p - dns);
2405 lp_set_cmdline("torture:ldap_userdn", userdn);
2407 /* retrieve the basedn */
2409 p = strchr_m(d, '#');
2411 lp_set_cmdline("torture:ldap_basedn", "");
2412 lp_set_cmdline("torture:ldap_secret", "");
2415 basedn = strndup(d, p - d);
2416 lp_set_cmdline("torture:ldap_basedn", basedn);
2418 /* retrieve the secret */
2421 lp_set_cmdline("torture:ldap_secret", "");
2425 lp_set_cmdline("torture:ldap_secret", secret);
2427 printf ("%s - %s - %s\n", userdn, basedn, secret);
2431 static void usage(poptContext pc)
2433 struct torture_op *o;
2436 poptPrintUsage(pc, stdout, 0);
2439 printf("The binding format is:\n\n");
2441 printf(" TRANSPORT:host[flags]\n\n");
2443 printf(" where TRANSPORT is either ncacn_np for SMB or ncacn_ip_tcp for RPC/TCP\n\n");
2445 printf(" 'host' is an IP or hostname or netbios name. If the binding string\n");
2446 printf(" identifies the server side of an endpoint, 'host' may be an empty\n");
2447 printf(" string.\n\n");
2449 printf(" 'flags' can include a SMB pipe name if using the ncacn_np transport or\n");
2450 printf(" a TCP port number if using the ncacn_ip_tcp transport, otherwise they\n");
2451 printf(" will be auto-determined.\n\n");
2453 printf(" other recognised flags are:\n\n");
2455 printf(" sign : enable ntlmssp signing\n");
2456 printf(" seal : enable ntlmssp sealing\n");
2457 printf(" connect : enable rpc connect level auth (auth, but no sign or seal)\n");
2458 printf(" validate: enable the NDR validator\n");
2459 printf(" print: enable debugging of the packets\n");
2460 printf(" bigendian: use bigendian RPC\n");
2461 printf(" padcheck: check reply data for non-zero pad bytes\n\n");
2463 printf(" For example, these all connect to the samr pipe:\n\n");
2465 printf(" ncacn_np:myserver\n");
2466 printf(" ncacn_np:myserver[samr]\n");
2467 printf(" ncacn_np:myserver[\\pipe\\samr]\n");
2468 printf(" ncacn_np:myserver[/pipe/samr]\n");
2469 printf(" ncacn_np:myserver[samr,sign,print]\n");
2470 printf(" ncacn_np:myserver[\\pipe\\samr,sign,seal,bigendian]\n");
2471 printf(" ncacn_np:myserver[/pipe/samr,seal,validate]\n");
2472 printf(" ncacn_np:\n");
2473 printf(" ncacn_np:[/pipe/samr]\n\n");
2475 printf(" ncacn_ip_tcp:myserver\n");
2476 printf(" ncacn_ip_tcp:myserver[1024]\n");
2477 printf(" ncacn_ip_tcp:myserver[1024,sign,seal]\n\n");
2479 printf("The unc format is:\n\n");
2481 printf(" //server/share\n\n");
2483 printf("tests are:\n");
2486 for (o = torture_ops; o; o = o->next) {
2487 if (i + strlen(o->name) >= MAX_COLS) {
2491 i+=printf("%s ", o->name);
2495 printf("default test is ALL\n");
2500 static BOOL is_binding_string(const char *binding_string)
2502 TALLOC_CTX *mem_ctx = talloc_init("is_binding_string");
2503 struct dcerpc_binding *binding_struct;
2506 status = dcerpc_parse_binding(mem_ctx, binding_string, &binding_struct);
2508 talloc_free(mem_ctx);
2509 return NT_STATUS_IS_OK(status);
2512 static void max_runtime_handler(int sig)
2514 DEBUG(0,("maximum runtime exceeded for smbtorture - terminating\n"));
2518 /****************************************************************************
2520 ****************************************************************************/
2521 int main(int argc,char *argv[])
2525 BOOL correct = True;
2530 enum {OPT_LOADFILE=1000,OPT_UNCLIST,OPT_TIMELIMIT,OPT_DNS,
2531 OPT_DANGEROUS,OPT_SMB_PORTS};
2532 init_module_fn static_init[] = STATIC_smbtorture_MODULES;
2533 init_module_fn *shared_init = load_samba_modules(NULL, "torture");
2535 struct poptOption long_options[] = {
2537 {"smb-ports", 'p', POPT_ARG_STRING, NULL, OPT_SMB_PORTS, "SMB ports", NULL},
2538 {"seed", 0, POPT_ARG_INT, &torture_seed, 0, "seed", NULL},
2539 {"num-progs", 0, POPT_ARG_INT, &torture_nprocs, 0, "num progs", NULL},
2540 {"num-ops", 0, POPT_ARG_INT, &torture_numops, 0, "num ops", NULL},
2541 {"entries", 0, POPT_ARG_INT, &torture_entries, 0, "entries", NULL},
2542 {"use-oplocks", 'L', POPT_ARG_NONE, &use_oplocks, 0, "use oplocks", NULL},
2543 {"show-all", 0, POPT_ARG_NONE, &torture_showall, 0, "show all", NULL},
2544 {"loadfile", 0, POPT_ARG_STRING, NULL, OPT_LOADFILE, "loadfile", NULL},
2545 {"unclist", 0, POPT_ARG_STRING, NULL, OPT_UNCLIST, "unclist", NULL},
2546 {"timelimit", 't', POPT_ARG_STRING, NULL, OPT_TIMELIMIT, "timelimit", NULL},
2547 {"failures", 'f', POPT_ARG_INT, &torture_failures, 0, "failures", NULL},
2548 {"parse-dns", 'D', POPT_ARG_STRING, NULL, OPT_DNS, "parse-dns", NULL},
2549 {"dangerous", 'X', POPT_ARG_NONE, NULL, OPT_DANGEROUS, "dangerous", NULL},
2550 {"maximum-runtime", 0, POPT_ARG_INT, &max_runtime, 0,
2551 "set maximum time for smbtorture to live", "seconds"},
2553 POPT_COMMON_CONNECTION
2554 POPT_COMMON_CREDENTIALS
2559 #ifdef HAVE_SETBUFFER
2560 setbuffer(stdout, NULL, 0);
2563 register_builtin_ops();
2565 run_init_functions(static_init);
2566 run_init_functions(shared_init);
2568 talloc_free(shared_init);
2570 /* we are never interested in SIGPIPE */
2571 BlockSignals(True,SIGPIPE);
2573 pc = poptGetContext("smbtorture", argc, (const char **) argv, long_options,
2574 POPT_CONTEXT_KEEP_FIRST);
2576 poptSetOtherOptionHelp(pc, "<binding>|<unc> TEST1 TEST2 ...");
2578 while((opt = poptGetNextOpt(pc)) != -1) {
2581 lp_set_cmdline("torture:loadfile", poptGetOptArg(pc));
2584 lp_set_cmdline("torture:unclist", poptGetOptArg(pc));
2587 lp_set_cmdline("torture:timelimit", poptGetOptArg(pc));
2590 parse_dns(poptGetOptArg(pc));
2593 lp_set_cmdline("torture:dangerous", "Yes");
2596 lp_set_cmdline("smb ports", poptGetOptArg(pc));
2599 d_printf("Invalid option %s: %s\n",
2600 poptBadOption(pc, 0), poptStrerror(opt));
2607 /* this will only work if nobody else uses alarm(),
2608 which means it won't work for some tests, but we
2609 can't use the event context method we use for smbd
2610 as so many tests create their own event
2611 context. This will at least catch most cases. */
2612 signal(SIGALRM, max_runtime_handler);
2620 dcerpc_table_init();
2622 if (torture_seed == 0) {
2623 torture_seed = time(NULL);
2625 printf("Using seed %d\n", torture_seed);
2626 srandom(torture_seed);
2628 argv_new = discard_const_p(char *, poptGetArgs(pc));
2631 for (i=0; i<argc; i++) {
2632 if (argv_new[i] == NULL) {
2643 for(p = argv_new[1]; *p; p++) {
2648 /* see if its a RPC transport specifier */
2649 if (is_binding_string(argv_new[1])) {
2650 lp_set_cmdline("torture:binding", argv_new[1]);
2652 char *binding = NULL;
2653 char *host = NULL, *share = NULL;
2655 if (!smbcli_parse_unc(argv_new[1], NULL, &host, &share)) {
2656 d_printf("Invalid option: %s is not a valid torture target (share or binding string)\n\n", argv_new[1]);
2660 lp_set_cmdline("torture:host", host);
2661 lp_set_cmdline("torture:share", share);
2662 asprintf(&binding, "ncacn_np:%s", host);
2663 lp_set_cmdline("torture:binding", binding);
2666 if (argc_new == 0) {
2667 printf("You must specify a test to run, or 'ALL'\n");
2669 for (i=2;i<argc_new;i++) {
2670 if (!run_test(argv_new[i])) {