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