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