r14379: Build torture/rpc/ as a seperate smbtorture module. Move helper
[ira/wip.git] / source4 / torture / torture.c
1 /* 
2    Unix SMB/CIFS implementation.
3    SMB torture tester
4    Copyright (C) Andrew Tridgell 1997-2003
5    Copyright (C) Jelmer Vernooij 2006
6    
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.
11    
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.
16    
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.
20 */
21
22 #include "includes.h"
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
37 #include "torture/basic/proto.h"
38 #include "torture/raw/proto.h"
39 #include "torture/smb2/proto.h"
40 #include "torture/rap/proto.h"
41 #include "torture/auth/proto.h"
42 #include "torture/local/proto.h"
43 #include "torture/nbench/proto.h"
44 #include "torture/ldap/proto.h"
45 #include "torture/com/proto.h"
46 #include "torture/nbt/proto.h"
47 #include "torture/libnet/proto.h"
48 #include "torture/torture.h"
49 #include "build.h"
50 #include "dlinklist.h"
51
52 int torture_nprocs=4;
53 int torture_numops=10;
54 int torture_entries=1000;
55 int torture_failures=1;
56 int torture_seed=0;
57 static int procnum; /* records process count number when forking */
58 static struct smbcli_state *current_cli;
59 static BOOL use_oplocks;
60 static BOOL use_level_II_oplocks;
61 #define MAX_COLS 80 /* FIXME: Determine this at run-time */
62
63 BOOL torture_showall = False;
64
65 #define CHECK_MAX_FAILURES(label) do { if (++failures >= torture_failures) goto label; } while (0)
66
67 static struct smbcli_state *open_nbt_connection(void)
68 {
69         struct nbt_name called, calling;
70         struct smbcli_state *cli;
71         const char *host = lp_parm_string(-1, "torture", "host");
72
73         make_nbt_name_client(&calling, lp_netbios_name());
74
75         nbt_choose_called_name(NULL, &called, host, NBT_NAME_SERVER);
76
77         cli = smbcli_state_init(NULL);
78         if (!cli) {
79                 printf("Failed initialize smbcli_struct to connect with %s\n", host);
80                 goto failed;
81         }
82
83         if (!smbcli_socket_connect(cli, host)) {
84                 printf("Failed to connect with %s\n", host);
85                 goto failed;
86         }
87
88         if (!smbcli_transport_establish(cli, &calling, &called)) {
89                 printf("%s rejected the session\n",host);
90                 goto failed;
91         }
92
93         return cli;
94
95 failed:
96         talloc_free(cli);
97         return NULL;
98 }
99
100 BOOL torture_open_connection_share(TALLOC_CTX *mem_ctx,
101                                    struct smbcli_state **c, 
102                                    const char *hostname, 
103                                    const char *sharename,
104                                    struct event_context *ev)
105 {
106         NTSTATUS status;
107
108         status = smbcli_full_connection(mem_ctx, c, hostname, 
109                                         sharename, NULL,
110                                         cmdline_credentials, ev);
111         if (!NT_STATUS_IS_OK(status)) {
112                 printf("Failed to open connection - %s\n", nt_errstr(status));
113                 return False;
114         }
115
116         (*c)->transport->options.use_oplocks = use_oplocks;
117         (*c)->transport->options.use_level2_oplocks = use_level_II_oplocks;
118
119         return True;
120 }
121
122 BOOL torture_open_connection(struct smbcli_state **c)
123 {
124         const char *host = lp_parm_string(-1, "torture", "host");
125         const char *share = lp_parm_string(-1, "torture", "share");
126
127         return torture_open_connection_share(NULL, c, host, share, NULL);
128 }
129
130
131
132 BOOL torture_close_connection(struct smbcli_state *c)
133 {
134         BOOL ret = True;
135         if (!c) return True;
136         if (NT_STATUS_IS_ERR(smbcli_tdis(c))) {
137                 printf("tdis failed (%s)\n", smbcli_errstr(c->tree));
138                 ret = False;
139         }
140         talloc_free(c);
141         return ret;
142 }
143
144
145 /* check if the server produced the expected error code */
146 BOOL check_error(const char *location, struct smbcli_state *c, 
147                  uint8_t eclass, uint32_t ecode, NTSTATUS nterr)
148 {
149         NTSTATUS status;
150         
151         status = smbcli_nt_error(c->tree);
152         if (NT_STATUS_IS_DOS(status)) {
153                 int class, num;
154                 class = NT_STATUS_DOS_CLASS(status);
155                 num = NT_STATUS_DOS_CODE(status);
156                 if (eclass != class || ecode != num) {
157                         printf("unexpected error code %s\n", nt_errstr(status));
158                         printf(" expected %s or %s (at %s)\n", 
159                                nt_errstr(NT_STATUS_DOS(eclass, ecode)), 
160                                nt_errstr(nterr), location);
161                         return False;
162                 }
163         } else {
164                 if (!NT_STATUS_EQUAL(nterr, status)) {
165                         printf("unexpected error code %s\n", nt_errstr(status));
166                         printf(" expected %s (at %s)\n", nt_errstr(nterr), location);
167                         return False;
168                 }
169         }
170
171         return True;
172 }
173
174
175 static BOOL wait_lock(struct smbcli_state *c, int fnum, uint32_t offset, uint32_t len)
176 {
177         while (NT_STATUS_IS_ERR(smbcli_lock(c->tree, fnum, offset, len, -1, WRITE_LOCK))) {
178                 if (!check_error(__location__, c, ERRDOS, ERRlock, NT_STATUS_LOCK_NOT_GRANTED)) return False;
179         }
180         return True;
181 }
182
183
184 static BOOL rw_torture(struct smbcli_state *c)
185 {
186         const char *lockfname = "\\torture.lck";
187         char *fname;
188         int fnum;
189         int fnum2;
190         pid_t pid2, pid = getpid();
191         int i, j;
192         uint8_t buf[1024];
193         BOOL correct = True;
194
195         fnum2 = smbcli_open(c->tree, lockfname, O_RDWR | O_CREAT | O_EXCL, 
196                          DENY_NONE);
197         if (fnum2 == -1)
198                 fnum2 = smbcli_open(c->tree, lockfname, O_RDWR, DENY_NONE);
199         if (fnum2 == -1) {
200                 printf("open of %s failed (%s)\n", lockfname, smbcli_errstr(c->tree));
201                 return False;
202         }
203
204
205         for (i=0;i<torture_numops;i++) {
206                 uint_t n = (uint_t)random()%10;
207                 if (i % 10 == 0) {
208                         printf("%d\r", i); fflush(stdout);
209                 }
210                 asprintf(&fname, "\\torture.%u", n);
211
212                 if (!wait_lock(c, fnum2, n*sizeof(int), sizeof(int))) {
213                         return False;
214                 }
215
216                 fnum = smbcli_open(c->tree, fname, O_RDWR | O_CREAT | O_TRUNC, DENY_ALL);
217                 if (fnum == -1) {
218                         printf("open failed (%s)\n", smbcli_errstr(c->tree));
219                         correct = False;
220                         break;
221                 }
222
223                 if (smbcli_write(c->tree, fnum, 0, &pid, 0, sizeof(pid)) != sizeof(pid)) {
224                         printf("write failed (%s)\n", smbcli_errstr(c->tree));
225                         correct = False;
226                 }
227
228                 for (j=0;j<50;j++) {
229                         if (smbcli_write(c->tree, fnum, 0, buf, 
230                                       sizeof(pid)+(j*sizeof(buf)), 
231                                       sizeof(buf)) != sizeof(buf)) {
232                                 printf("write failed (%s)\n", smbcli_errstr(c->tree));
233                                 correct = False;
234                         }
235                 }
236
237                 pid2 = 0;
238
239                 if (smbcli_read(c->tree, fnum, &pid2, 0, sizeof(pid)) != sizeof(pid)) {
240                         printf("read failed (%s)\n", smbcli_errstr(c->tree));
241                         correct = False;
242                 }
243
244                 if (pid2 != pid) {
245                         printf("data corruption!\n");
246                         correct = False;
247                 }
248
249                 if (NT_STATUS_IS_ERR(smbcli_close(c->tree, fnum))) {
250                         printf("close failed (%s)\n", smbcli_errstr(c->tree));
251                         correct = False;
252                 }
253
254                 if (NT_STATUS_IS_ERR(smbcli_unlink(c->tree, fname))) {
255                         printf("unlink failed (%s)\n", smbcli_errstr(c->tree));
256                         correct = False;
257                 }
258
259                 if (NT_STATUS_IS_ERR(smbcli_unlock(c->tree, fnum2, n*sizeof(int), sizeof(int)))) {
260                         printf("unlock failed (%s)\n", smbcli_errstr(c->tree));
261                         correct = False;
262                 }
263                 free(fname);
264         }
265
266         smbcli_close(c->tree, fnum2);
267         smbcli_unlink(c->tree, lockfname);
268
269         printf("%d\n", i);
270
271         return correct;
272 }
273
274 static BOOL run_torture(struct smbcli_state *cli, int dummy)
275 {
276         BOOL ret;
277
278         ret = rw_torture(cli);
279         
280         if (!torture_close_connection(cli)) {
281                 ret = False;
282         }
283
284         return ret;
285 }
286
287
288 static BOOL rw_torture2(struct smbcli_state *c1, struct smbcli_state *c2)
289 {
290         const char *lockfname = "\\torture2.lck";
291         int fnum1;
292         int fnum2;
293         int i;
294         uint8_t buf[131072];
295         uint8_t buf_rd[131072];
296         BOOL correct = True;
297         ssize_t bytes_read, bytes_written;
298
299         if (smbcli_deltree(c1->tree, lockfname) == -1) {
300                 printf("unlink failed (%s)\n", smbcli_errstr(c1->tree));
301         }
302
303         fnum1 = smbcli_open(c1->tree, lockfname, O_RDWR | O_CREAT | O_EXCL, 
304                          DENY_NONE);
305         if (fnum1 == -1) {
306                 printf("first open read/write of %s failed (%s)\n",
307                                 lockfname, smbcli_errstr(c1->tree));
308                 return False;
309         }
310         fnum2 = smbcli_open(c2->tree, lockfname, O_RDONLY, 
311                          DENY_NONE);
312         if (fnum2 == -1) {
313                 printf("second open read-only of %s failed (%s)\n",
314                                 lockfname, smbcli_errstr(c2->tree));
315                 smbcli_close(c1->tree, fnum1);
316                 return False;
317         }
318
319         printf("Checking data integrity over %d ops\n", torture_numops);
320
321         for (i=0;i<torture_numops;i++)
322         {
323                 size_t buf_size = ((uint_t)random()%(sizeof(buf)-1))+ 1;
324                 if (i % 10 == 0) {
325                         printf("%d\r", i); fflush(stdout);
326                 }
327
328                 generate_random_buffer(buf, buf_size);
329
330                 if ((bytes_written = smbcli_write(c1->tree, fnum1, 0, buf, 0, buf_size)) != buf_size) {
331                         printf("write failed (%s)\n", smbcli_errstr(c1->tree));
332                         printf("wrote %d, expected %d\n", (int)bytes_written, (int)buf_size); 
333                         correct = False;
334                         break;
335                 }
336
337                 if ((bytes_read = smbcli_read(c2->tree, fnum2, buf_rd, 0, buf_size)) != buf_size) {
338                         printf("read failed (%s)\n", smbcli_errstr(c2->tree));
339                         printf("read %d, expected %d\n", (int)bytes_read, (int)buf_size); 
340                         correct = False;
341                         break;
342                 }
343
344                 if (memcmp(buf_rd, buf, buf_size) != 0)
345                 {
346                         printf("read/write compare failed\n");
347                         correct = False;
348                         break;
349                 }
350         }
351
352         if (NT_STATUS_IS_ERR(smbcli_close(c2->tree, fnum2))) {
353                 printf("close failed (%s)\n", smbcli_errstr(c2->tree));
354                 correct = False;
355         }
356         if (NT_STATUS_IS_ERR(smbcli_close(c1->tree, fnum1))) {
357                 printf("close failed (%s)\n", smbcli_errstr(c1->tree));
358                 correct = False;
359         }
360
361         if (NT_STATUS_IS_ERR(smbcli_unlink(c1->tree, lockfname))) {
362                 printf("unlink failed (%s)\n", smbcli_errstr(c1->tree));
363                 correct = False;
364         }
365
366         return correct;
367 }
368
369 #define BOOLSTR(b) ((b) ? "Yes" : "No")
370
371 static BOOL run_readwritetest(void)
372 {
373         struct smbcli_state *cli1, *cli2;
374         BOOL test1, test2 = True;
375
376         if (!torture_open_connection(&cli1) || !torture_open_connection(&cli2)) {
377                 return False;
378         }
379
380         printf("starting readwritetest\n");
381
382         test1 = rw_torture2(cli1, cli2);
383         printf("Passed readwritetest v1: %s\n", BOOLSTR(test1));
384
385         if (test1) {
386                 test2 = rw_torture2(cli1, cli1);
387                 printf("Passed readwritetest v2: %s\n", BOOLSTR(test2));
388         }
389
390         if (!torture_close_connection(cli1)) {
391                 test1 = False;
392         }
393
394         if (!torture_close_connection(cli2)) {
395                 test2 = False;
396         }
397
398         return (test1 && test2);
399 }
400
401 /*
402   this checks to see if a secondary tconx can use open files from an
403   earlier tconx
404  */
405 static BOOL run_tcon_test(void)
406 {
407         struct smbcli_state *cli;
408         const char *fname = "\\tcontest.tmp";
409         int fnum1;
410         uint16_t cnum1, cnum2, cnum3;
411         uint16_t vuid1, vuid2;
412         uint8_t buf[4];
413         BOOL ret = True;
414         struct smbcli_tree *tree1;
415         const char *host = lp_parm_string(-1, "torture", "host");
416         const char *share = lp_parm_string(-1, "torture", "share");
417         const char *password = lp_parm_string(-1, "torture", "password");
418
419         if (!torture_open_connection(&cli)) {
420                 return False;
421         }
422
423         printf("starting tcontest\n");
424
425         if (smbcli_deltree(cli->tree, fname) == -1) {
426                 printf("unlink of %s failed (%s)\n", fname, smbcli_errstr(cli->tree));
427         }
428
429         fnum1 = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
430         if (fnum1 == -1) {
431                 printf("open of %s failed (%s)\n", fname, smbcli_errstr(cli->tree));
432                 return False;
433         }
434
435         cnum1 = cli->tree->tid;
436         vuid1 = cli->session->vuid;
437
438         memset(&buf, 0, 4); /* init buf so valgrind won't complain */
439         if (smbcli_write(cli->tree, fnum1, 0, buf, 130, 4) != 4) {
440                 printf("initial write failed (%s)\n", smbcli_errstr(cli->tree));
441                 return False;
442         }
443
444         tree1 = cli->tree;      /* save old tree connection */
445         if (NT_STATUS_IS_ERR(smbcli_tconX(cli, share, "?????", password))) {
446                 printf("%s refused 2nd tree connect (%s)\n", host,
447                            smbcli_errstr(cli->tree));
448                 talloc_free(cli);
449                 return False;
450         }
451
452         cnum2 = cli->tree->tid;
453         cnum3 = MAX(cnum1, cnum2) + 1; /* any invalid number */
454         vuid2 = cli->session->vuid + 1;
455
456         /* try a write with the wrong tid */
457         cli->tree->tid = cnum2;
458
459         if (smbcli_write(cli->tree, fnum1, 0, buf, 130, 4) == 4) {
460                 printf("* server allows write with wrong TID\n");
461                 ret = False;
462         } else {
463                 printf("server fails write with wrong TID : %s\n", smbcli_errstr(cli->tree));
464         }
465
466
467         /* try a write with an invalid tid */
468         cli->tree->tid = cnum3;
469
470         if (smbcli_write(cli->tree, fnum1, 0, buf, 130, 4) == 4) {
471                 printf("* server allows write with invalid TID\n");
472                 ret = False;
473         } else {
474                 printf("server fails write with invalid TID : %s\n", smbcli_errstr(cli->tree));
475         }
476
477         /* try a write with an invalid vuid */
478         cli->session->vuid = vuid2;
479         cli->tree->tid = cnum1;
480
481         if (smbcli_write(cli->tree, fnum1, 0, buf, 130, 4) == 4) {
482                 printf("* server allows write with invalid VUID\n");
483                 ret = False;
484         } else {
485                 printf("server fails write with invalid VUID : %s\n", smbcli_errstr(cli->tree));
486         }
487
488         cli->session->vuid = vuid1;
489         cli->tree->tid = cnum1;
490
491         if (NT_STATUS_IS_ERR(smbcli_close(cli->tree, fnum1))) {
492                 printf("close failed (%s)\n", smbcli_errstr(cli->tree));
493                 return False;
494         }
495
496         cli->tree->tid = cnum2;
497
498         if (NT_STATUS_IS_ERR(smbcli_tdis(cli))) {
499                 printf("secondary tdis failed (%s)\n", smbcli_errstr(cli->tree));
500                 return False;
501         }
502
503         cli->tree = tree1;  /* restore initial tree */
504         cli->tree->tid = cnum1;
505
506         smbcli_unlink(tree1, fname);
507
508         if (!torture_close_connection(cli)) {
509                 return False;
510         }
511
512         return ret;
513 }
514
515
516
517 static BOOL tcon_devtest(struct smbcli_state *cli,
518                          const char *myshare, const char *devtype,
519                          NTSTATUS expected_error)
520 {
521         BOOL status;
522         BOOL ret;
523         const char *password = lp_parm_string(-1, "torture", "password");
524
525         status = NT_STATUS_IS_OK(smbcli_tconX(cli, myshare, devtype, 
526                                                 password));
527
528         printf("Trying share %s with devtype %s\n", myshare, devtype);
529
530         if (NT_STATUS_IS_OK(expected_error)) {
531                 if (status) {
532                         ret = True;
533                 } else {
534                         printf("tconX to share %s with type %s "
535                                "should have succeeded but failed\n",
536                                myshare, devtype);
537                         ret = False;
538                 }
539                 smbcli_tdis(cli);
540         } else {
541                 if (status) {
542                         printf("tconx to share %s with type %s "
543                                "should have failed but succeeded\n",
544                                myshare, devtype);
545                         ret = False;
546                 } else {
547                         if (NT_STATUS_EQUAL(smbcli_nt_error(cli->tree),
548                                             expected_error)) {
549                                 ret = True;
550                         } else {
551                                 printf("Returned unexpected error\n");
552                                 ret = False;
553                         }
554                 }
555         }
556         return ret;
557 }
558
559 /*
560  checks for correct tconX support
561  */
562 static BOOL run_tcon_devtype_test(void)
563 {
564         struct smbcli_state *cli1 = NULL;
565         NTSTATUS status;
566         BOOL ret = True;
567         const char *host = lp_parm_string(-1, "torture", "host");
568         const char *share = lp_parm_string(-1, "torture", "share");
569         
570         status = smbcli_full_connection(NULL,
571                                         &cli1, host, 
572                                         share, NULL,
573                                         cmdline_credentials, NULL);
574
575         if (!NT_STATUS_IS_OK(status)) {
576                 printf("could not open connection\n");
577                 return False;
578         }
579
580         if (!tcon_devtest(cli1, "IPC$", "A:", NT_STATUS_BAD_DEVICE_TYPE))
581                 ret = False;
582
583         if (!tcon_devtest(cli1, "IPC$", "?????", NT_STATUS_OK))
584                 ret = False;
585
586         if (!tcon_devtest(cli1, "IPC$", "LPT:", NT_STATUS_BAD_DEVICE_TYPE))
587                 ret = False;
588
589         if (!tcon_devtest(cli1, "IPC$", "IPC", NT_STATUS_OK))
590                 ret = False;
591                         
592         if (!tcon_devtest(cli1, "IPC$", "FOOBA", NT_STATUS_BAD_DEVICE_TYPE))
593                 ret = False;
594
595         if (!tcon_devtest(cli1, share, "A:", NT_STATUS_OK))
596                 ret = False;
597
598         if (!tcon_devtest(cli1, share, "?????", NT_STATUS_OK))
599                 ret = False;
600
601         if (!tcon_devtest(cli1, share, "LPT:", NT_STATUS_BAD_DEVICE_TYPE))
602                 ret = False;
603
604         if (!tcon_devtest(cli1, share, "IPC", NT_STATUS_BAD_DEVICE_TYPE))
605                 ret = False;
606                         
607         if (!tcon_devtest(cli1, share, "FOOBA", NT_STATUS_BAD_DEVICE_TYPE))
608                 ret = False;
609
610         talloc_free(cli1);
611
612         if (ret)
613                 printf("Passed tcondevtest\n");
614
615         return ret;
616 }
617
618
619 /*
620 test whether fnums and tids open on one VC are available on another (a major
621 security hole)
622 */
623 static BOOL run_fdpasstest(void)
624 {
625         struct smbcli_state *cli1, *cli2;
626         const char *fname = "\\fdpass.tst";
627         int fnum1, oldtid;
628         uint8_t buf[1024];
629
630         if (!torture_open_connection(&cli1) || !torture_open_connection(&cli2)) {
631                 return False;
632         }
633
634         printf("starting fdpasstest\n");
635
636         smbcli_unlink(cli1->tree, fname);
637
638         printf("Opening a file on connection 1\n");
639
640         fnum1 = smbcli_open(cli1->tree, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
641         if (fnum1 == -1) {
642                 printf("open of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
643                 return False;
644         }
645
646         printf("writing to file on connection 1\n");
647
648         if (smbcli_write(cli1->tree, fnum1, 0, "hello world\n", 0, 13) != 13) {
649                 printf("write failed (%s)\n", smbcli_errstr(cli1->tree));
650                 return False;
651         }
652
653         oldtid = cli2->tree->tid;
654         cli2->session->vuid = cli1->session->vuid;
655         cli2->tree->tid = cli1->tree->tid;
656         cli2->session->pid = cli1->session->pid;
657
658         printf("reading from file on connection 2\n");
659
660         if (smbcli_read(cli2->tree, fnum1, buf, 0, 13) == 13) {
661                 printf("read succeeded! nasty security hole [%s]\n",
662                        buf);
663                 return False;
664         }
665
666         smbcli_close(cli1->tree, fnum1);
667         smbcli_unlink(cli1->tree, fname);
668
669         cli2->tree->tid = oldtid;
670
671         torture_close_connection(cli1);
672         torture_close_connection(cli2);
673
674         printf("finished fdpasstest\n");
675         return True;
676 }
677
678
679 /*
680 test the timing of deferred open requests
681 */
682 static BOOL run_deferopen(struct smbcli_state *cli, int dummy)
683 {
684         const char *fname = "\\defer_open_test.dat";
685         int retries=4;
686         int i = 0;
687         BOOL correct = True;
688
689         if (retries <= 0) {
690                 printf("failed to connect\n");
691                 return False;
692         }
693
694         printf("Testing deferred open requests.\n");
695
696         while (i < 4) {
697                 int fnum = -1;
698
699                 do {
700                         struct timeval tv;
701                         tv = timeval_current();
702                         fnum = smbcli_nt_create_full(cli->tree, fname, 0, 
703                                                      SEC_RIGHTS_FILE_ALL,
704                                                      FILE_ATTRIBUTE_NORMAL, 
705                                                      NTCREATEX_SHARE_ACCESS_NONE,
706                                                      NTCREATEX_DISP_OPEN_IF, 0, 0);
707                         if (fnum != -1) {
708                                 break;
709                         }
710                         if (NT_STATUS_EQUAL(smbcli_nt_error(cli->tree),NT_STATUS_SHARING_VIOLATION)) {
711                                 double e = timeval_elapsed(&tv);
712                                 if (e < 0.5 || e > 1.5) {
713                                         fprintf(stderr,"Timing incorrect %.2f violation\n",
714                                                 e);
715                                 }
716                         }
717                 } while (NT_STATUS_EQUAL(smbcli_nt_error(cli->tree),NT_STATUS_SHARING_VIOLATION));
718
719                 if (fnum == -1) {
720                         fprintf(stderr,"Failed to open %s, error=%s\n", fname, smbcli_errstr(cli->tree));
721                         return False;
722                 }
723
724                 printf("pid %u open %d\n", getpid(), i);
725
726                 sleep(10);
727                 i++;
728                 if (NT_STATUS_IS_ERR(smbcli_close(cli->tree, fnum))) {
729                         fprintf(stderr,"Failed to close %s, error=%s\n", fname, smbcli_errstr(cli->tree));
730                         return False;
731                 }
732                 sleep(2);
733         }
734
735         if (NT_STATUS_IS_ERR(smbcli_unlink(cli->tree, fname))) {
736                 /* All until the last unlink will fail with sharing violation. */
737                 if (!NT_STATUS_EQUAL(smbcli_nt_error(cli->tree),NT_STATUS_SHARING_VIOLATION)) {
738                         printf("unlink of %s failed (%s)\n", fname, smbcli_errstr(cli->tree));
739                         correct = False;
740                 }
741         }
742
743         printf("deferred test finished\n");
744         if (!torture_close_connection(cli)) {
745                 correct = False;
746         }
747         return correct;
748 }
749
750 /*
751 test how many open files this server supports on the one socket
752 */
753 static BOOL run_maxfidtest(struct smbcli_state *cli, int dummy)
754 {
755 #define MAXFID_TEMPLATE "\\maxfid\\fid%d\\maxfid.%d.%d"
756         char *fname;
757         int fnums[0x11000], i;
758         int retries=4, maxfid;
759         BOOL correct = True;
760
761         if (retries <= 0) {
762                 printf("failed to connect\n");
763                 return False;
764         }
765
766         if (smbcli_deltree(cli->tree, "\\maxfid") == -1) {
767                 printf("Failed to deltree \\maxfid - %s\n",
768                        smbcli_errstr(cli->tree));
769                 return False;
770         }
771         if (NT_STATUS_IS_ERR(smbcli_mkdir(cli->tree, "\\maxfid"))) {
772                 printf("Failed to mkdir \\maxfid, error=%s\n", 
773                        smbcli_errstr(cli->tree));
774                 return False;
775         }
776
777         printf("Testing maximum number of open files\n");
778
779         for (i=0; i<0x11000; i++) {
780                 if (i % 1000 == 0) {
781                         asprintf(&fname, "\\maxfid\\fid%d", i/1000);
782                         if (NT_STATUS_IS_ERR(smbcli_mkdir(cli->tree, fname))) {
783                                 printf("Failed to mkdir %s, error=%s\n", 
784                                        fname, smbcli_errstr(cli->tree));
785                                 return False;
786                         }
787                         free(fname);
788                 }
789                 asprintf(&fname, MAXFID_TEMPLATE, i/1000, i,(int)getpid());
790                 if ((fnums[i] = smbcli_open(cli->tree, fname, 
791                                         O_RDWR|O_CREAT|O_TRUNC, DENY_NONE)) ==
792                     -1) {
793                         printf("open of %s failed (%s)\n", 
794                                fname, smbcli_errstr(cli->tree));
795                         printf("maximum fnum is %d\n", i);
796                         break;
797                 }
798                 free(fname);
799                 printf("%6d\r", i);
800         }
801         printf("%6d\n", i);
802         i--;
803
804         maxfid = i;
805
806         printf("cleaning up\n");
807         for (i=0;i<maxfid/2;i++) {
808                 asprintf(&fname, MAXFID_TEMPLATE, i/1000, i,(int)getpid());
809                 if (NT_STATUS_IS_ERR(smbcli_close(cli->tree, fnums[i]))) {
810                         printf("Close of fnum %d failed - %s\n", fnums[i], smbcli_errstr(cli->tree));
811                 }
812                 if (NT_STATUS_IS_ERR(smbcli_unlink(cli->tree, fname))) {
813                         printf("unlink of %s failed (%s)\n", 
814                                fname, smbcli_errstr(cli->tree));
815                         correct = False;
816                 }
817                 free(fname);
818
819                 asprintf(&fname, MAXFID_TEMPLATE, (maxfid-i)/1000, maxfid-i,(int)getpid());
820                 if (NT_STATUS_IS_ERR(smbcli_close(cli->tree, fnums[maxfid-i]))) {
821                         printf("Close of fnum %d failed - %s\n", fnums[maxfid-i], smbcli_errstr(cli->tree));
822                 }
823                 if (NT_STATUS_IS_ERR(smbcli_unlink(cli->tree, fname))) {
824                         printf("unlink of %s failed (%s)\n", 
825                                fname, smbcli_errstr(cli->tree));
826                         correct = False;
827                 }
828                 free(fname);
829
830                 printf("%6d %6d\r", i, maxfid-i);
831         }
832         printf("%6d\n", 0);
833
834         if (smbcli_deltree(cli->tree, "\\maxfid") == -1) {
835                 printf("Failed to deltree \\maxfid - %s\n",
836                        smbcli_errstr(cli->tree));
837                 return False;
838         }
839
840         printf("maxfid test finished\n");
841         if (!torture_close_connection(cli)) {
842                 correct = False;
843         }
844         return correct;
845 #undef MAXFID_TEMPLATE
846 }
847
848 /* send smb negprot commands, not reading the response */
849 static BOOL run_negprot_nowait(void)
850 {
851         int i;
852         struct smbcli_state *cli, *cli2;
853         BOOL correct = True;
854
855         printf("starting negprot nowait test\n");
856
857         cli = open_nbt_connection();
858         if (!cli) {
859                 return False;
860         }
861
862         printf("Filling send buffer\n");
863
864         for (i=0;i<100;i++) {
865                 struct smbcli_request *req;
866                 req = smb_raw_negotiate_send(cli->transport, PROTOCOL_NT1);
867                 event_loop_once(cli->transport->socket->event.ctx);
868                 if (req->state == SMBCLI_REQUEST_ERROR) {
869                         if (i > 0) {
870                                 printf("Failed to fill pipe packet[%d] - %s (ignored)\n", i+1, nt_errstr(req->status));
871                                 break;
872                         } else {
873                                 printf("Failed to fill pipe - %s \n", nt_errstr(req->status));
874                                 torture_close_connection(cli);
875                                 return False;
876                         }
877                 }
878         }
879
880         printf("Opening secondary connection\n");
881         if (!torture_open_connection(&cli2)) {
882                 printf("Failed to open secondary connection\n");
883                 correct = False;
884         }
885
886         if (!torture_close_connection(cli2)) {
887                 printf("Failed to close secondary connection\n");
888                 correct = False;
889         }
890
891         torture_close_connection(cli);
892
893         printf("finished negprot nowait test\n");
894
895         return correct;
896 }
897
898
899 /*
900   This checks how the getatr calls works
901 */
902 static BOOL run_attrtest(void)
903 {
904         struct smbcli_state *cli;
905         int fnum;
906         time_t t, t2;
907         const char *fname = "\\attrib123456789.tst";
908         BOOL correct = True;
909
910         printf("starting attrib test\n");
911
912         if (!torture_open_connection(&cli)) {
913                 return False;
914         }
915
916         smbcli_unlink(cli->tree, fname);
917         fnum = smbcli_open(cli->tree, fname, 
918                         O_RDWR | O_CREAT | O_TRUNC, DENY_NONE);
919         smbcli_close(cli->tree, fnum);
920
921         if (NT_STATUS_IS_ERR(smbcli_getatr(cli->tree, fname, NULL, NULL, &t))) {
922                 printf("getatr failed (%s)\n", smbcli_errstr(cli->tree));
923                 correct = False;
924         }
925
926         printf("New file time is %s", ctime(&t));
927
928         if (abs(t - time(NULL)) > 60*60*24*10) {
929                 printf("ERROR: SMBgetatr bug. time is %s",
930                        ctime(&t));
931                 t = time(NULL);
932                 correct = False;
933         }
934
935         t2 = t-60*60*24; /* 1 day ago */
936
937         printf("Setting file time to %s", ctime(&t2));
938
939         if (NT_STATUS_IS_ERR(smbcli_setatr(cli->tree, fname, 0, t2))) {
940                 printf("setatr failed (%s)\n", smbcli_errstr(cli->tree));
941                 correct = True;
942         }
943
944         if (NT_STATUS_IS_ERR(smbcli_getatr(cli->tree, fname, NULL, NULL, &t))) {
945                 printf("getatr failed (%s)\n", smbcli_errstr(cli->tree));
946                 correct = True;
947         }
948
949         printf("Retrieved file time as %s", ctime(&t));
950
951         if (t != t2) {
952                 printf("ERROR: getatr/setatr bug. times are\n%s",
953                        ctime(&t));
954                 printf("%s", ctime(&t2));
955                 correct = True;
956         }
957
958         smbcli_unlink(cli->tree, fname);
959
960         if (!torture_close_connection(cli)) {
961                 correct = False;
962         }
963
964         printf("attrib test finished\n");
965
966         return correct;
967 }
968
969
970 /*
971   This checks a couple of trans2 calls
972 */
973 static BOOL run_trans2test(void)
974 {
975         struct smbcli_state *cli;
976         int fnum;
977         size_t size;
978         time_t c_time, a_time, m_time, w_time, m_time2;
979         const char *fname = "\\trans2.tst";
980         const char *dname = "\\trans2";
981         const char *fname2 = "\\trans2\\trans2.tst";
982         const char *pname;
983         BOOL correct = True;
984
985         printf("starting trans2 test\n");
986
987         if (!torture_open_connection(&cli)) {
988                 return False;
989         }
990
991         smbcli_unlink(cli->tree, fname);
992
993         printf("Testing qfileinfo\n");
994         
995         fnum = smbcli_open(cli->tree, fname, 
996                         O_RDWR | O_CREAT | O_TRUNC, DENY_NONE);
997         if (NT_STATUS_IS_ERR(smbcli_qfileinfo(cli->tree, fnum, NULL, &size, &c_time, &a_time, &m_time,
998                            NULL, NULL))) {
999                 printf("ERROR: qfileinfo failed (%s)\n", smbcli_errstr(cli->tree));
1000                 correct = False;
1001         }
1002
1003         printf("Testing NAME_INFO\n");
1004
1005         if (NT_STATUS_IS_ERR(smbcli_qfilename(cli->tree, fnum, &pname))) {
1006                 printf("ERROR: qfilename failed (%s)\n", smbcli_errstr(cli->tree));
1007                 correct = False;
1008         }
1009
1010         if (!pname || strcmp(pname, fname)) {
1011                 printf("qfilename gave different name? [%s] [%s]\n",
1012                        fname, pname);
1013                 correct = False;
1014         }
1015
1016         smbcli_close(cli->tree, fnum);
1017         smbcli_unlink(cli->tree, fname);
1018
1019         fnum = smbcli_open(cli->tree, fname, 
1020                         O_RDWR | O_CREAT | O_TRUNC, DENY_NONE);
1021         if (fnum == -1) {
1022                 printf("open of %s failed (%s)\n", fname, smbcli_errstr(cli->tree));
1023                 return False;
1024         }
1025         smbcli_close(cli->tree, fnum);
1026
1027         printf("Checking for sticky create times\n");
1028
1029         if (NT_STATUS_IS_ERR(smbcli_qpathinfo(cli->tree, fname, &c_time, &a_time, &m_time, &size, NULL))) {
1030                 printf("ERROR: qpathinfo failed (%s)\n", smbcli_errstr(cli->tree));
1031                 correct = False;
1032         } else {
1033                 if (c_time != m_time) {
1034                         printf("create time=%s", ctime(&c_time));
1035                         printf("modify time=%s", ctime(&m_time));
1036                         printf("This system appears to have sticky create times\n");
1037                 }
1038                 if (a_time % (60*60) == 0) {
1039                         printf("access time=%s", ctime(&a_time));
1040                         printf("This system appears to set a midnight access time\n");
1041                         correct = False;
1042                 }
1043
1044                 if (abs(m_time - time(NULL)) > 60*60*24*7) {
1045                         printf("ERROR: totally incorrect times - maybe word reversed? mtime=%s", ctime(&m_time));
1046                         correct = False;
1047                 }
1048         }
1049
1050
1051         smbcli_unlink(cli->tree, fname);
1052         fnum = smbcli_open(cli->tree, fname, 
1053                         O_RDWR | O_CREAT | O_TRUNC, DENY_NONE);
1054         smbcli_close(cli->tree, fnum);
1055         if (NT_STATUS_IS_ERR(smbcli_qpathinfo2(cli->tree, fname, &c_time, &a_time, &m_time, &w_time, &size, NULL, NULL))) {
1056                 printf("ERROR: qpathinfo2 failed (%s)\n", smbcli_errstr(cli->tree));
1057                 correct = False;
1058         } else {
1059                 if (w_time < 60*60*24*2) {
1060                         printf("write time=%s", ctime(&w_time));
1061                         printf("This system appears to set a initial 0 write time\n");
1062                         correct = False;
1063                 }
1064         }
1065
1066         smbcli_unlink(cli->tree, fname);
1067
1068
1069         /* check if the server updates the directory modification time
1070            when creating a new file */
1071         if (NT_STATUS_IS_ERR(smbcli_mkdir(cli->tree, dname))) {
1072                 printf("ERROR: mkdir failed (%s)\n", smbcli_errstr(cli->tree));
1073                 correct = False;
1074         }
1075         sleep(3);
1076         if (NT_STATUS_IS_ERR(smbcli_qpathinfo2(cli->tree, "\\trans2\\", &c_time, &a_time, &m_time, &w_time, &size, NULL, NULL))) {
1077                 printf("ERROR: qpathinfo2 failed (%s)\n", smbcli_errstr(cli->tree));
1078                 correct = False;
1079         }
1080
1081         fnum = smbcli_open(cli->tree, fname2, 
1082                         O_RDWR | O_CREAT | O_TRUNC, DENY_NONE);
1083         smbcli_write(cli->tree, fnum,  0, &fnum, 0, sizeof(fnum));
1084         smbcli_close(cli->tree, fnum);
1085         if (NT_STATUS_IS_ERR(smbcli_qpathinfo2(cli->tree, "\\trans2\\", &c_time, &a_time, &m_time2, &w_time, &size, NULL, NULL))) {
1086                 printf("ERROR: qpathinfo2 failed (%s)\n", smbcli_errstr(cli->tree));
1087                 correct = False;
1088         } else {
1089                 if (m_time2 == m_time) {
1090                         printf("This system does not update directory modification times\n");
1091                         correct = False;
1092                 }
1093         }
1094         smbcli_unlink(cli->tree, fname2);
1095         smbcli_rmdir(cli->tree, dname);
1096
1097         if (!torture_close_connection(cli)) {
1098                 correct = False;
1099         }
1100
1101         printf("trans2 test finished\n");
1102
1103         return correct;
1104 }
1105
1106
1107
1108 /* FIRST_DESIRED_ACCESS   0xf019f */
1109 #define FIRST_DESIRED_ACCESS   SEC_FILE_READ_DATA|SEC_FILE_WRITE_DATA|SEC_FILE_APPEND_DATA|\
1110                                SEC_FILE_READ_EA|                           /* 0xf */ \
1111                                SEC_FILE_WRITE_EA|SEC_FILE_READ_ATTRIBUTE|     /* 0x90 */ \
1112                                SEC_FILE_WRITE_ATTRIBUTE|                  /* 0x100 */ \
1113                                SEC_STD_DELETE|SEC_STD_READ_CONTROL|\
1114                                SEC_STD_WRITE_DAC|SEC_STD_WRITE_OWNER     /* 0xf0000 */
1115 /* SECOND_DESIRED_ACCESS  0xe0080 */
1116 #define SECOND_DESIRED_ACCESS  SEC_FILE_READ_ATTRIBUTE|                   /* 0x80 */ \
1117                                SEC_STD_READ_CONTROL|SEC_STD_WRITE_DAC|\
1118                                SEC_STD_WRITE_OWNER                      /* 0xe0000 */
1119
1120 #if 0
1121 #define THIRD_DESIRED_ACCESS   FILE_READ_ATTRIBUTE|                   /* 0x80 */ \
1122                                READ_CONTROL|WRITE_DAC|\
1123                                SEC_FILE_READ_DATA|\
1124                                WRITE_OWNER                      /* */
1125 #endif
1126
1127 /*
1128   Test ntcreate calls made by xcopy
1129  */
1130 static BOOL run_xcopy(void)
1131 {
1132         struct smbcli_state *cli1;
1133         const char *fname = "\\test.txt";
1134         BOOL correct = True;
1135         int fnum1, fnum2;
1136
1137         printf("starting xcopy test\n");
1138         
1139         if (!torture_open_connection(&cli1)) {
1140                 return False;
1141         }
1142         
1143         fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0,
1144                                       FIRST_DESIRED_ACCESS, 
1145                                       FILE_ATTRIBUTE_ARCHIVE,
1146                                       NTCREATEX_SHARE_ACCESS_NONE, 
1147                                       NTCREATEX_DISP_OVERWRITE_IF, 
1148                                       0x4044, 0);
1149
1150         if (fnum1 == -1) {
1151                 printf("First open failed - %s\n", smbcli_errstr(cli1->tree));
1152                 return False;
1153         }
1154
1155         fnum2 = smbcli_nt_create_full(cli1->tree, fname, 0,
1156                                    SECOND_DESIRED_ACCESS, 0,
1157                                    NTCREATEX_SHARE_ACCESS_READ|NTCREATEX_SHARE_ACCESS_WRITE|NTCREATEX_SHARE_ACCESS_DELETE, NTCREATEX_DISP_OPEN, 
1158                                    0x200000, 0);
1159         if (fnum2 == -1) {
1160                 printf("second open failed - %s\n", smbcli_errstr(cli1->tree));
1161                 return False;
1162         }
1163         
1164         if (!torture_close_connection(cli1)) {
1165                 correct = False;
1166         }
1167         
1168         return correct;
1169 }
1170
1171
1172 /*
1173   see how many RPC pipes we can open at once
1174 */
1175 static BOOL run_pipe_number(void)
1176 {
1177         struct smbcli_state *cli1;
1178         const char *pipe_name = "\\WKSSVC";
1179         int fnum;
1180         int num_pipes = 0;
1181
1182         printf("starting pipenumber test\n");
1183         if (!torture_open_connection(&cli1)) {
1184                 return False;
1185         }
1186
1187         while(1) {
1188                 fnum = smbcli_nt_create_full(cli1->tree, pipe_name, 0, SEC_FILE_READ_DATA, FILE_ATTRIBUTE_NORMAL,
1189                                    NTCREATEX_SHARE_ACCESS_READ|NTCREATEX_SHARE_ACCESS_WRITE, NTCREATEX_DISP_OPEN_IF, 0, 0);
1190
1191                 if (fnum == -1) {
1192                         printf("Open of pipe %s failed with error (%s)\n", pipe_name, smbcli_errstr(cli1->tree));
1193                         break;
1194                 }
1195                 num_pipes++;
1196                 printf("%d\r", num_pipes);
1197                 fflush(stdout);
1198         }
1199
1200         printf("pipe_number test - we can open %d %s pipes.\n", num_pipes, pipe_name );
1201         torture_close_connection(cli1);
1202         return True;
1203 }
1204
1205
1206
1207
1208 /*
1209   open N connections to the server and just hold them open
1210   used for testing performance when there are N idle users
1211   already connected
1212  */
1213  static BOOL torture_holdcon(void)
1214 {
1215         int i;
1216         struct smbcli_state **cli;
1217         int num_dead = 0;
1218
1219         printf("Opening %d connections\n", torture_numops);
1220         
1221         cli = malloc_array_p(struct smbcli_state *, torture_numops);
1222
1223         for (i=0;i<torture_numops;i++) {
1224                 if (!torture_open_connection(&cli[i])) {
1225                         return False;
1226                 }
1227                 printf("opened %d connections\r", i);
1228                 fflush(stdout);
1229         }
1230
1231         printf("\nStarting pings\n");
1232
1233         while (1) {
1234                 for (i=0;i<torture_numops;i++) {
1235                         NTSTATUS status;
1236                         if (cli[i]) {
1237                                 status = smbcli_chkpath(cli[i]->tree, "\\");
1238                                 if (!NT_STATUS_IS_OK(status)) {
1239                                         printf("Connection %d is dead\n", i);
1240                                         cli[i] = NULL;
1241                                         num_dead++;
1242                                 }
1243                                 usleep(100);
1244                         }
1245                 }
1246
1247                 if (num_dead == torture_numops) {
1248                         printf("All connections dead - finishing\n");
1249                         break;
1250                 }
1251
1252                 printf(".");
1253                 fflush(stdout);
1254         }
1255
1256         return True;
1257 }
1258
1259 /*
1260   Try with a wrong vuid and check error message.
1261  */
1262
1263 static BOOL run_vuidtest(void)
1264 {
1265         struct smbcli_state *cli;
1266         const char *fname = "\\vuid.tst";
1267         int fnum;
1268         size_t size;
1269         time_t c_time, a_time, m_time;
1270         BOOL correct = True;
1271
1272         uint16_t orig_vuid;
1273         NTSTATUS result;
1274
1275         printf("starting vuid test\n");
1276
1277         if (!torture_open_connection(&cli)) {
1278                 return False;
1279         }
1280
1281         smbcli_unlink(cli->tree, fname);
1282
1283         fnum = smbcli_open(cli->tree, fname, 
1284                         O_RDWR | O_CREAT | O_TRUNC, DENY_NONE);
1285
1286         orig_vuid = cli->session->vuid;
1287
1288         cli->session->vuid += 1234;
1289
1290         printf("Testing qfileinfo with wrong vuid\n");
1291         
1292         if (NT_STATUS_IS_OK(result = smbcli_qfileinfo(cli->tree, fnum, NULL,
1293                                                    &size, &c_time, &a_time,
1294                                                    &m_time, NULL, NULL))) {
1295                 printf("ERROR: qfileinfo passed with wrong vuid\n");
1296                 correct = False;
1297         }
1298
1299         if (!NT_STATUS_EQUAL(cli->transport->error.e.nt_status, 
1300                              NT_STATUS_DOS(ERRSRV, ERRbaduid)) &&
1301             !NT_STATUS_EQUAL(cli->transport->error.e.nt_status, 
1302                              NT_STATUS_INVALID_HANDLE)) {
1303                 printf("ERROR: qfileinfo should have returned DOS error "
1304                        "ERRSRV:ERRbaduid\n  but returned %s\n",
1305                        smbcli_errstr(cli->tree));
1306                 correct = False;
1307         }
1308
1309         cli->session->vuid -= 1234;
1310
1311         if (NT_STATUS_IS_ERR(smbcli_close(cli->tree, fnum))) {
1312                 printf("close failed (%s)\n", smbcli_errstr(cli->tree));
1313                 correct = False;
1314         }
1315
1316         smbcli_unlink(cli->tree, fname);
1317
1318         if (!torture_close_connection(cli)) {
1319                 correct = False;
1320         }
1321
1322         printf("vuid test finished\n");
1323
1324         return correct;
1325 }
1326
1327 /*
1328   Test open mode returns on read-only files.
1329  */
1330  static BOOL run_opentest(void)
1331 {
1332         static struct smbcli_state *cli1;
1333         static struct smbcli_state *cli2;
1334         const char *fname = "\\readonly.file";
1335         char *control_char_fname;
1336         int fnum1, fnum2;
1337         uint8_t buf[20];
1338         size_t fsize;
1339         BOOL correct = True;
1340         char *tmp_path;
1341         int failures = 0;
1342         int i;
1343
1344         printf("starting open test\n");
1345         
1346         if (!torture_open_connection(&cli1)) {
1347                 return False;
1348         }
1349         
1350         asprintf(&control_char_fname, "\\readonly.afile");
1351         for (i = 1; i <= 0x1f; i++) {
1352                 control_char_fname[10] = i;
1353                 fnum1 = smbcli_nt_create_full(cli1->tree, control_char_fname, 0, SEC_FILE_WRITE_DATA, FILE_ATTRIBUTE_NORMAL,
1354                                    NTCREATEX_SHARE_ACCESS_NONE, NTCREATEX_DISP_OVERWRITE_IF, 0, 0);
1355                 
1356                 if (!check_error(__location__, cli1, ERRDOS, ERRinvalidname, 
1357                                 NT_STATUS_OBJECT_NAME_INVALID)) {
1358                         printf("Error code should be NT_STATUS_OBJECT_NAME_INVALID, was %s for file with %d char\n",
1359                                         smbcli_errstr(cli1->tree), i);
1360                         failures++;
1361                 }
1362
1363                 if (fnum1 != -1) {
1364                         smbcli_close(cli1->tree, fnum1);
1365                 }
1366                 smbcli_setatr(cli1->tree, control_char_fname, 0, 0);
1367                 smbcli_unlink(cli1->tree, control_char_fname);
1368         }
1369         free(control_char_fname);
1370
1371         if (!failures)
1372                 printf("Create file with control char names passed.\n");
1373
1374         smbcli_setatr(cli1->tree, fname, 0, 0);
1375         smbcli_unlink(cli1->tree, fname);
1376         
1377         fnum1 = smbcli_open(cli1->tree, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
1378         if (fnum1 == -1) {
1379                 printf("open of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
1380                 return False;
1381         }
1382
1383         if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum1))) {
1384                 printf("close2 failed (%s)\n", smbcli_errstr(cli1->tree));
1385                 return False;
1386         }
1387         
1388         if (NT_STATUS_IS_ERR(smbcli_setatr(cli1->tree, fname, FILE_ATTRIBUTE_READONLY, 0))) {
1389                 printf("smbcli_setatr failed (%s)\n", smbcli_errstr(cli1->tree));
1390                 CHECK_MAX_FAILURES(error_test1);
1391                 return False;
1392         }
1393         
1394         fnum1 = smbcli_open(cli1->tree, fname, O_RDONLY, DENY_WRITE);
1395         if (fnum1 == -1) {
1396                 printf("open of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
1397                 CHECK_MAX_FAILURES(error_test1);
1398                 return False;
1399         }
1400         
1401         /* This will fail - but the error should be ERRnoaccess, not ERRbadshare. */
1402         fnum2 = smbcli_open(cli1->tree, fname, O_RDWR, DENY_ALL);
1403         
1404         if (check_error(__location__, cli1, ERRDOS, ERRnoaccess, 
1405                         NT_STATUS_ACCESS_DENIED)) {
1406                 printf("correct error code ERRDOS/ERRnoaccess returned\n");
1407         }
1408         
1409         printf("finished open test 1\n");
1410 error_test1:
1411         smbcli_close(cli1->tree, fnum1);
1412         
1413         /* Now try not readonly and ensure ERRbadshare is returned. */
1414         
1415         smbcli_setatr(cli1->tree, fname, 0, 0);
1416         
1417         fnum1 = smbcli_open(cli1->tree, fname, O_RDONLY, DENY_WRITE);
1418         if (fnum1 == -1) {
1419                 printf("open of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
1420                 return False;
1421         }
1422         
1423         /* This will fail - but the error should be ERRshare. */
1424         fnum2 = smbcli_open(cli1->tree, fname, O_RDWR, DENY_ALL);
1425         
1426         if (check_error(__location__, cli1, ERRDOS, ERRbadshare, 
1427                         NT_STATUS_SHARING_VIOLATION)) {
1428                 printf("correct error code ERRDOS/ERRbadshare returned\n");
1429         }
1430         
1431         if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum1))) {
1432                 printf("close2 failed (%s)\n", smbcli_errstr(cli1->tree));
1433                 return False;
1434         }
1435         
1436         smbcli_unlink(cli1->tree, fname);
1437         
1438         printf("finished open test 2\n");
1439         
1440         /* Test truncate open disposition on file opened for read. */
1441         
1442         fnum1 = smbcli_open(cli1->tree, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
1443         if (fnum1 == -1) {
1444                 printf("(3) open (1) of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
1445                 return False;
1446         }
1447         
1448         /* write 20 bytes. */
1449         
1450         memset(buf, '\0', 20);
1451
1452         if (smbcli_write(cli1->tree, fnum1, 0, buf, 0, 20) != 20) {
1453                 printf("write failed (%s)\n", smbcli_errstr(cli1->tree));
1454                 correct = False;
1455         }
1456
1457         if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum1))) {
1458                 printf("(3) close1 failed (%s)\n", smbcli_errstr(cli1->tree));
1459                 return False;
1460         }
1461         
1462         /* Ensure size == 20. */
1463         if (NT_STATUS_IS_ERR(smbcli_getatr(cli1->tree, fname, NULL, &fsize, NULL))) {
1464                 printf("(3) getatr failed (%s)\n", smbcli_errstr(cli1->tree));
1465                 CHECK_MAX_FAILURES(error_test3);
1466                 return False;
1467         }
1468         
1469         if (fsize != 20) {
1470                 printf("(3) file size != 20\n");
1471                 CHECK_MAX_FAILURES(error_test3);
1472                 return False;
1473         }
1474
1475         /* Now test if we can truncate a file opened for readonly. */
1476         
1477         fnum1 = smbcli_open(cli1->tree, fname, O_RDONLY|O_TRUNC, DENY_NONE);
1478         if (fnum1 == -1) {
1479                 printf("(3) open (2) of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
1480                 CHECK_MAX_FAILURES(error_test3);
1481                 return False;
1482         }
1483         
1484         if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum1))) {
1485                 printf("close2 failed (%s)\n", smbcli_errstr(cli1->tree));
1486                 return False;
1487         }
1488
1489         /* Ensure size == 0. */
1490         if (NT_STATUS_IS_ERR(smbcli_getatr(cli1->tree, fname, NULL, &fsize, NULL))) {
1491                 printf("(3) getatr failed (%s)\n", smbcli_errstr(cli1->tree));
1492                 CHECK_MAX_FAILURES(error_test3);
1493                 return False;
1494         }
1495
1496         if (fsize != 0) {
1497                 printf("(3) file size != 0\n");
1498                 CHECK_MAX_FAILURES(error_test3);
1499                 return False;
1500         }
1501         printf("finished open test 3\n");
1502 error_test3:    
1503         smbcli_unlink(cli1->tree, fname);
1504
1505
1506         printf("testing ctemp\n");
1507         fnum1 = smbcli_ctemp(cli1->tree, "\\", &tmp_path);
1508         if (fnum1 == -1) {
1509                 printf("ctemp failed (%s)\n", smbcli_errstr(cli1->tree));
1510                 CHECK_MAX_FAILURES(error_test4);
1511                 return False;
1512         }
1513         printf("ctemp gave path %s\n", tmp_path);
1514         if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum1))) {
1515                 printf("close of temp failed (%s)\n", smbcli_errstr(cli1->tree));
1516         }
1517         if (NT_STATUS_IS_ERR(smbcli_unlink(cli1->tree, tmp_path))) {
1518                 printf("unlink of temp failed (%s)\n", smbcli_errstr(cli1->tree));
1519         }
1520 error_test4:    
1521         /* Test the non-io opens... */
1522
1523         if (!torture_open_connection(&cli2)) {
1524                 return False;
1525         }
1526         
1527         smbcli_setatr(cli2->tree, fname, 0, 0);
1528         smbcli_unlink(cli2->tree, fname);
1529         
1530         printf("TEST #1 testing 2 non-io opens (no delete)\n");
1531         
1532         fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0, SEC_FILE_READ_ATTRIBUTE, FILE_ATTRIBUTE_NORMAL,
1533                                    NTCREATEX_SHARE_ACCESS_NONE, NTCREATEX_DISP_OVERWRITE_IF, 0, 0);
1534
1535         if (fnum1 == -1) {
1536                 printf("test 1 open 1 of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
1537                 CHECK_MAX_FAILURES(error_test10);
1538                 return False;
1539         }
1540
1541         fnum2 = smbcli_nt_create_full(cli2->tree, fname, 0, SEC_FILE_READ_ATTRIBUTE, FILE_ATTRIBUTE_NORMAL,
1542                                    NTCREATEX_SHARE_ACCESS_NONE, NTCREATEX_DISP_OPEN_IF, 0, 0);
1543         if (fnum2 == -1) {
1544                 printf("test 1 open 2 of %s failed (%s)\n", fname, smbcli_errstr(cli2->tree));
1545                 CHECK_MAX_FAILURES(error_test10);
1546                 return False;
1547         }
1548
1549         if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum1))) {
1550                 printf("test 1 close 1 of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
1551                 return False;
1552         }
1553         if (NT_STATUS_IS_ERR(smbcli_close(cli2->tree, fnum2))) {
1554                 printf("test 1 close 2 of %s failed (%s)\n", fname, smbcli_errstr(cli2->tree));
1555                 return False;
1556         }
1557
1558         printf("non-io open test #1 passed.\n");
1559 error_test10:
1560         smbcli_unlink(cli1->tree, fname);
1561
1562         printf("TEST #2 testing 2 non-io opens (first with delete)\n");
1563         
1564         fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0, SEC_STD_DELETE|SEC_FILE_READ_ATTRIBUTE, FILE_ATTRIBUTE_NORMAL,
1565                                    NTCREATEX_SHARE_ACCESS_NONE, NTCREATEX_DISP_OVERWRITE_IF, 0, 0);
1566
1567         if (fnum1 == -1) {
1568                 printf("test 2 open 1 of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
1569                 CHECK_MAX_FAILURES(error_test20);
1570                 return False;
1571         }
1572
1573         fnum2 = smbcli_nt_create_full(cli2->tree, fname, 0, SEC_FILE_READ_ATTRIBUTE, FILE_ATTRIBUTE_NORMAL,
1574                                    NTCREATEX_SHARE_ACCESS_NONE, NTCREATEX_DISP_OPEN_IF, 0, 0);
1575
1576         if (fnum2 == -1) {
1577                 printf("test 2 open 2 of %s failed (%s)\n", fname, smbcli_errstr(cli2->tree));
1578                 CHECK_MAX_FAILURES(error_test20);
1579                 return False;
1580         }
1581
1582         if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum1))) {
1583                 printf("test 1 close 1 of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
1584                 return False;
1585         }
1586         if (NT_STATUS_IS_ERR(smbcli_close(cli2->tree, fnum2))) {
1587                 printf("test 1 close 2 of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
1588                 return False;
1589         }
1590
1591         printf("non-io open test #2 passed.\n");
1592 error_test20:
1593         smbcli_unlink(cli1->tree, fname);
1594
1595         printf("TEST #3 testing 2 non-io opens (second with delete)\n");
1596         
1597         fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0, SEC_FILE_READ_ATTRIBUTE, FILE_ATTRIBUTE_NORMAL,
1598                                    NTCREATEX_SHARE_ACCESS_NONE, NTCREATEX_DISP_OVERWRITE_IF, 0, 0);
1599
1600         if (fnum1 == -1) {
1601                 printf("test 3 open 1 of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
1602                 CHECK_MAX_FAILURES(error_test30);
1603                 return False;
1604         }
1605
1606         fnum2 = smbcli_nt_create_full(cli2->tree, fname, 0, SEC_STD_DELETE|SEC_FILE_READ_ATTRIBUTE, FILE_ATTRIBUTE_NORMAL,
1607                                    NTCREATEX_SHARE_ACCESS_NONE, NTCREATEX_DISP_OPEN_IF, 0, 0);
1608
1609         if (fnum2 == -1) {
1610                 printf("test 3 open 2 of %s failed (%s)\n", fname, smbcli_errstr(cli2->tree));
1611                 CHECK_MAX_FAILURES(error_test30);
1612                 return False;
1613         }
1614
1615         if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum1))) {
1616                 printf("test 3 close 1 of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
1617                 return False;
1618         }
1619         if (NT_STATUS_IS_ERR(smbcli_close(cli2->tree, fnum2))) {
1620                 printf("test 3 close 2 of %s failed (%s)\n", fname, smbcli_errstr(cli2->tree));
1621                 return False;
1622         }
1623
1624         printf("non-io open test #3 passed.\n");
1625 error_test30:
1626         smbcli_unlink(cli1->tree, fname);
1627
1628         printf("TEST #4 testing 2 non-io opens (both with delete)\n");
1629         
1630         fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0, SEC_STD_DELETE|SEC_FILE_READ_ATTRIBUTE, FILE_ATTRIBUTE_NORMAL,
1631                                    NTCREATEX_SHARE_ACCESS_NONE, NTCREATEX_DISP_OVERWRITE_IF, 0, 0);
1632
1633         if (fnum1 == -1) {
1634                 printf("test 4 open 1 of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
1635                 CHECK_MAX_FAILURES(error_test40);
1636                 return False;
1637         }
1638
1639         fnum2 = smbcli_nt_create_full(cli2->tree, fname, 0, SEC_STD_DELETE|SEC_FILE_READ_ATTRIBUTE, FILE_ATTRIBUTE_NORMAL,
1640                                    NTCREATEX_SHARE_ACCESS_NONE, NTCREATEX_DISP_OPEN_IF, 0, 0);
1641
1642         if (fnum2 != -1) {
1643                 printf("test 4 open 2 of %s SUCCEEDED - should have failed (%s)\n", fname, smbcli_errstr(cli2->tree));
1644                 CHECK_MAX_FAILURES(error_test40);
1645                 return False;
1646         }
1647
1648         printf("test 4 open 2 of %s gave %s (correct error should be %s)\n", fname, smbcli_errstr(cli2->tree), "sharing violation");
1649
1650         if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum1))) {
1651                 printf("test 4 close 1 of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
1652                 return False;
1653         }
1654
1655         printf("non-io open test #4 passed.\n");
1656 error_test40:
1657         smbcli_unlink(cli1->tree, fname);
1658
1659         printf("TEST #5 testing 2 non-io opens (both with delete - both with file share delete)\n");
1660         
1661         fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0, SEC_STD_DELETE|SEC_FILE_READ_ATTRIBUTE, FILE_ATTRIBUTE_NORMAL,
1662                                    NTCREATEX_SHARE_ACCESS_DELETE, NTCREATEX_DISP_OVERWRITE_IF, 0, 0);
1663
1664         if (fnum1 == -1) {
1665                 printf("test 5 open 1 of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
1666                 CHECK_MAX_FAILURES(error_test50);
1667                 return False;
1668         }
1669
1670         fnum2 = smbcli_nt_create_full(cli2->tree, fname, 0, SEC_STD_DELETE|SEC_FILE_READ_ATTRIBUTE, FILE_ATTRIBUTE_NORMAL,
1671                                    NTCREATEX_SHARE_ACCESS_DELETE, NTCREATEX_DISP_OPEN_IF, 0, 0);
1672
1673         if (fnum2 == -1) {
1674                 printf("test 5 open 2 of %s failed (%s)\n", fname, smbcli_errstr(cli2->tree));
1675                 CHECK_MAX_FAILURES(error_test50);
1676                 return False;
1677         }
1678
1679         if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum1))) {
1680                 printf("test 5 close 1 of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
1681                 return False;
1682         }
1683
1684         if (NT_STATUS_IS_ERR(smbcli_close(cli2->tree, fnum2))) {
1685                 printf("test 5 close 2 of %s failed (%s)\n", fname, smbcli_errstr(cli2->tree));
1686                 return False;
1687         }
1688
1689         printf("non-io open test #5 passed.\n");
1690 error_test50:
1691         printf("TEST #6 testing 1 non-io open, one io open\n");
1692         
1693         smbcli_unlink(cli1->tree, fname);
1694
1695         fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0, SEC_FILE_READ_DATA, FILE_ATTRIBUTE_NORMAL,
1696                                    NTCREATEX_SHARE_ACCESS_NONE, NTCREATEX_DISP_OVERWRITE_IF, 0, 0);
1697
1698         if (fnum1 == -1) {
1699                 printf("test 6 open 1 of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
1700                 CHECK_MAX_FAILURES(error_test60);
1701                 return False;
1702         }
1703
1704         fnum2 = smbcli_nt_create_full(cli2->tree, fname, 0, SEC_FILE_READ_ATTRIBUTE, FILE_ATTRIBUTE_NORMAL,
1705                                    NTCREATEX_SHARE_ACCESS_READ, NTCREATEX_DISP_OPEN_IF, 0, 0);
1706
1707         if (fnum2 == -1) {
1708                 printf("test 6 open 2 of %s failed (%s)\n", fname, smbcli_errstr(cli2->tree));
1709                 CHECK_MAX_FAILURES(error_test60);
1710                 return False;
1711         }
1712
1713         if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum1))) {
1714                 printf("test 6 close 1 of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
1715                 return False;
1716         }
1717
1718         if (NT_STATUS_IS_ERR(smbcli_close(cli2->tree, fnum2))) {
1719                 printf("test 6 close 2 of %s failed (%s)\n", fname, smbcli_errstr(cli2->tree));
1720                 return False;
1721         }
1722
1723         printf("non-io open test #6 passed.\n");
1724 error_test60:
1725         printf("TEST #7 testing 1 non-io open, one io open with delete\n");
1726
1727         smbcli_unlink(cli1->tree, fname);
1728
1729         fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0, SEC_FILE_READ_DATA, FILE_ATTRIBUTE_NORMAL,
1730                                    NTCREATEX_SHARE_ACCESS_NONE, NTCREATEX_DISP_OVERWRITE_IF, 0, 0);
1731
1732         if (fnum1 == -1) {
1733                 printf("test 7 open 1 of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
1734                 CHECK_MAX_FAILURES(error_test70);
1735                 return False;
1736         }
1737
1738         fnum2 = smbcli_nt_create_full(cli2->tree, fname, 0, SEC_STD_DELETE|SEC_FILE_READ_ATTRIBUTE, FILE_ATTRIBUTE_NORMAL,
1739                                    NTCREATEX_SHARE_ACCESS_READ|NTCREATEX_SHARE_ACCESS_DELETE, NTCREATEX_DISP_OPEN_IF, 0, 0);
1740
1741         if (fnum2 != -1) {
1742                 printf("test 7 open 2 of %s SUCCEEDED - should have failed (%s)\n", fname, smbcli_errstr(cli2->tree));
1743                 CHECK_MAX_FAILURES(error_test70);
1744                 return False;
1745         }
1746
1747         printf("test 7 open 2 of %s gave %s (correct error should be %s)\n", fname, smbcli_errstr(cli2->tree), "sharing violation");
1748
1749         if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum1))) {
1750                 printf("test 7 close 1 of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
1751                 return False;
1752         }
1753
1754         printf("non-io open test #7 passed.\n");
1755
1756 error_test70:
1757
1758         printf("TEST #8 testing one normal open, followed by lock, followed by open with truncate\n");
1759
1760         smbcli_unlink(cli1->tree, fname);
1761
1762         fnum1 = smbcli_open(cli1->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
1763         if (fnum1 == -1) {
1764                 printf("(8) open (1) of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
1765                 return False;
1766         }
1767         
1768         /* write 20 bytes. */
1769         
1770         memset(buf, '\0', 20);
1771
1772         if (smbcli_write(cli1->tree, fnum1, 0, buf, 0, 20) != 20) {
1773                 printf("(8) write failed (%s)\n", smbcli_errstr(cli1->tree));
1774                 correct = False;
1775         }
1776
1777         /* Ensure size == 20. */
1778         if (NT_STATUS_IS_ERR(smbcli_getatr(cli1->tree, fname, NULL, &fsize, NULL))) {
1779                 printf("(8) getatr (1) failed (%s)\n", smbcli_errstr(cli1->tree));
1780                 CHECK_MAX_FAILURES(error_test80);
1781                 return False;
1782         }
1783         
1784         if (fsize != 20) {
1785                 printf("(8) file size != 20\n");
1786                 CHECK_MAX_FAILURES(error_test80);
1787                 return False;
1788         }
1789
1790         /* Get an exclusive lock on the open file. */
1791         if (NT_STATUS_IS_ERR(smbcli_lock(cli1->tree, fnum1, 0, 4, 0, WRITE_LOCK))) {
1792                 printf("(8) lock1 failed (%s)\n", smbcli_errstr(cli1->tree));
1793                 CHECK_MAX_FAILURES(error_test80);
1794                 return False;
1795         }
1796
1797         fnum2 = smbcli_open(cli1->tree, fname, O_RDWR|O_TRUNC, DENY_NONE);
1798         if (fnum1 == -1) {
1799                 printf("(8) open (2) of %s with truncate failed (%s)\n", fname, smbcli_errstr(cli1->tree));
1800                 return False;
1801         }
1802
1803         /* Ensure size == 0. */
1804         if (NT_STATUS_IS_ERR(smbcli_getatr(cli1->tree, fname, NULL, &fsize, NULL))) {
1805                 printf("(8) getatr (2) failed (%s)\n", smbcli_errstr(cli1->tree));
1806                 CHECK_MAX_FAILURES(error_test80);
1807                 return False;
1808         }
1809         
1810         if (fsize != 0) {
1811                 printf("(8) file size != 0\n");
1812                 CHECK_MAX_FAILURES(error_test80);
1813                 return False;
1814         }
1815
1816         if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum1))) {
1817                 printf("(8) close1 failed (%s)\n", smbcli_errstr(cli1->tree));
1818                 return False;
1819         }
1820         
1821         if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum2))) {
1822                 printf("(8) close1 failed (%s)\n", smbcli_errstr(cli1->tree));
1823                 return False;
1824         }
1825         
1826 error_test80:
1827
1828         printf("open test #8 passed.\n");
1829
1830         smbcli_unlink(cli1->tree, fname);
1831
1832         if (!torture_close_connection(cli1)) {
1833                 correct = False;
1834         }
1835         if (!torture_close_connection(cli2)) {
1836                 correct = False;
1837         }
1838         
1839         return correct;
1840 }
1841
1842
1843 /*
1844   sees what IOCTLs are supported
1845  */
1846 BOOL torture_ioctl_test(void)
1847 {
1848         struct smbcli_state *cli;
1849         uint16_t device, function;
1850         int fnum;
1851         const char *fname = "\\ioctl.dat";
1852         NTSTATUS status;
1853         union smb_ioctl parms;
1854         TALLOC_CTX *mem_ctx;
1855
1856         if (!torture_open_connection(&cli)) {
1857                 return False;
1858         }
1859
1860         mem_ctx = talloc_init("ioctl_test");
1861
1862         printf("starting ioctl test\n");
1863
1864         smbcli_unlink(cli->tree, fname);
1865
1866         fnum = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
1867         if (fnum == -1) {
1868                 printf("open of %s failed (%s)\n", fname, smbcli_errstr(cli->tree));
1869                 return False;
1870         }
1871
1872         parms.ioctl.level = RAW_IOCTL_IOCTL;
1873         parms.ioctl.in.file.fnum = fnum;
1874         parms.ioctl.in.request = IOCTL_QUERY_JOB_INFO;
1875         status = smb_raw_ioctl(cli->tree, mem_ctx, &parms);
1876         printf("ioctl job info: %s\n", smbcli_errstr(cli->tree));
1877
1878         for (device=0;device<0x100;device++) {
1879                 printf("testing device=0x%x\n", device);
1880                 for (function=0;function<0x100;function++) {
1881                         parms.ioctl.in.request = (device << 16) | function;
1882                         status = smb_raw_ioctl(cli->tree, mem_ctx, &parms);
1883
1884                         if (NT_STATUS_IS_OK(status)) {
1885                                 printf("ioctl device=0x%x function=0x%x OK : %d bytes\n", 
1886                                         device, function, (int)parms.ioctl.out.blob.length);
1887                         }
1888                 }
1889         }
1890
1891         if (!torture_close_connection(cli)) {
1892                 return False;
1893         }
1894
1895         return True;
1896 }
1897
1898
1899 /*
1900   tries variants of chkpath
1901  */
1902 BOOL torture_chkpath_test(void)
1903 {
1904         struct smbcli_state *cli;
1905         int fnum;
1906         BOOL ret;
1907
1908         if (!torture_open_connection(&cli)) {
1909                 return False;
1910         }
1911
1912         printf("starting chkpath test\n");
1913
1914         printf("Testing valid and invalid paths\n");
1915
1916         /* cleanup from an old run */
1917         smbcli_rmdir(cli->tree, "\\chkpath.dir\\dir2");
1918         smbcli_unlink(cli->tree, "\\chkpath.dir\\*");
1919         smbcli_rmdir(cli->tree, "\\chkpath.dir");
1920
1921         if (NT_STATUS_IS_ERR(smbcli_mkdir(cli->tree, "\\chkpath.dir"))) {
1922                 printf("mkdir1 failed : %s\n", smbcli_errstr(cli->tree));
1923                 return False;
1924         }
1925
1926         if (NT_STATUS_IS_ERR(smbcli_mkdir(cli->tree, "\\chkpath.dir\\dir2"))) {
1927                 printf("mkdir2 failed : %s\n", smbcli_errstr(cli->tree));
1928                 return False;
1929         }
1930
1931         fnum = smbcli_open(cli->tree, "\\chkpath.dir\\foo.txt", O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
1932         if (fnum == -1) {
1933                 printf("open1 failed (%s)\n", smbcli_errstr(cli->tree));
1934                 return False;
1935         }
1936         smbcli_close(cli->tree, fnum);
1937
1938         if (NT_STATUS_IS_ERR(smbcli_chkpath(cli->tree, "\\chkpath.dir"))) {
1939                 printf("chkpath1 failed: %s\n", smbcli_errstr(cli->tree));
1940                 ret = False;
1941         }
1942
1943         if (NT_STATUS_IS_ERR(smbcli_chkpath(cli->tree, "\\chkpath.dir\\dir2"))) {
1944                 printf("chkpath2 failed: %s\n", smbcli_errstr(cli->tree));
1945                 ret = False;
1946         }
1947
1948         if (NT_STATUS_IS_ERR(smbcli_chkpath(cli->tree, "\\chkpath.dir\\foo.txt"))) {
1949                 ret = check_error(__location__, cli, ERRDOS, ERRbadpath, 
1950                                   NT_STATUS_NOT_A_DIRECTORY);
1951         } else {
1952                 printf("* chkpath on a file should fail\n");
1953                 ret = False;
1954         }
1955
1956         if (NT_STATUS_IS_ERR(smbcli_chkpath(cli->tree, "\\chkpath.dir\\bar.txt"))) {
1957                 ret = check_error(__location__, cli, ERRDOS, ERRbadpath, 
1958                                   NT_STATUS_OBJECT_NAME_NOT_FOUND);
1959         } else {
1960                 printf("* chkpath on a non existent file should fail\n");
1961                 ret = False;
1962         }
1963
1964         if (NT_STATUS_IS_ERR(smbcli_chkpath(cli->tree, "\\chkpath.dir\\dirxx\\bar.txt"))) {
1965                 ret = check_error(__location__, cli, ERRDOS, ERRbadpath, 
1966                                   NT_STATUS_OBJECT_PATH_NOT_FOUND);
1967         } else {
1968                 printf("* chkpath on a non existent component should fail\n");
1969                 ret = False;
1970         }
1971
1972         smbcli_rmdir(cli->tree, "\\chkpath.dir\\dir2");
1973         smbcli_unlink(cli->tree, "\\chkpath.dir\\*");
1974         smbcli_rmdir(cli->tree, "\\chkpath.dir");
1975
1976         if (!torture_close_connection(cli)) {
1977                 return False;
1978         }
1979
1980         return ret;
1981 }
1982
1983
1984 static void sigcont(int sig)
1985 {
1986 }
1987
1988 double torture_create_procs(BOOL (*fn)(struct smbcli_state *, int), BOOL *result)
1989 {
1990         int i, status;
1991         volatile pid_t *child_status;
1992         volatile BOOL *child_status_out;
1993         int synccount;
1994         int tries = 8;
1995         double start_time_limit = 10 + (torture_nprocs * 1.5);
1996         char **unc_list = NULL;
1997         const char *p;
1998         int num_unc_names = 0;
1999         struct timeval tv;
2000
2001         *result = True;
2002
2003         synccount = 0;
2004
2005         signal(SIGCONT, sigcont);
2006
2007         child_status = (volatile pid_t *)shm_setup(sizeof(pid_t)*torture_nprocs);
2008         if (!child_status) {
2009                 printf("Failed to setup shared memory\n");
2010                 return -1;
2011         }
2012
2013         child_status_out = (volatile BOOL *)shm_setup(sizeof(BOOL)*torture_nprocs);
2014         if (!child_status_out) {
2015                 printf("Failed to setup result status shared memory\n");
2016                 return -1;
2017         }
2018
2019         p = lp_parm_string(-1, "torture", "unclist");
2020         if (p) {
2021                 unc_list = file_lines_load(p, &num_unc_names, NULL);
2022                 if (!unc_list || num_unc_names <= 0) {
2023                         printf("Failed to load unc names list from '%s'\n", p);
2024                         exit(1);
2025                 }
2026         }
2027
2028         for (i = 0; i < torture_nprocs; i++) {
2029                 child_status[i] = 0;
2030                 child_status_out[i] = True;
2031         }
2032
2033         tv = timeval_current();
2034
2035         for (i=0;i<torture_nprocs;i++) {
2036                 procnum = i;
2037                 if (fork() == 0) {
2038                         char *myname;
2039                         const char *hostname=NULL, *sharename;
2040
2041                         pid_t mypid = getpid();
2042                         srandom(((int)mypid) ^ ((int)time(NULL)));
2043
2044                         asprintf(&myname, "CLIENT%d", i);
2045                         lp_set_cmdline("netbios name", myname);
2046                         free(myname);
2047
2048
2049                         if (unc_list) {
2050                                 if (!smbcli_parse_unc(unc_list[i % num_unc_names],
2051                                                       NULL, &hostname, &sharename)) {
2052                                         printf("Failed to parse UNC name %s\n",
2053                                                unc_list[i % num_unc_names]);
2054                                         exit(1);
2055                                 }
2056                         }
2057
2058                         while (1) {
2059                                 if (hostname) {
2060                                         if (torture_open_connection_share(NULL,
2061                                                                           &current_cli,
2062                                                                           hostname, 
2063                                                                           sharename,
2064                                                                           NULL)) {
2065                                                 break;
2066                                         }
2067                                 } else if (torture_open_connection(&current_cli)) {
2068                                                 break;
2069                                 }
2070                                 if (tries-- == 0) {
2071                                         printf("pid %d failed to start\n", (int)getpid());
2072                                         _exit(1);
2073                                 }
2074                                 msleep(100);    
2075                         }
2076
2077                         child_status[i] = getpid();
2078
2079                         pause();
2080
2081                         if (child_status[i]) {
2082                                 printf("Child %d failed to start!\n", i);
2083                                 child_status_out[i] = 1;
2084                                 _exit(1);
2085                         }
2086
2087                         child_status_out[i] = fn(current_cli, i);
2088                         _exit(0);
2089                 }
2090         }
2091
2092         do {
2093                 synccount = 0;
2094                 for (i=0;i<torture_nprocs;i++) {
2095                         if (child_status[i]) synccount++;
2096                 }
2097                 if (synccount == torture_nprocs) break;
2098                 msleep(100);
2099         } while (timeval_elapsed(&tv) < start_time_limit);
2100
2101         if (synccount != torture_nprocs) {
2102                 printf("FAILED TO START %d CLIENTS (started %d)\n", torture_nprocs, synccount);
2103                 *result = False;
2104                 return timeval_elapsed(&tv);
2105         }
2106
2107         printf("Starting %d clients\n", torture_nprocs);
2108
2109         /* start the client load */
2110         tv = timeval_current();
2111         for (i=0;i<torture_nprocs;i++) {
2112                 child_status[i] = 0;
2113         }
2114
2115         printf("%d clients started\n", torture_nprocs);
2116
2117         kill(0, SIGCONT);
2118
2119         for (i=0;i<torture_nprocs;i++) {
2120                 int ret;
2121                 while ((ret=waitpid(0, &status, 0)) == -1 && errno == EINTR) /* noop */ ;
2122                 if (ret == -1 || WEXITSTATUS(status) != 0) {
2123                         *result = False;
2124                 }
2125         }
2126
2127         printf("\n");
2128         
2129         for (i=0;i<torture_nprocs;i++) {
2130                 if (!child_status_out[i]) {
2131                         *result = False;
2132                 }
2133         }
2134         return timeval_elapsed(&tv);
2135 }
2136
2137 #define FLAG_MULTIPROC 1
2138
2139 static struct {
2140         const char *name;
2141         BOOL (*fn)(void);
2142         BOOL (*multi_fn)(struct smbcli_state *, int );
2143 } builtin_torture_ops[] = {
2144         /* base tests */
2145         {"BASE-FDPASS", run_fdpasstest, 0},
2146         {"BASE-LOCK1",  torture_locktest1,  0},
2147         {"BASE-LOCK2",  torture_locktest2,  0},
2148         {"BASE-LOCK3",  torture_locktest3,  0},
2149         {"BASE-LOCK4",  torture_locktest4,  0},
2150         {"BASE-LOCK5",  torture_locktest5,  0},
2151         {"BASE-LOCK6",  torture_locktest6,  0},
2152         {"BASE-LOCK7",  torture_locktest7,  0},
2153         {"BASE-UNLINK", torture_unlinktest, 0},
2154         {"BASE-ATTR",   run_attrtest,   0},
2155         {"BASE-TRANS2", run_trans2test, 0},
2156         {"BASE-NEGNOWAIT", run_negprot_nowait, 0},
2157         {"BASE-DIR1",  torture_dirtest1, 0},
2158         {"BASE-DIR2",  torture_dirtest2, 0},
2159         {"BASE-DENY1",  torture_denytest1, 0},
2160         {"BASE-DENY2",  torture_denytest2, 0},
2161         {"BASE-DENY3",  torture_denytest3, 0},
2162         {"BASE-DENYDOS",  torture_denydos_sharing, 0},
2163         {"BASE-NTDENY1",  NULL, torture_ntdenytest1},
2164         {"BASE-NTDENY2",  torture_ntdenytest2, 0},
2165         {"BASE-TCON",  run_tcon_test, 0},
2166         {"BASE-TCONDEV",  run_tcon_devtype_test, 0},
2167         {"BASE-VUID", run_vuidtest, 0},
2168         {"BASE-RW1",  run_readwritetest, 0},
2169         {"BASE-OPEN", run_opentest, 0},
2170         {"BASE-DEFER_OPEN", NULL, run_deferopen},
2171         {"BASE-XCOPY", run_xcopy, 0},
2172         {"BASE-RENAME", torture_test_rename, 0},
2173         {"BASE-DELETE", torture_test_delete, 0},
2174         {"BASE-PROPERTIES", torture_test_properties, 0},
2175         {"BASE-MANGLE", torture_mangle, 0},
2176         {"BASE-OPENATTR", torture_openattrtest, 0},
2177         {"BASE-CHARSET", torture_charset, 0},
2178         {"BASE-CHKPATH",  torture_chkpath_test, 0},
2179         {"BASE-SECLEAK",  torture_sec_leak, 0},
2180         {"BASE-DISCONNECT",  torture_disconnect, 0},
2181         {"BASE-DELAYWRITE", torture_delay_write, 0},
2182
2183         /* benchmarking tests */
2184         {"BENCH-HOLDCON",  torture_holdcon, 0},
2185         {"BENCH-NBENCH",  torture_nbench, 0},
2186         {"BENCH-TORTURE", NULL, run_torture},
2187         {"BENCH-NBT",     torture_bench_nbt, 0},
2188         {"BENCH-WINS",    torture_bench_wins, 0},
2189         {"BENCH-CLDAP",   torture_bench_cldap, 0},
2190
2191         /* RAW smb tests */
2192         {"RAW-QFSINFO", torture_raw_qfsinfo, 0},
2193         {"RAW-QFILEINFO", torture_raw_qfileinfo, 0},
2194         {"RAW-SFILEINFO", torture_raw_sfileinfo, 0},
2195         {"RAW-SFILEINFO-BUG", torture_raw_sfileinfo_bug, 0},
2196         {"RAW-SEARCH", torture_raw_search, 0},
2197         {"RAW-CLOSE", torture_raw_close, 0},
2198         {"RAW-OPEN", torture_raw_open, 0},
2199         {"RAW-MKDIR", torture_raw_mkdir, 0},
2200         {"RAW-OPLOCK", torture_raw_oplock, 0},
2201         {"RAW-NOTIFY", torture_raw_notify, 0},
2202         {"RAW-MUX", torture_raw_mux, 0},
2203         {"RAW-IOCTL", torture_raw_ioctl, 0},
2204         {"RAW-CHKPATH", torture_raw_chkpath, 0},
2205         {"RAW-UNLINK", torture_raw_unlink, 0},
2206         {"RAW-READ", torture_raw_read, 0},
2207         {"RAW-WRITE", torture_raw_write, 0},
2208         {"RAW-LOCK", torture_raw_lock, 0},
2209         {"RAW-CONTEXT", torture_raw_context, 0},
2210         {"RAW-RENAME", torture_raw_rename, 0},
2211         {"RAW-SEEK", torture_raw_seek, 0},
2212         {"RAW-EAS", torture_raw_eas, 0},
2213         {"RAW-EAMAX", torture_max_eas, 0},
2214         {"RAW-STREAMS", torture_raw_streams, 0},
2215         {"RAW-ACLS", torture_raw_acls, 0},
2216         {"RAW-RAP", torture_raw_rap, 0},
2217         {"RAW-COMPOSITE", torture_raw_composite, 0},
2218
2219         /* SMB2 tests */
2220         {"SMB2-CONNECT", torture_smb2_connect, 0},
2221         {"SMB2-SCAN", torture_smb2_scan, 0},
2222         {"SMB2-SCANGETINFO", torture_smb2_getinfo_scan, 0},
2223         {"SMB2-SCANSETINFO", torture_smb2_setinfo_scan, 0},
2224         {"SMB2-SCANFIND", torture_smb2_find_scan, 0},
2225         {"SMB2-GETINFO", torture_smb2_getinfo, 0},
2226         {"SMB2-SETINFO", torture_smb2_setinfo, 0},
2227         {"SMB2-FIND", torture_smb2_find, 0},
2228
2229         /* protocol scanners */
2230         {"SCAN-TRANS2", torture_trans2_scan, 0},
2231         {"SCAN-NTTRANS", torture_nttrans_scan, 0},
2232         {"SCAN-ALIASES", torture_trans2_aliases, 0},
2233         {"SCAN-SMB", torture_smb_scan, 0},
2234         {"SCAN-MAXFID", NULL, run_maxfidtest},
2235         {"SCAN-UTABLE", torture_utable, 0},
2236         {"SCAN-CASETABLE", torture_casetable, 0},
2237         {"SCAN-PIPE_NUMBER", run_pipe_number, 0},
2238         {"SCAN-IOCTL",  torture_ioctl_test, 0},
2239         {"SCAN-RAP",  torture_rap_scan, 0},
2240
2241         /* local (no server) testers */
2242         {"LOCAL-NTLMSSP", torture_ntlmssp_self_check, 0},
2243         {"LOCAL-ICONV", torture_local_iconv, 0},
2244         {"LOCAL-TALLOC", torture_local_talloc, 0},
2245         {"LOCAL-MESSAGING", torture_local_messaging, 0},
2246         {"LOCAL-IRPC",  torture_local_irpc, 0},
2247         {"LOCAL-BINDING", torture_local_binding_string, 0},
2248         {"LOCAL-STRLIST", torture_local_util_strlist, 0},
2249         {"LOCAL-FILE", torture_local_util_file, 0},
2250         {"LOCAL-IDTREE", torture_local_idtree, 0},
2251         {"LOCAL-SOCKET", torture_local_socket, 0},
2252         {"LOCAL-PAC", torture_pac, 0},
2253         {"LOCAL-REGISTRY", torture_registry, 0},
2254         {"LOCAL-RESOLVE", torture_local_resolve, 0},
2255         {"LOCAL-SDDL", torture_local_sddl, 0},
2256         {"LOCAL-NDR", torture_local_ndr, 0},
2257
2258         /* ldap testers */
2259         {"LDAP-BASIC", torture_ldap_basic, 0},
2260         {"LDAP-CLDAP", torture_cldap, 0},
2261
2262         /* nbt tests */
2263         {"NBT-REGISTER", torture_nbt_register, 0},
2264         {"NBT-WINS", torture_nbt_wins, 0},
2265         {"NBT-DGRAM", torture_nbt_dgram, 0},
2266         {"NBT-BROWSE", torture_nbt_browse, 0},
2267         {"NBT-WINSREPLICATION-SIMPLE", torture_nbt_winsreplication_simple, 0},
2268         {"NBT-WINSREPLICATION-REPLICA", torture_nbt_winsreplication_replica, 0},
2269         {"NBT-WINSREPLICATION-OWNED", torture_nbt_winsreplication_owned, 0},
2270         
2271         /* libnet tests */
2272         {"NET-USERINFO", torture_userinfo, 0},
2273         {"NET-USERADD", torture_useradd, 0},
2274         {"NET-USERDEL", torture_userdel, 0},
2275         {"NET-USERMOD", torture_usermod, 0},
2276         {"NET-DOMOPEN", torture_domainopen, 0},
2277         {"NET-API-LOOKUP", torture_lookup, 0},
2278         {"NET-API-LOOKUPHOST", torture_lookup_host, 0},
2279         {"NET-API-LOOKUPPDC", torture_lookup_pdc, 0},
2280         {"NET-API-CREATEUSER", torture_createuser, 0},
2281         {"NET-API-RPCCONNECT", torture_rpc_connect, 0},
2282         {"NET-API-LISTSHARES", torture_listshares, 0},
2283         {"NET-API-DELSHARE", torture_delshare, 0},
2284
2285         {NULL, NULL, 0}};
2286
2287 static void register_builtin_ops(void)
2288 {
2289         int i;
2290         for (i = 0; builtin_torture_ops[i].name; i++) {
2291                 register_torture_op(builtin_torture_ops[i].name, 
2292                                                         builtin_torture_ops[i].fn, 
2293                                                         builtin_torture_ops[i].multi_fn);
2294         }
2295 }
2296
2297
2298 static struct torture_op {
2299         const char *name;
2300         BOOL (*fn)(void);
2301         BOOL (*multi_fn)(struct smbcli_state *, int );
2302         struct torture_op *prev, *next;
2303 }* torture_ops = NULL;;
2304
2305 static struct torture_op *find_torture_op(const char *name)
2306 {
2307         struct torture_op *o;
2308         for (o = torture_ops; o; o = o->next) {
2309                 if (strcmp(name, o->name) == 0)
2310                         return o;
2311         }
2312
2313         return NULL;
2314 }
2315
2316 NTSTATUS register_torture_op(const char *name, BOOL (*fn)(void), BOOL (*multi_fn)(struct smbcli_state *, int ))
2317 {
2318         struct torture_op *op;
2319         
2320         /* Check for duplicates */
2321         if (find_torture_op(name) != NULL) {
2322                 DEBUG(0,("There already is a torture op registered with the name %s!\n", name));
2323                 return NT_STATUS_OBJECT_NAME_COLLISION;
2324         }
2325
2326         op = talloc(talloc_autofree_context(), struct torture_op);
2327
2328         op->name = talloc_strdup(op, name);
2329         op->fn = fn;
2330         op->multi_fn = multi_fn;
2331
2332         DLIST_ADD(torture_ops, op);
2333         
2334         return NT_STATUS_OK;
2335 }
2336
2337 /****************************************************************************
2338 run a specified test or "ALL"
2339 ****************************************************************************/
2340 static BOOL run_test(const char *name)
2341 {
2342         BOOL ret = True;
2343         struct torture_op *o;
2344         BOOL matched = False;
2345
2346         if (strequal(name,"ALL")) {
2347                 for (o = torture_ops; o; o = o->next) {
2348                         if (!run_test(o->name)) {
2349                                 ret = False;
2350                         }
2351                 }
2352                 return ret;
2353         }
2354
2355         for (o = torture_ops; o; o = o->next) {
2356                 if (gen_fnmatch(name, o->name) == 0) {
2357                         double t;
2358                         matched = True;
2359                         init_iconv();
2360                         printf("Running %s\n", o->name);
2361                         if (o->multi_fn) {
2362                                 BOOL result = False;
2363                                 t = torture_create_procs(o->multi_fn, 
2364                                                          &result);
2365                                 if (!result) { 
2366                                         ret = False;
2367                                         printf("TEST %s FAILED!\n", o->name);
2368                                 }
2369                                          
2370                         } else {
2371                                 struct timeval tv = timeval_current();
2372                                 if (!o->fn()) {
2373                                         ret = False;
2374                                         printf("TEST %s FAILED!\n", o->name);
2375                                 }
2376                                 t = timeval_elapsed(&tv);
2377                         }
2378                         printf("%s took %g secs\n\n", o->name, t);
2379                 }
2380         }
2381
2382         if (!matched) {
2383                 printf("Unknown torture operation '%s'\n", name);
2384         }
2385
2386         return ret;
2387 }
2388
2389
2390 static void parse_dns(const char *dns)
2391 {
2392         char *userdn, *basedn, *secret;
2393         char *p, *d;
2394
2395         /* retrievieng the userdn */
2396         p = strchr_m(dns, '#');
2397         if (!p) {
2398                 lp_set_cmdline("torture:ldap_userdn", "");
2399                 lp_set_cmdline("torture:ldap_basedn", "");
2400                 lp_set_cmdline("torture:ldap_secret", "");
2401                 return;
2402         }
2403         userdn = strndup(dns, p - dns);
2404         lp_set_cmdline("torture:ldap_userdn", userdn);
2405
2406         /* retrieve the basedn */
2407         d = p + 1;
2408         p = strchr_m(d, '#');
2409         if (!p) {
2410                 lp_set_cmdline("torture:ldap_basedn", "");
2411                 lp_set_cmdline("torture:ldap_secret", "");
2412                 return;
2413         }
2414         basedn = strndup(d, p - d);
2415         lp_set_cmdline("torture:ldap_basedn", basedn);
2416
2417         /* retrieve the secret */
2418         p = p + 1;
2419         if (!p) {
2420                 lp_set_cmdline("torture:ldap_secret", "");
2421                 return;
2422         }
2423         secret = strdup(p);
2424         lp_set_cmdline("torture:ldap_secret", secret);
2425
2426         printf ("%s - %s - %s\n", userdn, basedn, secret);
2427
2428 }
2429
2430 static void usage(poptContext pc)
2431 {
2432         struct torture_op *o;
2433         int i;
2434
2435         poptPrintUsage(pc, stdout, 0);
2436         printf("\n");
2437
2438         printf("The binding format is:\n\n");
2439
2440         printf("  TRANSPORT:host[flags]\n\n");
2441
2442         printf("  where TRANSPORT is either ncacn_np for SMB or ncacn_ip_tcp for RPC/TCP\n\n");
2443
2444         printf("  'host' is an IP or hostname or netbios name. If the binding string\n");
2445         printf("  identifies the server side of an endpoint, 'host' may be an empty\n");
2446         printf("  string.\n\n");
2447
2448         printf("  'flags' can include a SMB pipe name if using the ncacn_np transport or\n");
2449         printf("  a TCP port number if using the ncacn_ip_tcp transport, otherwise they\n");
2450         printf("  will be auto-determined.\n\n");
2451
2452         printf("  other recognised flags are:\n\n");
2453
2454         printf("    sign : enable ntlmssp signing\n");
2455         printf("    seal : enable ntlmssp sealing\n");
2456         printf("    connect : enable rpc connect level auth (auth, but no sign or seal)\n");
2457         printf("    validate: enable the NDR validator\n");
2458         printf("    print: enable debugging of the packets\n");
2459         printf("    bigendian: use bigendian RPC\n");
2460         printf("    padcheck: check reply data for non-zero pad bytes\n\n");
2461
2462         printf("  For example, these all connect to the samr pipe:\n\n");
2463
2464         printf("    ncacn_np:myserver\n");
2465         printf("    ncacn_np:myserver[samr]\n");
2466         printf("    ncacn_np:myserver[\\pipe\\samr]\n");
2467         printf("    ncacn_np:myserver[/pipe/samr]\n");
2468         printf("    ncacn_np:myserver[samr,sign,print]\n");
2469         printf("    ncacn_np:myserver[\\pipe\\samr,sign,seal,bigendian]\n");
2470         printf("    ncacn_np:myserver[/pipe/samr,seal,validate]\n");
2471         printf("    ncacn_np:\n");
2472         printf("    ncacn_np:[/pipe/samr]\n\n");
2473
2474         printf("    ncacn_ip_tcp:myserver\n");
2475         printf("    ncacn_ip_tcp:myserver[1024]\n");
2476         printf("    ncacn_ip_tcp:myserver[1024,sign,seal]\n\n");
2477
2478         printf("The unc format is:\n\n");
2479
2480         printf("    //server/share\n\n");
2481
2482         printf("tests are:\n");
2483
2484         i = 0;
2485         for (o = torture_ops; o; o = o->next) {
2486                 if (i + strlen(o->name) >= MAX_COLS) {
2487                         printf("\n");
2488                         i = 0;
2489                 }
2490                 i+=printf("%s ", o->name);
2491         }
2492         printf("\n\n");
2493
2494         printf("default test is ALL\n");
2495
2496         exit(1);
2497 }
2498
2499 static BOOL is_binding_string(const char *binding_string)
2500 {
2501         TALLOC_CTX *mem_ctx = talloc_init("is_binding_string");
2502         struct dcerpc_binding *binding_struct;
2503         NTSTATUS status;
2504         
2505         status = dcerpc_parse_binding(mem_ctx, binding_string, &binding_struct);
2506
2507         talloc_free(mem_ctx);
2508         return NT_STATUS_IS_OK(status);
2509 }
2510
2511 static void max_runtime_handler(int sig)
2512 {
2513         DEBUG(0,("maximum runtime exceeded for smbtorture - terminating\n"));
2514         exit(1);
2515 }
2516
2517 /****************************************************************************
2518   main program
2519 ****************************************************************************/
2520  int main(int argc,char *argv[])
2521 {
2522         int opt, i;
2523         char *p;
2524         BOOL correct = True;
2525         int max_runtime=0;
2526         int argc_new;
2527         char **argv_new;
2528         poptContext pc;
2529         enum {OPT_LOADFILE=1000,OPT_UNCLIST,OPT_TIMELIMIT,OPT_DNS,
2530             OPT_DANGEROUS,OPT_SMB_PORTS};
2531         init_module_fn static_init[] = STATIC_smbtorture_MODULES;
2532         init_module_fn *shared_init = load_samba_modules(NULL, "torture");
2533         
2534         struct poptOption long_options[] = {
2535                 POPT_AUTOHELP
2536                 {"smb-ports",   'p', POPT_ARG_STRING, NULL,     OPT_SMB_PORTS,  "SMB ports",    NULL},
2537                 {"seed",          0, POPT_ARG_INT,  &torture_seed,      0,      "seed",         NULL},
2538                 {"num-progs",     0, POPT_ARG_INT,  &torture_nprocs,    0,      "num progs",    NULL},
2539                 {"num-ops",       0, POPT_ARG_INT,  &torture_numops,    0,      "num ops",      NULL},
2540                 {"entries",       0, POPT_ARG_INT,  &torture_entries,   0,      "entries",      NULL},
2541                 {"use-oplocks", 'L', POPT_ARG_NONE, &use_oplocks,       0,      "use oplocks",  NULL},
2542                 {"show-all",      0, POPT_ARG_NONE, &torture_showall,   0,      "show all",     NULL},
2543                 {"loadfile",      0, POPT_ARG_STRING,   NULL,   OPT_LOADFILE,   "loadfile",     NULL},
2544                 {"unclist",       0, POPT_ARG_STRING,   NULL,   OPT_UNCLIST,    "unclist",      NULL},
2545                 {"timelimit",   't', POPT_ARG_STRING,   NULL,   OPT_TIMELIMIT,  "timelimit",    NULL},
2546                 {"failures",    'f', POPT_ARG_INT,  &torture_failures,  0,      "failures",     NULL},
2547                 {"parse-dns",   'D', POPT_ARG_STRING,   NULL,   OPT_DNS,        "parse-dns",    NULL},
2548                 {"dangerous",   'X', POPT_ARG_NONE,     NULL,   OPT_DANGEROUS,  "dangerous",    NULL},
2549                 {"maximum-runtime", 0, POPT_ARG_INT, &max_runtime, 0, 
2550                  "set maximum time for smbtorture to live", "seconds"},
2551                 POPT_COMMON_SAMBA
2552                 POPT_COMMON_CONNECTION
2553                 POPT_COMMON_CREDENTIALS
2554                 POPT_COMMON_VERSION
2555                 POPT_TABLEEND
2556         };
2557
2558 #ifdef HAVE_SETBUFFER
2559         setbuffer(stdout, NULL, 0);
2560 #endif
2561
2562         register_builtin_ops();
2563
2564         run_init_functions(static_init);
2565         run_init_functions(shared_init);
2566
2567         talloc_free(shared_init);
2568
2569         /* we are never interested in SIGPIPE */
2570         BlockSignals(True,SIGPIPE);
2571
2572         pc = poptGetContext("smbtorture", argc, (const char **) argv, long_options, 
2573                             POPT_CONTEXT_KEEP_FIRST);
2574
2575         poptSetOtherOptionHelp(pc, "<binding>|<unc> TEST1 TEST2 ...");
2576
2577         while((opt = poptGetNextOpt(pc)) != -1) {
2578                 switch (opt) {
2579                 case OPT_LOADFILE:
2580                         lp_set_cmdline("torture:loadfile", poptGetOptArg(pc));
2581                         break;
2582                 case OPT_UNCLIST:
2583                         lp_set_cmdline("torture:unclist", poptGetOptArg(pc));
2584                         break;
2585                 case OPT_TIMELIMIT:
2586                         lp_set_cmdline("torture:timelimit", poptGetOptArg(pc));
2587                         break;
2588                 case OPT_DNS:
2589                         parse_dns(poptGetOptArg(pc));
2590                         break;
2591                 case OPT_DANGEROUS:
2592                         lp_set_cmdline("torture:dangerous", "Yes");
2593                         break;
2594                 case OPT_SMB_PORTS:
2595                         lp_set_cmdline("smb ports", poptGetOptArg(pc));
2596                         break;
2597                 default:
2598                         d_printf("Invalid option %s: %s\n", 
2599                                  poptBadOption(pc, 0), poptStrerror(opt));
2600                         usage(pc);
2601                         exit(1);
2602                 }
2603         }
2604
2605         if (max_runtime) {
2606                 /* this will only work if nobody else uses alarm(),
2607                    which means it won't work for some tests, but we
2608                    can't use the event context method we use for smbd
2609                    as so many tests create their own event
2610                    context. This will at least catch most cases. */
2611                 signal(SIGALRM, max_runtime_handler);
2612                 alarm(max_runtime);
2613         }
2614
2615         ldb_global_init();
2616
2617         dcerpc_init();
2618
2619         dcerpc_table_init();
2620
2621         if (torture_seed == 0) {
2622                 torture_seed = time(NULL);
2623         } 
2624         printf("Using seed %d\n", torture_seed);
2625         srandom(torture_seed);
2626
2627         argv_new = discard_const_p(char *, poptGetArgs(pc));
2628
2629         argc_new = argc;
2630         for (i=0; i<argc; i++) {
2631                 if (argv_new[i] == NULL) {
2632                         argc_new = i;
2633                         break;
2634                 }
2635         }
2636
2637         if (argc_new < 3) {
2638                 usage(pc);
2639                 exit(1);
2640         }
2641
2642         for(p = argv_new[1]; *p; p++) {
2643                 if(*p == '\\')
2644                         *p = '/';
2645         }
2646
2647         /* see if its a RPC transport specifier */
2648         if (is_binding_string(argv_new[1])) {
2649                 lp_set_cmdline("torture:binding", argv_new[1]);
2650         } else {
2651                 char *binding = NULL;
2652                 const char *host = NULL, *share = NULL;
2653
2654                 if (!smbcli_parse_unc(argv_new[1], NULL, &host, &share)) {
2655                         d_printf("Invalid option: %s is not a valid torture target (share or binding string)\n\n", argv_new[1]);
2656                         usage(pc);
2657                 }
2658
2659                 lp_set_cmdline("torture:host", host);
2660                 lp_set_cmdline("torture:share", share);
2661                 asprintf(&binding, "ncacn_np:%s", host);
2662                 lp_set_cmdline("torture:binding", binding);
2663         }
2664
2665         if (argc_new == 0) {
2666                 printf("You must specify a test to run, or 'ALL'\n");
2667         } else {
2668                 for (i=2;i<argc_new;i++) {
2669                         if (!run_test(argv_new[i])) {
2670                                 correct = False;
2671                         }
2672                 }
2673         }
2674
2675         if (correct) {
2676                 return(0);
2677         } else {
2678                 return(1);
2679         }
2680 }