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