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