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