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