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