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