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