r13924: Split more prototypes out of include/proto.h + initial work on header
[abartlet/samba.git/.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                         printf("Failed to fill pipe - %s\n", nt_errstr(req->status));
922                         torture_close_connection(cli);
923                         return correct;
924                 }
925         }
926
927         printf("Opening secondary connection\n");
928         if (!torture_open_connection(&cli2)) {
929                 return False;
930         }
931
932         if (!torture_close_connection(cli)) {
933                 correct = False;
934         }
935
936         if (!torture_close_connection(cli2)) {
937                 correct = False;
938         }
939
940         printf("finished negprot nowait test\n");
941
942         return correct;
943 }
944
945
946 /*
947   This checks how the getatr calls works
948 */
949 static BOOL run_attrtest(void)
950 {
951         struct smbcli_state *cli;
952         int fnum;
953         time_t t, t2;
954         const char *fname = "\\attrib123456789.tst";
955         BOOL correct = True;
956
957         printf("starting attrib test\n");
958
959         if (!torture_open_connection(&cli)) {
960                 return False;
961         }
962
963         smbcli_unlink(cli->tree, fname);
964         fnum = smbcli_open(cli->tree, fname, 
965                         O_RDWR | O_CREAT | O_TRUNC, DENY_NONE);
966         smbcli_close(cli->tree, fnum);
967
968         if (NT_STATUS_IS_ERR(smbcli_getatr(cli->tree, fname, NULL, NULL, &t))) {
969                 printf("getatr failed (%s)\n", smbcli_errstr(cli->tree));
970                 correct = False;
971         }
972
973         printf("New file time is %s", ctime(&t));
974
975         if (abs(t - time(NULL)) > 60*60*24*10) {
976                 printf("ERROR: SMBgetatr bug. time is %s",
977                        ctime(&t));
978                 t = time(NULL);
979                 correct = False;
980         }
981
982         t2 = t-60*60*24; /* 1 day ago */
983
984         printf("Setting file time to %s", ctime(&t2));
985
986         if (NT_STATUS_IS_ERR(smbcli_setatr(cli->tree, fname, 0, t2))) {
987                 printf("setatr failed (%s)\n", smbcli_errstr(cli->tree));
988                 correct = True;
989         }
990
991         if (NT_STATUS_IS_ERR(smbcli_getatr(cli->tree, fname, NULL, NULL, &t))) {
992                 printf("getatr failed (%s)\n", smbcli_errstr(cli->tree));
993                 correct = True;
994         }
995
996         printf("Retrieved file time as %s", ctime(&t));
997
998         if (t != t2) {
999                 printf("ERROR: getatr/setatr bug. times are\n%s",
1000                        ctime(&t));
1001                 printf("%s", ctime(&t2));
1002                 correct = True;
1003         }
1004
1005         smbcli_unlink(cli->tree, fname);
1006
1007         if (!torture_close_connection(cli)) {
1008                 correct = False;
1009         }
1010
1011         printf("attrib test finished\n");
1012
1013         return correct;
1014 }
1015
1016
1017 /*
1018   This checks a couple of trans2 calls
1019 */
1020 static BOOL run_trans2test(void)
1021 {
1022         struct smbcli_state *cli;
1023         int fnum;
1024         size_t size;
1025         time_t c_time, a_time, m_time, w_time, m_time2;
1026         const char *fname = "\\trans2.tst";
1027         const char *dname = "\\trans2";
1028         const char *fname2 = "\\trans2\\trans2.tst";
1029         const char *pname;
1030         BOOL correct = True;
1031
1032         printf("starting trans2 test\n");
1033
1034         if (!torture_open_connection(&cli)) {
1035                 return False;
1036         }
1037
1038         smbcli_unlink(cli->tree, fname);
1039
1040         printf("Testing qfileinfo\n");
1041         
1042         fnum = smbcli_open(cli->tree, fname, 
1043                         O_RDWR | O_CREAT | O_TRUNC, DENY_NONE);
1044         if (NT_STATUS_IS_ERR(smbcli_qfileinfo(cli->tree, fnum, NULL, &size, &c_time, &a_time, &m_time,
1045                            NULL, NULL))) {
1046                 printf("ERROR: qfileinfo failed (%s)\n", smbcli_errstr(cli->tree));
1047                 correct = False;
1048         }
1049
1050         printf("Testing NAME_INFO\n");
1051
1052         if (NT_STATUS_IS_ERR(smbcli_qfilename(cli->tree, fnum, &pname))) {
1053                 printf("ERROR: qfilename failed (%s)\n", smbcli_errstr(cli->tree));
1054                 correct = False;
1055         }
1056
1057         if (!pname || strcmp(pname, fname)) {
1058                 printf("qfilename gave different name? [%s] [%s]\n",
1059                        fname, pname);
1060                 correct = False;
1061         }
1062
1063         smbcli_close(cli->tree, fnum);
1064         smbcli_unlink(cli->tree, fname);
1065
1066         fnum = smbcli_open(cli->tree, fname, 
1067                         O_RDWR | O_CREAT | O_TRUNC, DENY_NONE);
1068         if (fnum == -1) {
1069                 printf("open of %s failed (%s)\n", fname, smbcli_errstr(cli->tree));
1070                 return False;
1071         }
1072         smbcli_close(cli->tree, fnum);
1073
1074         printf("Checking for sticky create times\n");
1075
1076         if (NT_STATUS_IS_ERR(smbcli_qpathinfo(cli->tree, fname, &c_time, &a_time, &m_time, &size, NULL))) {
1077                 printf("ERROR: qpathinfo failed (%s)\n", smbcli_errstr(cli->tree));
1078                 correct = False;
1079         } else {
1080                 if (c_time != m_time) {
1081                         printf("create time=%s", ctime(&c_time));
1082                         printf("modify time=%s", ctime(&m_time));
1083                         printf("This system appears to have sticky create times\n");
1084                 }
1085                 if (a_time % (60*60) == 0) {
1086                         printf("access time=%s", ctime(&a_time));
1087                         printf("This system appears to set a midnight access time\n");
1088                         correct = False;
1089                 }
1090
1091                 if (abs(m_time - time(NULL)) > 60*60*24*7) {
1092                         printf("ERROR: totally incorrect times - maybe word reversed? mtime=%s", ctime(&m_time));
1093                         correct = False;
1094                 }
1095         }
1096
1097
1098         smbcli_unlink(cli->tree, fname);
1099         fnum = smbcli_open(cli->tree, fname, 
1100                         O_RDWR | O_CREAT | O_TRUNC, DENY_NONE);
1101         smbcli_close(cli->tree, fnum);
1102         if (NT_STATUS_IS_ERR(smbcli_qpathinfo2(cli->tree, fname, &c_time, &a_time, &m_time, &w_time, &size, NULL, NULL))) {
1103                 printf("ERROR: qpathinfo2 failed (%s)\n", smbcli_errstr(cli->tree));
1104                 correct = False;
1105         } else {
1106                 if (w_time < 60*60*24*2) {
1107                         printf("write time=%s", ctime(&w_time));
1108                         printf("This system appears to set a initial 0 write time\n");
1109                         correct = False;
1110                 }
1111         }
1112
1113         smbcli_unlink(cli->tree, fname);
1114
1115
1116         /* check if the server updates the directory modification time
1117            when creating a new file */
1118         if (NT_STATUS_IS_ERR(smbcli_mkdir(cli->tree, dname))) {
1119                 printf("ERROR: mkdir failed (%s)\n", smbcli_errstr(cli->tree));
1120                 correct = False;
1121         }
1122         sleep(3);
1123         if (NT_STATUS_IS_ERR(smbcli_qpathinfo2(cli->tree, "\\trans2\\", &c_time, &a_time, &m_time, &w_time, &size, NULL, NULL))) {
1124                 printf("ERROR: qpathinfo2 failed (%s)\n", smbcli_errstr(cli->tree));
1125                 correct = False;
1126         }
1127
1128         fnum = smbcli_open(cli->tree, fname2, 
1129                         O_RDWR | O_CREAT | O_TRUNC, DENY_NONE);
1130         smbcli_write(cli->tree, fnum,  0, &fnum, 0, sizeof(fnum));
1131         smbcli_close(cli->tree, fnum);
1132         if (NT_STATUS_IS_ERR(smbcli_qpathinfo2(cli->tree, "\\trans2\\", &c_time, &a_time, &m_time2, &w_time, &size, NULL, NULL))) {
1133                 printf("ERROR: qpathinfo2 failed (%s)\n", smbcli_errstr(cli->tree));
1134                 correct = False;
1135         } else {
1136                 if (m_time2 == m_time) {
1137                         printf("This system does not update directory modification times\n");
1138                         correct = False;
1139                 }
1140         }
1141         smbcli_unlink(cli->tree, fname2);
1142         smbcli_rmdir(cli->tree, dname);
1143
1144         if (!torture_close_connection(cli)) {
1145                 correct = False;
1146         }
1147
1148         printf("trans2 test finished\n");
1149
1150         return correct;
1151 }
1152
1153
1154
1155 /* FIRST_DESIRED_ACCESS   0xf019f */
1156 #define FIRST_DESIRED_ACCESS   SEC_FILE_READ_DATA|SEC_FILE_WRITE_DATA|SEC_FILE_APPEND_DATA|\
1157                                SEC_FILE_READ_EA|                           /* 0xf */ \
1158                                SEC_FILE_WRITE_EA|SEC_FILE_READ_ATTRIBUTE|     /* 0x90 */ \
1159                                SEC_FILE_WRITE_ATTRIBUTE|                  /* 0x100 */ \
1160                                SEC_STD_DELETE|SEC_STD_READ_CONTROL|\
1161                                SEC_STD_WRITE_DAC|SEC_STD_WRITE_OWNER     /* 0xf0000 */
1162 /* SECOND_DESIRED_ACCESS  0xe0080 */
1163 #define SECOND_DESIRED_ACCESS  SEC_FILE_READ_ATTRIBUTE|                   /* 0x80 */ \
1164                                SEC_STD_READ_CONTROL|SEC_STD_WRITE_DAC|\
1165                                SEC_STD_WRITE_OWNER                      /* 0xe0000 */
1166
1167 #if 0
1168 #define THIRD_DESIRED_ACCESS   FILE_READ_ATTRIBUTE|                   /* 0x80 */ \
1169                                READ_CONTROL|WRITE_DAC|\
1170                                SEC_FILE_READ_DATA|\
1171                                WRITE_OWNER                      /* */
1172 #endif
1173
1174 /*
1175   Test ntcreate calls made by xcopy
1176  */
1177 static BOOL run_xcopy(void)
1178 {
1179         struct smbcli_state *cli1;
1180         const char *fname = "\\test.txt";
1181         BOOL correct = True;
1182         int fnum1, fnum2;
1183
1184         printf("starting xcopy test\n");
1185         
1186         if (!torture_open_connection(&cli1)) {
1187                 return False;
1188         }
1189         
1190         fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0,
1191                                       FIRST_DESIRED_ACCESS, 
1192                                       FILE_ATTRIBUTE_ARCHIVE,
1193                                       NTCREATEX_SHARE_ACCESS_NONE, 
1194                                       NTCREATEX_DISP_OVERWRITE_IF, 
1195                                       0x4044, 0);
1196
1197         if (fnum1 == -1) {
1198                 printf("First open failed - %s\n", smbcli_errstr(cli1->tree));
1199                 return False;
1200         }
1201
1202         fnum2 = smbcli_nt_create_full(cli1->tree, fname, 0,
1203                                    SECOND_DESIRED_ACCESS, 0,
1204                                    NTCREATEX_SHARE_ACCESS_READ|NTCREATEX_SHARE_ACCESS_WRITE|NTCREATEX_SHARE_ACCESS_DELETE, NTCREATEX_DISP_OPEN, 
1205                                    0x200000, 0);
1206         if (fnum2 == -1) {
1207                 printf("second open failed - %s\n", smbcli_errstr(cli1->tree));
1208                 return False;
1209         }
1210         
1211         if (!torture_close_connection(cli1)) {
1212                 correct = False;
1213         }
1214         
1215         return correct;
1216 }
1217
1218
1219 /*
1220   see how many RPC pipes we can open at once
1221 */
1222 static BOOL run_pipe_number(void)
1223 {
1224         struct smbcli_state *cli1;
1225         const char *pipe_name = "\\WKSSVC";
1226         int fnum;
1227         int num_pipes = 0;
1228
1229         printf("starting pipenumber test\n");
1230         if (!torture_open_connection(&cli1)) {
1231                 return False;
1232         }
1233
1234         while(1) {
1235                 fnum = smbcli_nt_create_full(cli1->tree, pipe_name, 0, SEC_FILE_READ_DATA, FILE_ATTRIBUTE_NORMAL,
1236                                    NTCREATEX_SHARE_ACCESS_READ|NTCREATEX_SHARE_ACCESS_WRITE, NTCREATEX_DISP_OPEN_IF, 0, 0);
1237
1238                 if (fnum == -1) {
1239                         printf("Open of pipe %s failed with error (%s)\n", pipe_name, smbcli_errstr(cli1->tree));
1240                         break;
1241                 }
1242                 num_pipes++;
1243                 printf("%d\r", num_pipes);
1244                 fflush(stdout);
1245         }
1246
1247         printf("pipe_number test - we can open %d %s pipes.\n", num_pipes, pipe_name );
1248         torture_close_connection(cli1);
1249         return True;
1250 }
1251
1252
1253
1254
1255 /*
1256   open N connections to the server and just hold them open
1257   used for testing performance when there are N idle users
1258   already connected
1259  */
1260  static BOOL torture_holdcon(void)
1261 {
1262         int i;
1263         struct smbcli_state **cli;
1264         int num_dead = 0;
1265
1266         printf("Opening %d connections\n", torture_numops);
1267         
1268         cli = malloc_array_p(struct smbcli_state *, torture_numops);
1269
1270         for (i=0;i<torture_numops;i++) {
1271                 if (!torture_open_connection(&cli[i])) {
1272                         return False;
1273                 }
1274                 printf("opened %d connections\r", i);
1275                 fflush(stdout);
1276         }
1277
1278         printf("\nStarting pings\n");
1279
1280         while (1) {
1281                 for (i=0;i<torture_numops;i++) {
1282                         NTSTATUS status;
1283                         if (cli[i]) {
1284                                 status = smbcli_chkpath(cli[i]->tree, "\\");
1285                                 if (!NT_STATUS_IS_OK(status)) {
1286                                         printf("Connection %d is dead\n", i);
1287                                         cli[i] = NULL;
1288                                         num_dead++;
1289                                 }
1290                                 usleep(100);
1291                         }
1292                 }
1293
1294                 if (num_dead == torture_numops) {
1295                         printf("All connections dead - finishing\n");
1296                         break;
1297                 }
1298
1299                 printf(".");
1300                 fflush(stdout);
1301         }
1302
1303         return True;
1304 }
1305
1306 /*
1307   Try with a wrong vuid and check error message.
1308  */
1309
1310 static BOOL run_vuidtest(void)
1311 {
1312         struct smbcli_state *cli;
1313         const char *fname = "\\vuid.tst";
1314         int fnum;
1315         size_t size;
1316         time_t c_time, a_time, m_time;
1317         BOOL correct = True;
1318
1319         uint16_t orig_vuid;
1320         NTSTATUS result;
1321
1322         printf("starting vuid test\n");
1323
1324         if (!torture_open_connection(&cli)) {
1325                 return False;
1326         }
1327
1328         smbcli_unlink(cli->tree, fname);
1329
1330         fnum = smbcli_open(cli->tree, fname, 
1331                         O_RDWR | O_CREAT | O_TRUNC, DENY_NONE);
1332
1333         orig_vuid = cli->session->vuid;
1334
1335         cli->session->vuid += 1234;
1336
1337         printf("Testing qfileinfo with wrong vuid\n");
1338         
1339         if (NT_STATUS_IS_OK(result = smbcli_qfileinfo(cli->tree, fnum, NULL,
1340                                                    &size, &c_time, &a_time,
1341                                                    &m_time, NULL, NULL))) {
1342                 printf("ERROR: qfileinfo passed with wrong vuid\n");
1343                 correct = False;
1344         }
1345
1346         if (!NT_STATUS_EQUAL(cli->transport->error.e.nt_status, 
1347                              NT_STATUS_DOS(ERRSRV, ERRbaduid)) &&
1348             !NT_STATUS_EQUAL(cli->transport->error.e.nt_status, 
1349                              NT_STATUS_INVALID_HANDLE)) {
1350                 printf("ERROR: qfileinfo should have returned DOS error "
1351                        "ERRSRV:ERRbaduid\n  but returned %s\n",
1352                        smbcli_errstr(cli->tree));
1353                 correct = False;
1354         }
1355
1356         cli->session->vuid -= 1234;
1357
1358         if (NT_STATUS_IS_ERR(smbcli_close(cli->tree, fnum))) {
1359                 printf("close failed (%s)\n", smbcli_errstr(cli->tree));
1360                 correct = False;
1361         }
1362
1363         smbcli_unlink(cli->tree, fname);
1364
1365         if (!torture_close_connection(cli)) {
1366                 correct = False;
1367         }
1368
1369         printf("vuid test finished\n");
1370
1371         return correct;
1372 }
1373
1374 /*
1375   Test open mode returns on read-only files.
1376  */
1377  static BOOL run_opentest(void)
1378 {
1379         static struct smbcli_state *cli1;
1380         static struct smbcli_state *cli2;
1381         const char *fname = "\\readonly.file";
1382         char *control_char_fname;
1383         int fnum1, fnum2;
1384         uint8_t buf[20];
1385         size_t fsize;
1386         BOOL correct = True;
1387         char *tmp_path;
1388         int failures = 0;
1389         int i;
1390
1391         printf("starting open test\n");
1392         
1393         if (!torture_open_connection(&cli1)) {
1394                 return False;
1395         }
1396         
1397         asprintf(&control_char_fname, "\\readonly.afile");
1398         for (i = 1; i <= 0x1f; i++) {
1399                 control_char_fname[10] = i;
1400                 fnum1 = smbcli_nt_create_full(cli1->tree, control_char_fname, 0, SEC_FILE_WRITE_DATA, FILE_ATTRIBUTE_NORMAL,
1401                                    NTCREATEX_SHARE_ACCESS_NONE, NTCREATEX_DISP_OVERWRITE_IF, 0, 0);
1402                 
1403                 if (!check_error(__location__, cli1, ERRDOS, ERRinvalidname, 
1404                                 NT_STATUS_OBJECT_NAME_INVALID)) {
1405                         printf("Error code should be NT_STATUS_OBJECT_NAME_INVALID, was %s for file with %d char\n",
1406                                         smbcli_errstr(cli1->tree), i);
1407                         failures++;
1408                 }
1409
1410                 if (fnum1 != -1) {
1411                         smbcli_close(cli1->tree, fnum1);
1412                 }
1413                 smbcli_setatr(cli1->tree, control_char_fname, 0, 0);
1414                 smbcli_unlink(cli1->tree, control_char_fname);
1415         }
1416         free(control_char_fname);
1417
1418         if (!failures)
1419                 printf("Create file with control char names passed.\n");
1420
1421         smbcli_setatr(cli1->tree, fname, 0, 0);
1422         smbcli_unlink(cli1->tree, fname);
1423         
1424         fnum1 = smbcli_open(cli1->tree, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
1425         if (fnum1 == -1) {
1426                 printf("open of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
1427                 return False;
1428         }
1429
1430         if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum1))) {
1431                 printf("close2 failed (%s)\n", smbcli_errstr(cli1->tree));
1432                 return False;
1433         }
1434         
1435         if (NT_STATUS_IS_ERR(smbcli_setatr(cli1->tree, fname, FILE_ATTRIBUTE_READONLY, 0))) {
1436                 printf("smbcli_setatr failed (%s)\n", smbcli_errstr(cli1->tree));
1437                 CHECK_MAX_FAILURES(error_test1);
1438                 return False;
1439         }
1440         
1441         fnum1 = smbcli_open(cli1->tree, fname, O_RDONLY, DENY_WRITE);
1442         if (fnum1 == -1) {
1443                 printf("open of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
1444                 CHECK_MAX_FAILURES(error_test1);
1445                 return False;
1446         }
1447         
1448         /* This will fail - but the error should be ERRnoaccess, not ERRbadshare. */
1449         fnum2 = smbcli_open(cli1->tree, fname, O_RDWR, DENY_ALL);
1450         
1451         if (check_error(__location__, cli1, ERRDOS, ERRnoaccess, 
1452                         NT_STATUS_ACCESS_DENIED)) {
1453                 printf("correct error code ERRDOS/ERRnoaccess returned\n");
1454         }
1455         
1456         printf("finished open test 1\n");
1457 error_test1:
1458         smbcli_close(cli1->tree, fnum1);
1459         
1460         /* Now try not readonly and ensure ERRbadshare is returned. */
1461         
1462         smbcli_setatr(cli1->tree, fname, 0, 0);
1463         
1464         fnum1 = smbcli_open(cli1->tree, fname, O_RDONLY, DENY_WRITE);
1465         if (fnum1 == -1) {
1466                 printf("open of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
1467                 return False;
1468         }
1469         
1470         /* This will fail - but the error should be ERRshare. */
1471         fnum2 = smbcli_open(cli1->tree, fname, O_RDWR, DENY_ALL);
1472         
1473         if (check_error(__location__, cli1, ERRDOS, ERRbadshare, 
1474                         NT_STATUS_SHARING_VIOLATION)) {
1475                 printf("correct error code ERRDOS/ERRbadshare returned\n");
1476         }
1477         
1478         if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum1))) {
1479                 printf("close2 failed (%s)\n", smbcli_errstr(cli1->tree));
1480                 return False;
1481         }
1482         
1483         smbcli_unlink(cli1->tree, fname);
1484         
1485         printf("finished open test 2\n");
1486         
1487         /* Test truncate open disposition on file opened for read. */
1488         
1489         fnum1 = smbcli_open(cli1->tree, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
1490         if (fnum1 == -1) {
1491                 printf("(3) open (1) of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
1492                 return False;
1493         }
1494         
1495         /* write 20 bytes. */
1496         
1497         memset(buf, '\0', 20);
1498
1499         if (smbcli_write(cli1->tree, fnum1, 0, buf, 0, 20) != 20) {
1500                 printf("write failed (%s)\n", smbcli_errstr(cli1->tree));
1501                 correct = False;
1502         }
1503
1504         if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum1))) {
1505                 printf("(3) close1 failed (%s)\n", smbcli_errstr(cli1->tree));
1506                 return False;
1507         }
1508         
1509         /* Ensure size == 20. */
1510         if (NT_STATUS_IS_ERR(smbcli_getatr(cli1->tree, fname, NULL, &fsize, NULL))) {
1511                 printf("(3) getatr failed (%s)\n", smbcli_errstr(cli1->tree));
1512                 CHECK_MAX_FAILURES(error_test3);
1513                 return False;
1514         }
1515         
1516         if (fsize != 20) {
1517                 printf("(3) file size != 20\n");
1518                 CHECK_MAX_FAILURES(error_test3);
1519                 return False;
1520         }
1521
1522         /* Now test if we can truncate a file opened for readonly. */
1523         
1524         fnum1 = smbcli_open(cli1->tree, fname, O_RDONLY|O_TRUNC, DENY_NONE);
1525         if (fnum1 == -1) {
1526                 printf("(3) open (2) of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
1527                 CHECK_MAX_FAILURES(error_test3);
1528                 return False;
1529         }
1530         
1531         if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum1))) {
1532                 printf("close2 failed (%s)\n", smbcli_errstr(cli1->tree));
1533                 return False;
1534         }
1535
1536         /* Ensure size == 0. */
1537         if (NT_STATUS_IS_ERR(smbcli_getatr(cli1->tree, fname, NULL, &fsize, NULL))) {
1538                 printf("(3) getatr failed (%s)\n", smbcli_errstr(cli1->tree));
1539                 CHECK_MAX_FAILURES(error_test3);
1540                 return False;
1541         }
1542
1543         if (fsize != 0) {
1544                 printf("(3) file size != 0\n");
1545                 CHECK_MAX_FAILURES(error_test3);
1546                 return False;
1547         }
1548         printf("finished open test 3\n");
1549 error_test3:    
1550         smbcli_unlink(cli1->tree, fname);
1551
1552
1553         printf("testing ctemp\n");
1554         fnum1 = smbcli_ctemp(cli1->tree, "\\", &tmp_path);
1555         if (fnum1 == -1) {
1556                 printf("ctemp failed (%s)\n", smbcli_errstr(cli1->tree));
1557                 CHECK_MAX_FAILURES(error_test4);
1558                 return False;
1559         }
1560         printf("ctemp gave path %s\n", tmp_path);
1561         if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum1))) {
1562                 printf("close of temp failed (%s)\n", smbcli_errstr(cli1->tree));
1563         }
1564         if (NT_STATUS_IS_ERR(smbcli_unlink(cli1->tree, tmp_path))) {
1565                 printf("unlink of temp failed (%s)\n", smbcli_errstr(cli1->tree));
1566         }
1567 error_test4:    
1568         /* Test the non-io opens... */
1569
1570         if (!torture_open_connection(&cli2)) {
1571                 return False;
1572         }
1573         
1574         smbcli_setatr(cli2->tree, fname, 0, 0);
1575         smbcli_unlink(cli2->tree, fname);
1576         
1577         printf("TEST #1 testing 2 non-io opens (no delete)\n");
1578         
1579         fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0, SEC_FILE_READ_ATTRIBUTE, FILE_ATTRIBUTE_NORMAL,
1580                                    NTCREATEX_SHARE_ACCESS_NONE, NTCREATEX_DISP_OVERWRITE_IF, 0, 0);
1581
1582         if (fnum1 == -1) {
1583                 printf("test 1 open 1 of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
1584                 CHECK_MAX_FAILURES(error_test10);
1585                 return False;
1586         }
1587
1588         fnum2 = smbcli_nt_create_full(cli2->tree, fname, 0, SEC_FILE_READ_ATTRIBUTE, FILE_ATTRIBUTE_NORMAL,
1589                                    NTCREATEX_SHARE_ACCESS_NONE, NTCREATEX_DISP_OPEN_IF, 0, 0);
1590         if (fnum2 == -1) {
1591                 printf("test 1 open 2 of %s failed (%s)\n", fname, smbcli_errstr(cli2->tree));
1592                 CHECK_MAX_FAILURES(error_test10);
1593                 return False;
1594         }
1595
1596         if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum1))) {
1597                 printf("test 1 close 1 of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
1598                 return False;
1599         }
1600         if (NT_STATUS_IS_ERR(smbcli_close(cli2->tree, fnum2))) {
1601                 printf("test 1 close 2 of %s failed (%s)\n", fname, smbcli_errstr(cli2->tree));
1602                 return False;
1603         }
1604
1605         printf("non-io open test #1 passed.\n");
1606 error_test10:
1607         smbcli_unlink(cli1->tree, fname);
1608
1609         printf("TEST #2 testing 2 non-io opens (first with delete)\n");
1610         
1611         fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0, SEC_STD_DELETE|SEC_FILE_READ_ATTRIBUTE, FILE_ATTRIBUTE_NORMAL,
1612                                    NTCREATEX_SHARE_ACCESS_NONE, NTCREATEX_DISP_OVERWRITE_IF, 0, 0);
1613
1614         if (fnum1 == -1) {
1615                 printf("test 2 open 1 of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
1616                 CHECK_MAX_FAILURES(error_test20);
1617                 return False;
1618         }
1619
1620         fnum2 = smbcli_nt_create_full(cli2->tree, fname, 0, SEC_FILE_READ_ATTRIBUTE, FILE_ATTRIBUTE_NORMAL,
1621                                    NTCREATEX_SHARE_ACCESS_NONE, NTCREATEX_DISP_OPEN_IF, 0, 0);
1622
1623         if (fnum2 == -1) {
1624                 printf("test 2 open 2 of %s failed (%s)\n", fname, smbcli_errstr(cli2->tree));
1625                 CHECK_MAX_FAILURES(error_test20);
1626                 return False;
1627         }
1628
1629         if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum1))) {
1630                 printf("test 1 close 1 of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
1631                 return False;
1632         }
1633         if (NT_STATUS_IS_ERR(smbcli_close(cli2->tree, fnum2))) {
1634                 printf("test 1 close 2 of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
1635                 return False;
1636         }
1637
1638         printf("non-io open test #2 passed.\n");
1639 error_test20:
1640         smbcli_unlink(cli1->tree, fname);
1641
1642         printf("TEST #3 testing 2 non-io opens (second with delete)\n");
1643         
1644         fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0, SEC_FILE_READ_ATTRIBUTE, FILE_ATTRIBUTE_NORMAL,
1645                                    NTCREATEX_SHARE_ACCESS_NONE, NTCREATEX_DISP_OVERWRITE_IF, 0, 0);
1646
1647         if (fnum1 == -1) {
1648                 printf("test 3 open 1 of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
1649                 CHECK_MAX_FAILURES(error_test30);
1650                 return False;
1651         }
1652
1653         fnum2 = smbcli_nt_create_full(cli2->tree, fname, 0, SEC_STD_DELETE|SEC_FILE_READ_ATTRIBUTE, FILE_ATTRIBUTE_NORMAL,
1654                                    NTCREATEX_SHARE_ACCESS_NONE, NTCREATEX_DISP_OPEN_IF, 0, 0);
1655
1656         if (fnum2 == -1) {
1657                 printf("test 3 open 2 of %s failed (%s)\n", fname, smbcli_errstr(cli2->tree));
1658                 CHECK_MAX_FAILURES(error_test30);
1659                 return False;
1660         }
1661
1662         if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum1))) {
1663                 printf("test 3 close 1 of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
1664                 return False;
1665         }
1666         if (NT_STATUS_IS_ERR(smbcli_close(cli2->tree, fnum2))) {
1667                 printf("test 3 close 2 of %s failed (%s)\n", fname, smbcli_errstr(cli2->tree));
1668                 return False;
1669         }
1670
1671         printf("non-io open test #3 passed.\n");
1672 error_test30:
1673         smbcli_unlink(cli1->tree, fname);
1674
1675         printf("TEST #4 testing 2 non-io opens (both with delete)\n");
1676         
1677         fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0, SEC_STD_DELETE|SEC_FILE_READ_ATTRIBUTE, FILE_ATTRIBUTE_NORMAL,
1678                                    NTCREATEX_SHARE_ACCESS_NONE, NTCREATEX_DISP_OVERWRITE_IF, 0, 0);
1679
1680         if (fnum1 == -1) {
1681                 printf("test 4 open 1 of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
1682                 CHECK_MAX_FAILURES(error_test40);
1683                 return False;
1684         }
1685
1686         fnum2 = smbcli_nt_create_full(cli2->tree, fname, 0, SEC_STD_DELETE|SEC_FILE_READ_ATTRIBUTE, FILE_ATTRIBUTE_NORMAL,
1687                                    NTCREATEX_SHARE_ACCESS_NONE, NTCREATEX_DISP_OPEN_IF, 0, 0);
1688
1689         if (fnum2 != -1) {
1690                 printf("test 4 open 2 of %s SUCCEEDED - should have failed (%s)\n", fname, smbcli_errstr(cli2->tree));
1691                 CHECK_MAX_FAILURES(error_test40);
1692                 return False;
1693         }
1694
1695         printf("test 4 open 2 of %s gave %s (correct error should be %s)\n", fname, smbcli_errstr(cli2->tree), "sharing violation");
1696
1697         if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum1))) {
1698                 printf("test 4 close 1 of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
1699                 return False;
1700         }
1701
1702         printf("non-io open test #4 passed.\n");
1703 error_test40:
1704         smbcli_unlink(cli1->tree, fname);
1705
1706         printf("TEST #5 testing 2 non-io opens (both with delete - both with file share delete)\n");
1707         
1708         fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0, SEC_STD_DELETE|SEC_FILE_READ_ATTRIBUTE, FILE_ATTRIBUTE_NORMAL,
1709                                    NTCREATEX_SHARE_ACCESS_DELETE, NTCREATEX_DISP_OVERWRITE_IF, 0, 0);
1710
1711         if (fnum1 == -1) {
1712                 printf("test 5 open 1 of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
1713                 CHECK_MAX_FAILURES(error_test50);
1714                 return False;
1715         }
1716
1717         fnum2 = smbcli_nt_create_full(cli2->tree, fname, 0, SEC_STD_DELETE|SEC_FILE_READ_ATTRIBUTE, FILE_ATTRIBUTE_NORMAL,
1718                                    NTCREATEX_SHARE_ACCESS_DELETE, NTCREATEX_DISP_OPEN_IF, 0, 0);
1719
1720         if (fnum2 == -1) {
1721                 printf("test 5 open 2 of %s failed (%s)\n", fname, smbcli_errstr(cli2->tree));
1722                 CHECK_MAX_FAILURES(error_test50);
1723                 return False;
1724         }
1725
1726         if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum1))) {
1727                 printf("test 5 close 1 of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
1728                 return False;
1729         }
1730
1731         if (NT_STATUS_IS_ERR(smbcli_close(cli2->tree, fnum2))) {
1732                 printf("test 5 close 2 of %s failed (%s)\n", fname, smbcli_errstr(cli2->tree));
1733                 return False;
1734         }
1735
1736         printf("non-io open test #5 passed.\n");
1737 error_test50:
1738         printf("TEST #6 testing 1 non-io open, one io open\n");
1739         
1740         smbcli_unlink(cli1->tree, fname);
1741
1742         fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0, SEC_FILE_READ_DATA, FILE_ATTRIBUTE_NORMAL,
1743                                    NTCREATEX_SHARE_ACCESS_NONE, NTCREATEX_DISP_OVERWRITE_IF, 0, 0);
1744
1745         if (fnum1 == -1) {
1746                 printf("test 6 open 1 of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
1747                 CHECK_MAX_FAILURES(error_test60);
1748                 return False;
1749         }
1750
1751         fnum2 = smbcli_nt_create_full(cli2->tree, fname, 0, SEC_FILE_READ_ATTRIBUTE, FILE_ATTRIBUTE_NORMAL,
1752                                    NTCREATEX_SHARE_ACCESS_READ, NTCREATEX_DISP_OPEN_IF, 0, 0);
1753
1754         if (fnum2 == -1) {
1755                 printf("test 6 open 2 of %s failed (%s)\n", fname, smbcli_errstr(cli2->tree));
1756                 CHECK_MAX_FAILURES(error_test60);
1757                 return False;
1758         }
1759
1760         if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum1))) {
1761                 printf("test 6 close 1 of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
1762                 return False;
1763         }
1764
1765         if (NT_STATUS_IS_ERR(smbcli_close(cli2->tree, fnum2))) {
1766                 printf("test 6 close 2 of %s failed (%s)\n", fname, smbcli_errstr(cli2->tree));
1767                 return False;
1768         }
1769
1770         printf("non-io open test #6 passed.\n");
1771 error_test60:
1772         printf("TEST #7 testing 1 non-io open, one io open with delete\n");
1773
1774         smbcli_unlink(cli1->tree, fname);
1775
1776         fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0, SEC_FILE_READ_DATA, FILE_ATTRIBUTE_NORMAL,
1777                                    NTCREATEX_SHARE_ACCESS_NONE, NTCREATEX_DISP_OVERWRITE_IF, 0, 0);
1778
1779         if (fnum1 == -1) {
1780                 printf("test 7 open 1 of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
1781                 CHECK_MAX_FAILURES(error_test70);
1782                 return False;
1783         }
1784
1785         fnum2 = smbcli_nt_create_full(cli2->tree, fname, 0, SEC_STD_DELETE|SEC_FILE_READ_ATTRIBUTE, FILE_ATTRIBUTE_NORMAL,
1786                                    NTCREATEX_SHARE_ACCESS_READ|NTCREATEX_SHARE_ACCESS_DELETE, NTCREATEX_DISP_OPEN_IF, 0, 0);
1787
1788         if (fnum2 != -1) {
1789                 printf("test 7 open 2 of %s SUCCEEDED - should have failed (%s)\n", fname, smbcli_errstr(cli2->tree));
1790                 CHECK_MAX_FAILURES(error_test70);
1791                 return False;
1792         }
1793
1794         printf("test 7 open 2 of %s gave %s (correct error should be %s)\n", fname, smbcli_errstr(cli2->tree), "sharing violation");
1795
1796         if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum1))) {
1797                 printf("test 7 close 1 of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
1798                 return False;
1799         }
1800
1801         printf("non-io open test #7 passed.\n");
1802
1803 error_test70:
1804
1805         printf("TEST #8 testing one normal open, followed by lock, followed by open with truncate\n");
1806
1807         smbcli_unlink(cli1->tree, fname);
1808
1809         fnum1 = smbcli_open(cli1->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
1810         if (fnum1 == -1) {
1811                 printf("(8) open (1) of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
1812                 return False;
1813         }
1814         
1815         /* write 20 bytes. */
1816         
1817         memset(buf, '\0', 20);
1818
1819         if (smbcli_write(cli1->tree, fnum1, 0, buf, 0, 20) != 20) {
1820                 printf("(8) write failed (%s)\n", smbcli_errstr(cli1->tree));
1821                 correct = False;
1822         }
1823
1824         /* Ensure size == 20. */
1825         if (NT_STATUS_IS_ERR(smbcli_getatr(cli1->tree, fname, NULL, &fsize, NULL))) {
1826                 printf("(8) getatr (1) failed (%s)\n", smbcli_errstr(cli1->tree));
1827                 CHECK_MAX_FAILURES(error_test80);
1828                 return False;
1829         }
1830         
1831         if (fsize != 20) {
1832                 printf("(8) file size != 20\n");
1833                 CHECK_MAX_FAILURES(error_test80);
1834                 return False;
1835         }
1836
1837         /* Get an exclusive lock on the open file. */
1838         if (NT_STATUS_IS_ERR(smbcli_lock(cli1->tree, fnum1, 0, 4, 0, WRITE_LOCK))) {
1839                 printf("(8) lock1 failed (%s)\n", smbcli_errstr(cli1->tree));
1840                 CHECK_MAX_FAILURES(error_test80);
1841                 return False;
1842         }
1843
1844         fnum2 = smbcli_open(cli1->tree, fname, O_RDWR|O_TRUNC, DENY_NONE);
1845         if (fnum1 == -1) {
1846                 printf("(8) open (2) of %s with truncate failed (%s)\n", fname, smbcli_errstr(cli1->tree));
1847                 return False;
1848         }
1849
1850         /* Ensure size == 0. */
1851         if (NT_STATUS_IS_ERR(smbcli_getatr(cli1->tree, fname, NULL, &fsize, NULL))) {
1852                 printf("(8) getatr (2) failed (%s)\n", smbcli_errstr(cli1->tree));
1853                 CHECK_MAX_FAILURES(error_test80);
1854                 return False;
1855         }
1856         
1857         if (fsize != 0) {
1858                 printf("(8) file size != 0\n");
1859                 CHECK_MAX_FAILURES(error_test80);
1860                 return False;
1861         }
1862
1863         if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum1))) {
1864                 printf("(8) close1 failed (%s)\n", smbcli_errstr(cli1->tree));
1865                 return False;
1866         }
1867         
1868         if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum2))) {
1869                 printf("(8) close1 failed (%s)\n", smbcli_errstr(cli1->tree));
1870                 return False;
1871         }
1872         
1873 error_test80:
1874
1875         printf("open test #8 passed.\n");
1876
1877         smbcli_unlink(cli1->tree, fname);
1878
1879         if (!torture_close_connection(cli1)) {
1880                 correct = False;
1881         }
1882         if (!torture_close_connection(cli2)) {
1883                 correct = False;
1884         }
1885         
1886         return correct;
1887 }
1888
1889
1890 /*
1891   sees what IOCTLs are supported
1892  */
1893 BOOL torture_ioctl_test(void)
1894 {
1895         struct smbcli_state *cli;
1896         uint16_t device, function;
1897         int fnum;
1898         const char *fname = "\\ioctl.dat";
1899         NTSTATUS status;
1900         union smb_ioctl parms;
1901         TALLOC_CTX *mem_ctx;
1902
1903         if (!torture_open_connection(&cli)) {
1904                 return False;
1905         }
1906
1907         mem_ctx = talloc_init("ioctl_test");
1908
1909         printf("starting ioctl test\n");
1910
1911         smbcli_unlink(cli->tree, fname);
1912
1913         fnum = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
1914         if (fnum == -1) {
1915                 printf("open of %s failed (%s)\n", fname, smbcli_errstr(cli->tree));
1916                 return False;
1917         }
1918
1919         parms.ioctl.level = RAW_IOCTL_IOCTL;
1920         parms.ioctl.in.fnum = fnum;
1921         parms.ioctl.in.request = IOCTL_QUERY_JOB_INFO;
1922         status = smb_raw_ioctl(cli->tree, mem_ctx, &parms);
1923         printf("ioctl job info: %s\n", smbcli_errstr(cli->tree));
1924
1925         for (device=0;device<0x100;device++) {
1926                 printf("testing device=0x%x\n", device);
1927                 for (function=0;function<0x100;function++) {
1928                         parms.ioctl.in.request = (device << 16) | function;
1929                         status = smb_raw_ioctl(cli->tree, mem_ctx, &parms);
1930
1931                         if (NT_STATUS_IS_OK(status)) {
1932                                 printf("ioctl device=0x%x function=0x%x OK : %d bytes\n", 
1933                                         device, function, (int)parms.ioctl.out.blob.length);
1934                         }
1935                 }
1936         }
1937
1938         if (!torture_close_connection(cli)) {
1939                 return False;
1940         }
1941
1942         return True;
1943 }
1944
1945
1946 /*
1947   tries variants of chkpath
1948  */
1949 BOOL torture_chkpath_test(void)
1950 {
1951         struct smbcli_state *cli;
1952         int fnum;
1953         BOOL ret;
1954
1955         if (!torture_open_connection(&cli)) {
1956                 return False;
1957         }
1958
1959         printf("starting chkpath test\n");
1960
1961         printf("Testing valid and invalid paths\n");
1962
1963         /* cleanup from an old run */
1964         smbcli_rmdir(cli->tree, "\\chkpath.dir\\dir2");
1965         smbcli_unlink(cli->tree, "\\chkpath.dir\\*");
1966         smbcli_rmdir(cli->tree, "\\chkpath.dir");
1967
1968         if (NT_STATUS_IS_ERR(smbcli_mkdir(cli->tree, "\\chkpath.dir"))) {
1969                 printf("mkdir1 failed : %s\n", smbcli_errstr(cli->tree));
1970                 return False;
1971         }
1972
1973         if (NT_STATUS_IS_ERR(smbcli_mkdir(cli->tree, "\\chkpath.dir\\dir2"))) {
1974                 printf("mkdir2 failed : %s\n", smbcli_errstr(cli->tree));
1975                 return False;
1976         }
1977
1978         fnum = smbcli_open(cli->tree, "\\chkpath.dir\\foo.txt", O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
1979         if (fnum == -1) {
1980                 printf("open1 failed (%s)\n", smbcli_errstr(cli->tree));
1981                 return False;
1982         }
1983         smbcli_close(cli->tree, fnum);
1984
1985         if (NT_STATUS_IS_ERR(smbcli_chkpath(cli->tree, "\\chkpath.dir"))) {
1986                 printf("chkpath1 failed: %s\n", smbcli_errstr(cli->tree));
1987                 ret = False;
1988         }
1989
1990         if (NT_STATUS_IS_ERR(smbcli_chkpath(cli->tree, "\\chkpath.dir\\dir2"))) {
1991                 printf("chkpath2 failed: %s\n", smbcli_errstr(cli->tree));
1992                 ret = False;
1993         }
1994
1995         if (NT_STATUS_IS_ERR(smbcli_chkpath(cli->tree, "\\chkpath.dir\\foo.txt"))) {
1996                 ret = check_error(__location__, cli, ERRDOS, ERRbadpath, 
1997                                   NT_STATUS_NOT_A_DIRECTORY);
1998         } else {
1999                 printf("* chkpath on a file should fail\n");
2000                 ret = False;
2001         }
2002
2003         if (NT_STATUS_IS_ERR(smbcli_chkpath(cli->tree, "\\chkpath.dir\\bar.txt"))) {
2004                 ret = check_error(__location__, cli, ERRDOS, ERRbadpath, 
2005                                   NT_STATUS_OBJECT_NAME_NOT_FOUND);
2006         } else {
2007                 printf("* chkpath on a non existent file should fail\n");
2008                 ret = False;
2009         }
2010
2011         if (NT_STATUS_IS_ERR(smbcli_chkpath(cli->tree, "\\chkpath.dir\\dirxx\\bar.txt"))) {
2012                 ret = check_error(__location__, cli, ERRDOS, ERRbadpath, 
2013                                   NT_STATUS_OBJECT_PATH_NOT_FOUND);
2014         } else {
2015                 printf("* chkpath on a non existent component should fail\n");
2016                 ret = False;
2017         }
2018
2019         smbcli_rmdir(cli->tree, "\\chkpath.dir\\dir2");
2020         smbcli_unlink(cli->tree, "\\chkpath.dir\\*");
2021         smbcli_rmdir(cli->tree, "\\chkpath.dir");
2022
2023         if (!torture_close_connection(cli)) {
2024                 return False;
2025         }
2026
2027         return ret;
2028 }
2029
2030
2031 static void sigcont(int sig)
2032 {
2033 }
2034
2035 double torture_create_procs(BOOL (*fn)(struct smbcli_state *, int), BOOL *result)
2036 {
2037         int i, status;
2038         volatile pid_t *child_status;
2039         volatile BOOL *child_status_out;
2040         int synccount;
2041         int tries = 8;
2042         double start_time_limit = 10 + (torture_nprocs * 1.5);
2043         char **unc_list = NULL;
2044         const char *p;
2045         int num_unc_names = 0;
2046         struct timeval tv;
2047
2048         *result = True;
2049
2050         synccount = 0;
2051
2052         signal(SIGCONT, sigcont);
2053
2054         child_status = (volatile pid_t *)shm_setup(sizeof(pid_t)*torture_nprocs);
2055         if (!child_status) {
2056                 printf("Failed to setup shared memory\n");
2057                 return -1;
2058         }
2059
2060         child_status_out = (volatile BOOL *)shm_setup(sizeof(BOOL)*torture_nprocs);
2061         if (!child_status_out) {
2062                 printf("Failed to setup result status shared memory\n");
2063                 return -1;
2064         }
2065
2066         p = lp_parm_string(-1, "torture", "unclist");
2067         if (p) {
2068                 unc_list = file_lines_load(p, &num_unc_names, NULL);
2069                 if (!unc_list || num_unc_names <= 0) {
2070                         printf("Failed to load unc names list from '%s'\n", p);
2071                         exit(1);
2072                 }
2073         }
2074
2075         for (i = 0; i < torture_nprocs; i++) {
2076                 child_status[i] = 0;
2077                 child_status_out[i] = True;
2078         }
2079
2080         tv = timeval_current();
2081
2082         for (i=0;i<torture_nprocs;i++) {
2083                 procnum = i;
2084                 if (fork() == 0) {
2085                         char *myname;
2086                         const char *hostname=NULL, *sharename;
2087
2088                         pid_t mypid = getpid();
2089                         srandom(((int)mypid) ^ ((int)time(NULL)));
2090
2091                         asprintf(&myname, "CLIENT%d", i);
2092                         lp_set_cmdline("netbios name", myname);
2093                         free(myname);
2094
2095
2096                         if (unc_list) {
2097                                 if (!smbcli_parse_unc(unc_list[i % num_unc_names],
2098                                                       NULL, &hostname, &sharename)) {
2099                                         printf("Failed to parse UNC name %s\n",
2100                                                unc_list[i % num_unc_names]);
2101                                         exit(1);
2102                                 }
2103                         }
2104
2105                         while (1) {
2106                                 if (hostname) {
2107                                         if (torture_open_connection_share(NULL,
2108                                                                           &current_cli,
2109                                                                           hostname, 
2110                                                                           sharename,
2111                                                                           NULL)) {
2112                                                 break;
2113                                         }
2114                                 } else if (torture_open_connection(&current_cli)) {
2115                                                 break;
2116                                 }
2117                                 if (tries-- == 0) {
2118                                         printf("pid %d failed to start\n", (int)getpid());
2119                                         _exit(1);
2120                                 }
2121                                 msleep(100);    
2122                         }
2123
2124                         child_status[i] = getpid();
2125
2126                         pause();
2127
2128                         if (child_status[i]) {
2129                                 printf("Child %d failed to start!\n", i);
2130                                 child_status_out[i] = 1;
2131                                 _exit(1);
2132                         }
2133
2134                         child_status_out[i] = fn(current_cli, i);
2135                         _exit(0);
2136                 }
2137         }
2138
2139         do {
2140                 synccount = 0;
2141                 for (i=0;i<torture_nprocs;i++) {
2142                         if (child_status[i]) synccount++;
2143                 }
2144                 if (synccount == torture_nprocs) break;
2145                 msleep(100);
2146         } while (timeval_elapsed(&tv) < start_time_limit);
2147
2148         if (synccount != torture_nprocs) {
2149                 printf("FAILED TO START %d CLIENTS (started %d)\n", torture_nprocs, synccount);
2150                 *result = False;
2151                 return timeval_elapsed(&tv);
2152         }
2153
2154         printf("Starting %d clients\n", torture_nprocs);
2155
2156         /* start the client load */
2157         tv = timeval_current();
2158         for (i=0;i<torture_nprocs;i++) {
2159                 child_status[i] = 0;
2160         }
2161
2162         printf("%d clients started\n", torture_nprocs);
2163
2164         kill(0, SIGCONT);
2165
2166         for (i=0;i<torture_nprocs;i++) {
2167                 int ret;
2168                 while ((ret=waitpid(0, &status, 0)) == -1 && errno == EINTR) /* noop */ ;
2169                 if (ret == -1 || WEXITSTATUS(status) != 0) {
2170                         *result = False;
2171                 }
2172         }
2173
2174         printf("\n");
2175         
2176         for (i=0;i<torture_nprocs;i++) {
2177                 if (!child_status_out[i]) {
2178                         *result = False;
2179                 }
2180         }
2181         return timeval_elapsed(&tv);
2182 }
2183
2184 #define FLAG_MULTIPROC 1
2185
2186 static struct {
2187         const char *name;
2188         BOOL (*fn)(void);
2189         BOOL (*multi_fn)(struct smbcli_state *, int );
2190 } torture_ops[] = {
2191         /* base tests */
2192         {"BASE-FDPASS", run_fdpasstest, 0},
2193         {"BASE-LOCK1",  torture_locktest1,  0},
2194         {"BASE-LOCK2",  torture_locktest2,  0},
2195         {"BASE-LOCK3",  torture_locktest3,  0},
2196         {"BASE-LOCK4",  torture_locktest4,  0},
2197         {"BASE-LOCK5",  torture_locktest5,  0},
2198         {"BASE-LOCK6",  torture_locktest6,  0},
2199         {"BASE-LOCK7",  torture_locktest7,  0},
2200         {"BASE-UNLINK", torture_unlinktest, 0},
2201         {"BASE-ATTR",   run_attrtest,   0},
2202         {"BASE-TRANS2", run_trans2test, 0},
2203         {"BASE-NEGNOWAIT", run_negprot_nowait, 0},
2204         {"BASE-DIR1",  torture_dirtest1, 0},
2205         {"BASE-DIR2",  torture_dirtest2, 0},
2206         {"BASE-DENY1",  torture_denytest1, 0},
2207         {"BASE-DENY2",  torture_denytest2, 0},
2208         {"BASE-DENY3",  torture_denytest3, 0},
2209         {"BASE-DENYDOS",  torture_denydos_sharing, 0},
2210         {"BASE-NTDENY1",  NULL, torture_ntdenytest1},
2211         {"BASE-NTDENY2",  torture_ntdenytest2, 0},
2212         {"BASE-TCON",  run_tcon_test, 0},
2213         {"BASE-TCONDEV",  run_tcon_devtype_test, 0},
2214         {"BASE-VUID", run_vuidtest, 0},
2215         {"BASE-RW1",  run_readwritetest, 0},
2216         {"BASE-OPEN", run_opentest, 0},
2217         {"BASE-DEFER_OPEN", NULL, run_deferopen},
2218         {"BASE-XCOPY", run_xcopy, 0},
2219         {"BASE-RENAME", torture_test_rename, 0},
2220         {"BASE-DELETE", torture_test_delete, 0},
2221         {"BASE-PROPERTIES", torture_test_properties, 0},
2222         {"BASE-MANGLE", torture_mangle, 0},
2223         {"BASE-OPENATTR", torture_openattrtest, 0},
2224         {"BASE-CHARSET", torture_charset, 0},
2225         {"BASE-CHKPATH",  torture_chkpath_test, 0},
2226         {"BASE-SECLEAK",  torture_sec_leak, 0},
2227         {"BASE-DISCONNECT",  torture_disconnect, 0},
2228         {"BASE-DELAYWRITE", torture_delay_write, 0},
2229
2230         /* benchmarking tests */
2231         {"BENCH-HOLDCON",  torture_holdcon, 0},
2232         {"BENCH-NBENCH",  torture_nbench, 0},
2233         {"BENCH-TORTURE", NULL, run_torture},
2234         {"BENCH-NBT",     torture_bench_nbt, 0},
2235         {"BENCH-WINS",    torture_bench_wins, 0},
2236         {"BENCH-RPC",     torture_bench_rpc, 0},
2237         {"BENCH-CLDAP",   torture_bench_cldap, 0},
2238
2239         /* RAW smb tests */
2240         {"RAW-QFSINFO", torture_raw_qfsinfo, 0},
2241         {"RAW-QFILEINFO", torture_raw_qfileinfo, 0},
2242         {"RAW-SFILEINFO", torture_raw_sfileinfo, 0},
2243         {"RAW-SFILEINFO-BUG", torture_raw_sfileinfo_bug, 0},
2244         {"RAW-SEARCH", torture_raw_search, 0},
2245         {"RAW-CLOSE", torture_raw_close, 0},
2246         {"RAW-OPEN", torture_raw_open, 0},
2247         {"RAW-MKDIR", torture_raw_mkdir, 0},
2248         {"RAW-OPLOCK", torture_raw_oplock, 0},
2249         {"RAW-NOTIFY", torture_raw_notify, 0},
2250         {"RAW-MUX", torture_raw_mux, 0},
2251         {"RAW-IOCTL", torture_raw_ioctl, 0},
2252         {"RAW-CHKPATH", torture_raw_chkpath, 0},
2253         {"RAW-UNLINK", torture_raw_unlink, 0},
2254         {"RAW-READ", torture_raw_read, 0},
2255         {"RAW-WRITE", torture_raw_write, 0},
2256         {"RAW-LOCK", torture_raw_lock, 0},
2257         {"RAW-CONTEXT", torture_raw_context, 0},
2258         {"RAW-RENAME", torture_raw_rename, 0},
2259         {"RAW-SEEK", torture_raw_seek, 0},
2260         {"RAW-EAS", torture_raw_eas, 0},
2261         {"RAW-EAMAX", torture_max_eas, 0},
2262         {"RAW-STREAMS", torture_raw_streams, 0},
2263         {"RAW-ACLS", torture_raw_acls, 0},
2264         {"RAW-RAP", torture_raw_rap, 0},
2265         {"RAW-COMPOSITE", torture_raw_composite, 0},
2266
2267         /* SMB2 tests */
2268         {"SMB2-CONNECT", torture_smb2_connect, 0},
2269         {"SMB2-SCAN", torture_smb2_scan, 0},
2270         {"SMB2-SCANGETINFO", torture_smb2_getinfo_scan, 0},
2271         {"SMB2-SCANSETINFO", torture_smb2_setinfo_scan, 0},
2272         {"SMB2-SCANFIND", torture_smb2_find_scan, 0},
2273         {"SMB2-GETINFO", torture_smb2_getinfo, 0},
2274         {"SMB2-SETINFO", torture_smb2_setinfo, 0},
2275         {"SMB2-FIND", torture_smb2_find, 0},
2276
2277         /* protocol scanners */
2278         {"SCAN-TRANS2", torture_trans2_scan, 0},
2279         {"SCAN-NTTRANS", torture_nttrans_scan, 0},
2280         {"SCAN-ALIASES", torture_trans2_aliases, 0},
2281         {"SCAN-SMB", torture_smb_scan, 0},
2282         {"SCAN-MAXFID", NULL, run_maxfidtest},
2283         {"SCAN-UTABLE", torture_utable, 0},
2284         {"SCAN-CASETABLE", torture_casetable, 0},
2285         {"SCAN-PIPE_NUMBER", run_pipe_number, 0},
2286         {"SCAN-IOCTL",  torture_ioctl_test, 0},
2287         {"SCAN-RAP",  torture_rap_scan, 0},
2288
2289         /* rpc testers */
2290         {"RPC-LSA", torture_rpc_lsa, 0},
2291         {"RPC-LSALOOKUP", torture_rpc_lsa_lookup, 0},
2292         {"RPC-SECRETS", torture_rpc_lsa_secrets, 0},
2293         {"RPC-ECHO", torture_rpc_echo, 0},
2294         {"RPC-DFS", torture_rpc_dfs, 0},
2295         {"RPC-SPOOLSS", torture_rpc_spoolss, 0},
2296         {"RPC-SAMR", torture_rpc_samr, 0},
2297         {"RPC-UNIXINFO", torture_rpc_unixinfo, 0},
2298         {"RPC-NETLOGON", torture_rpc_netlogon, 0},
2299         {"RPC-SAMLOGON", torture_rpc_samlogon, 0},
2300         {"RPC-SAMSYNC", torture_rpc_samsync, 0},
2301         {"RPC-SCHANNEL", torture_rpc_schannel, 0},
2302         {"RPC-WKSSVC", torture_rpc_wkssvc, 0},
2303         {"RPC-SRVSVC", torture_rpc_srvsvc, 0},
2304         {"RPC-SVCCTL", torture_rpc_svcctl, 0},
2305         {"RPC-ATSVC", torture_rpc_atsvc, 0},
2306         {"RPC-EVENTLOG", torture_rpc_eventlog, 0},
2307         {"RPC-EPMAPPER", torture_rpc_epmapper, 0},
2308         {"RPC-WINREG", torture_rpc_winreg, 0},
2309         {"RPC-INITSHUTDOWN", torture_rpc_initshutdown, 0},
2310         {"RPC-OXIDRESOLVE", torture_rpc_oxidresolve, 0},
2311         {"RPC-REMACT", torture_rpc_remact, 0},
2312         {"RPC-MGMT", torture_rpc_mgmt, 0},
2313         {"RPC-SCANNER", torture_rpc_scanner, 0},
2314         {"RPC-AUTOIDL", torture_rpc_autoidl, 0},
2315         {"RPC-COUNTCALLS", torture_rpc_countcalls, 0},
2316         {"RPC-MULTIBIND", torture_multi_bind, 0},
2317         {"RPC-DRSUAPI", torture_rpc_drsuapi, 0},
2318         {"RPC-CRACKNAMES", torture_rpc_drsuapi_cracknames, 0},
2319         {"RPC-ROT", torture_rpc_rot, 0},
2320         {"RPC-DSSETUP", torture_rpc_dssetup, 0},
2321         {"RPC-ALTERCONTEXT", torture_rpc_alter_context, 0},
2322         {"RPC-JOIN", torture_rpc_join, 0},
2323         {"RPC-DSSYNC", torture_rpc_dssync, 0},
2324
2325         /* local (no server) testers */
2326         {"LOCAL-NTLMSSP", torture_ntlmssp_self_check, 0},
2327         {"LOCAL-ICONV", torture_local_iconv, 0},
2328         {"LOCAL-TALLOC", torture_local_talloc, 0},
2329         {"LOCAL-MESSAGING", torture_local_messaging, 0},
2330         {"LOCAL-IRPC",  torture_local_irpc, 0},
2331         {"LOCAL-BINDING", torture_local_binding_string, 0},
2332         {"LOCAL-STRLIST", torture_local_util_strlist, 0},
2333         {"LOCAL-FILE", torture_local_util_file, 0},
2334         {"LOCAL-IDTREE", torture_local_idtree, 0},
2335         {"LOCAL-SOCKET", torture_local_socket, 0},
2336         {"LOCAL-PAC", torture_pac, 0},
2337         {"LOCAL-REGISTRY", torture_registry, 0},
2338         {"LOCAL-RESOLVE", torture_local_resolve, 0},
2339         {"LOCAL-SDDL", torture_local_sddl, 0},
2340         {"LOCAL-NDR", torture_local_ndr, 0},
2341
2342         /* COM (Component Object Model) testers */
2343         {"COM-SIMPLE", torture_com_simple, 0 },
2344
2345         /* ldap testers */
2346         {"LDAP-BASIC", torture_ldap_basic, 0},
2347         {"LDAP-CLDAP", torture_cldap, 0},
2348
2349         /* nbt tests */
2350         {"NBT-REGISTER", torture_nbt_register, 0},
2351         {"NBT-WINS", torture_nbt_wins, 0},
2352         {"NBT-DGRAM", torture_nbt_dgram, 0},
2353         {"NBT-BROWSE", torture_nbt_browse, 0},
2354         {"NBT-WINSREPLICATION-SIMPLE", torture_nbt_winsreplication_simple, 0},
2355         {"NBT-WINSREPLICATION-REPLICA", torture_nbt_winsreplication_replica, 0},
2356         {"NBT-WINSREPLICATION-OWNED", torture_nbt_winsreplication_owned, 0},
2357         
2358         /* libnet tests */
2359         {"NET-USERINFO", torture_userinfo, 0},
2360         {"NET-USERADD", torture_useradd, 0},
2361         {"NET-USERDEL", torture_userdel, 0},
2362         {"NET-USERMOD", torture_usermod, 0},
2363         {"NET-DOMOPEN", torture_domainopen, 0},
2364         {"NET-API-LOOKUP", torture_lookup, 0},
2365         {"NET-API-LOOKUPHOST", torture_lookup_host, 0},
2366         {"NET-API-LOOKUPPDC", torture_lookup_pdc, 0},
2367         {"NET-API-CREATEUSER", torture_createuser, 0},
2368         {"NET-API-RPCCONNECT", torture_rpc_connect, 0},
2369         {"NET-API-LISTSHARES", torture_listshares, 0},
2370         {"NET-API-DELSHARE", torture_delshare, 0},
2371
2372         {NULL, NULL, 0}};
2373
2374
2375
2376 /****************************************************************************
2377 run a specified test or "ALL"
2378 ****************************************************************************/
2379 static BOOL run_test(const char *name)
2380 {
2381         BOOL ret = True;
2382         int i;
2383         BOOL matched = False;
2384
2385         if (strequal(name,"ALL")) {
2386                 for (i=0;torture_ops[i].name;i++) {
2387                         if (!run_test(torture_ops[i].name)) {
2388                                 ret = False;
2389                         }
2390                 }
2391                 return ret;
2392         }
2393
2394         for (i=0;torture_ops[i].name;i++) {
2395                 if (gen_fnmatch(name, torture_ops[i].name) == 0) {
2396                         double t;
2397                         matched = True;
2398                         init_iconv();
2399                         printf("Running %s\n", torture_ops[i].name);
2400                         if (torture_ops[i].multi_fn) {
2401                                 BOOL result = False;
2402                                 t = torture_create_procs(torture_ops[i].multi_fn, 
2403                                                          &result);
2404                                 if (!result) { 
2405                                         ret = False;
2406                                         printf("TEST %s FAILED!\n", torture_ops[i].name);
2407                                 }
2408                                          
2409                         } else {
2410                                 struct timeval tv = timeval_current();
2411                                 if (!torture_ops[i].fn()) {
2412                                         ret = False;
2413                                         printf("TEST %s FAILED!\n", torture_ops[i].name);
2414                                 }
2415                                 t = timeval_elapsed(&tv);
2416                         }
2417                         printf("%s took %g secs\n\n", torture_ops[i].name, t);
2418                 }
2419         }
2420
2421         if (!matched) {
2422                 printf("Unknown torture operation '%s'\n", name);
2423         }
2424
2425         return ret;
2426 }
2427
2428
2429 static void parse_dns(const char *dns)
2430 {
2431         char *userdn, *basedn, *secret;
2432         char *p, *d;
2433
2434         /* retrievieng the userdn */
2435         p = strchr_m(dns, '#');
2436         if (!p) {
2437                 lp_set_cmdline("torture:ldap_userdn", "");
2438                 lp_set_cmdline("torture:ldap_basedn", "");
2439                 lp_set_cmdline("torture:ldap_secret", "");
2440                 return;
2441         }
2442         userdn = strndup(dns, p - dns);
2443         lp_set_cmdline("torture:ldap_userdn", userdn);
2444
2445         /* retrieve the basedn */
2446         d = p + 1;
2447         p = strchr_m(d, '#');
2448         if (!p) {
2449                 lp_set_cmdline("torture:ldap_basedn", "");
2450                 lp_set_cmdline("torture:ldap_secret", "");
2451                 return;
2452         }
2453         basedn = strndup(d, p - d);
2454         lp_set_cmdline("torture:ldap_basedn", basedn);
2455
2456         /* retrieve the secret */
2457         p = p + 1;
2458         if (!p) {
2459                 lp_set_cmdline("torture:ldap_secret", "");
2460                 return;
2461         }
2462         secret = strdup(p);
2463         lp_set_cmdline("torture:ldap_secret", secret);
2464
2465         printf ("%s - %s - %s\n", userdn, basedn, secret);
2466
2467 }
2468
2469 static void usage(poptContext pc)
2470 {
2471         int i;
2472         int perline = 5;
2473
2474         poptPrintUsage(pc, stdout, 0);
2475         printf("\n");
2476
2477         printf("The binding format is:\n\n");
2478
2479         printf("  TRANSPORT:host[flags]\n\n");
2480
2481         printf("  where TRANSPORT is either ncacn_np for SMB or ncacn_ip_tcp for RPC/TCP\n\n");
2482
2483         printf("  'host' is an IP or hostname or netbios name. If the binding string\n");
2484         printf("  identifies the server side of an endpoint, 'host' may be an empty\n");
2485         printf("  string.\n\n");
2486
2487         printf("  'flags' can include a SMB pipe name if using the ncacn_np transport or\n");
2488         printf("  a TCP port number if using the ncacn_ip_tcp transport, otherwise they\n");
2489         printf("  will be auto-determined.\n\n");
2490
2491         printf("  other recognised flags are:\n\n");
2492
2493         printf("    sign : enable ntlmssp signing\n");
2494         printf("    seal : enable ntlmssp sealing\n");
2495         printf("    connect : enable rpc connect level auth (auth, but no sign or seal)\n");
2496         printf("    validate: enable the NDR validator\n");
2497         printf("    print: enable debugging of the packets\n");
2498         printf("    bigendian: use bigendian RPC\n");
2499         printf("    padcheck: check reply data for non-zero pad bytes\n\n");
2500
2501         printf("  For example, these all connect to the samr pipe:\n\n");
2502
2503         printf("    ncacn_np:myserver\n");
2504         printf("    ncacn_np:myserver[samr]\n");
2505         printf("    ncacn_np:myserver[\\pipe\\samr]\n");
2506         printf("    ncacn_np:myserver[/pipe/samr]\n");
2507         printf("    ncacn_np:myserver[samr,sign,print]\n");
2508         printf("    ncacn_np:myserver[\\pipe\\samr,sign,seal,bigendian]\n");
2509         printf("    ncacn_np:myserver[/pipe/samr,seal,validate]\n");
2510         printf("    ncacn_np:\n");
2511         printf("    ncacn_np:[/pipe/samr]\n\n");
2512
2513         printf("    ncacn_ip_tcp:myserver\n");
2514         printf("    ncacn_ip_tcp:myserver[1024]\n");
2515         printf("    ncacn_ip_tcp:myserver[1024,sign,seal]\n\n");
2516
2517         printf("The unc format is:\n\n");
2518
2519         printf("    //server/share\n\n");
2520
2521         printf("tests are:");
2522         for (i=0;torture_ops[i].name;i++) {
2523                 if ((i%perline)==0) {
2524                         printf("\n");
2525                 }
2526                 printf("%s ", torture_ops[i].name);
2527         }
2528         printf("\n\n");
2529
2530         printf("default test is ALL\n");
2531
2532         exit(1);
2533 }
2534
2535 static BOOL is_binding_string(const char *binding_string)
2536 {
2537         TALLOC_CTX *mem_ctx = talloc_init("is_binding_string");
2538         struct dcerpc_binding *binding_struct;
2539         NTSTATUS status;
2540         
2541         status = dcerpc_parse_binding(mem_ctx, binding_string, &binding_struct);
2542
2543         talloc_free(mem_ctx);
2544         return NT_STATUS_IS_OK(status);
2545 }
2546
2547 static void max_runtime_handler(int sig)
2548 {
2549         DEBUG(0,("maximum runtime exceeded for smbtorture - terminating\n"));
2550         exit(1);
2551 }
2552
2553 /****************************************************************************
2554   main program
2555 ****************************************************************************/
2556  int main(int argc,char *argv[])
2557 {
2558         int opt, i;
2559         char *p;
2560         BOOL correct = True;
2561         int max_runtime=0;
2562         int argc_new;
2563         char **argv_new;
2564         poptContext pc;
2565         enum {OPT_LOADFILE=1000,OPT_UNCLIST,OPT_TIMELIMIT,OPT_DNS,
2566             OPT_DANGEROUS,OPT_SMB_PORTS};
2567
2568         struct poptOption long_options[] = {
2569                 POPT_AUTOHELP
2570                 {"smb-ports",   'p', POPT_ARG_STRING, NULL,     OPT_SMB_PORTS,  "SMB ports",    NULL},
2571                 {"seed",          0, POPT_ARG_INT,  &torture_seed,      0,      "seed",         NULL},
2572                 {"num-progs",     0, POPT_ARG_INT,  &torture_nprocs,    0,      "num progs",    NULL},
2573                 {"num-ops",       0, POPT_ARG_INT,  &torture_numops,    0,      "num ops",      NULL},
2574                 {"entries",       0, POPT_ARG_INT,  &torture_entries,   0,      "entries",      NULL},
2575                 {"use-oplocks", 'L', POPT_ARG_NONE, &use_oplocks,       0,      "use oplocks",  NULL},
2576                 {"show-all",      0, POPT_ARG_NONE, &torture_showall,   0,      "show all",     NULL},
2577                 {"loadfile",      0, POPT_ARG_STRING,   NULL,   OPT_LOADFILE,   "loadfile",     NULL},
2578                 {"unclist",       0, POPT_ARG_STRING,   NULL,   OPT_UNCLIST,    "unclist",      NULL},
2579                 {"timelimit",   't', POPT_ARG_STRING,   NULL,   OPT_TIMELIMIT,  "timelimit",    NULL},
2580                 {"failures",    'f', POPT_ARG_INT,  &torture_failures,  0,      "failures",     NULL},
2581                 {"parse-dns",   'D', POPT_ARG_STRING,   NULL,   OPT_DNS,        "parse-dns",    NULL},
2582                 {"dangerous",   'X', POPT_ARG_NONE,     NULL,   OPT_DANGEROUS,  "dangerous",    NULL},
2583                 {"maximum-runtime", 0, POPT_ARG_INT, &max_runtime, 0, 
2584                  "set maximum time for smbtorture to live", "seconds"},
2585                 POPT_COMMON_SAMBA
2586                 POPT_COMMON_CONNECTION
2587                 POPT_COMMON_CREDENTIALS
2588                 POPT_COMMON_VERSION
2589                 POPT_TABLEEND
2590         };
2591
2592 #ifdef HAVE_SETBUFFER
2593         setbuffer(stdout, NULL, 0);
2594 #endif
2595
2596         pc = poptGetContext("smbtorture", argc, (const char **) argv, long_options, 
2597                             POPT_CONTEXT_KEEP_FIRST);
2598
2599         poptSetOtherOptionHelp(pc, "<binding>|<unc> TEST1 TEST2 ...");
2600
2601         while((opt = poptGetNextOpt(pc)) != -1) {
2602                 switch (opt) {
2603                 case OPT_LOADFILE:
2604                         lp_set_cmdline("torture:loadfile", poptGetOptArg(pc));
2605                         break;
2606                 case OPT_UNCLIST:
2607                         lp_set_cmdline("torture:unclist", poptGetOptArg(pc));
2608                         break;
2609                 case OPT_TIMELIMIT:
2610                         lp_set_cmdline("torture:timelimit", poptGetOptArg(pc));
2611                         break;
2612                 case OPT_DNS:
2613                         parse_dns(poptGetOptArg(pc));
2614                         break;
2615                 case OPT_DANGEROUS:
2616                         lp_set_cmdline("torture:dangerous", "Yes");
2617                         break;
2618                 case OPT_SMB_PORTS:
2619                         lp_set_cmdline("smb ports", poptGetOptArg(pc));
2620                         break;
2621                 default:
2622                         d_printf("Invalid option %s: %s\n", 
2623                                  poptBadOption(pc, 0), poptStrerror(opt));
2624                         usage(pc);
2625                         exit(1);
2626                 }
2627         }
2628
2629         if (max_runtime) {
2630                 /* this will only work if nobody else uses alarm(),
2631                    which means it won't work for some tests, but we
2632                    can't use the event context method we use for smbd
2633                    as so many tests create their own event
2634                    context. This will at least catch most cases. */
2635                 signal(SIGALRM, max_runtime_handler);
2636                 alarm(max_runtime);
2637         }
2638
2639         ldb_global_init();
2640
2641         dcerpc_init();
2642
2643         dcerpc_table_init();
2644
2645         if (torture_seed == 0) {
2646                 torture_seed = time(NULL);
2647         } 
2648         printf("Using seed %d\n", torture_seed);
2649         srandom(torture_seed);
2650
2651         argv_new = discard_const_p(char *, poptGetArgs(pc));
2652
2653         argc_new = argc;
2654         for (i=0; i<argc; i++) {
2655                 if (argv_new[i] == NULL) {
2656                         argc_new = i;
2657                         break;
2658                 }
2659         }
2660
2661         if (argc_new < 3) {
2662                 usage(pc);
2663                 exit(1);
2664         }
2665
2666         for(p = argv_new[1]; *p; p++) {
2667                 if(*p == '\\')
2668                         *p = '/';
2669         }
2670
2671         /* see if its a RPC transport specifier */
2672         if (is_binding_string(argv_new[1])) {
2673                 lp_set_cmdline("torture:binding", argv_new[1]);
2674         } else {
2675                 char *binding = NULL;
2676                 const char *host = NULL, *share = NULL;
2677
2678                 if (!smbcli_parse_unc(argv_new[1], NULL, &host, &share)) {
2679                         d_printf("Invalid option: %s is not a valid torture target (share or binding string)\n\n", argv_new[1]);
2680                         usage(pc);
2681                 }
2682
2683                 lp_set_cmdline("torture:host", host);
2684                 lp_set_cmdline("torture:share", share);
2685                 asprintf(&binding, "ncacn_np:%s", host);
2686                 lp_set_cmdline("torture:binding", binding);
2687         }
2688
2689         if (argc_new == 0) {
2690                 printf("You must specify a test to run, or 'ALL'\n");
2691         } else {
2692                 for (i=2;i<argc_new;i++) {
2693                         if (!run_test(argv_new[i])) {
2694                                 correct = False;
2695                         }
2696                 }
2697         }
2698
2699         if (correct) {
2700                 return(0);
2701         } else {
2702                 return(1);
2703         }
2704 }