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