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