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