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