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