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