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