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