bc4b58be739214aa8aeb79504d8cc92e59478719
[nivanova/samba-autobuild/.git] / source3 / torture / torture.c
1 /* 
2    Unix SMB/CIFS implementation.
3    SMB torture tester
4    Copyright (C) Andrew Tridgell 1997-1998
5    Copyright (C) Jeremy Allison 2009
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 3 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, see <http://www.gnu.org/licenses/>.
19 */
20
21 #include "includes.h"
22 #include "nsswitch/libwbclient/wbc_async.h"
23 #include "torture/proto.h"
24 #include "libcli/security/security.h"
25 #include "tldap.h"
26 #include "tldap_util.h"
27 #include "../librpc/gen_ndr/svcctl.h"
28 #include "memcache.h"
29 #include "nsswitch/winbind_client.h"
30 #include "dbwrap.h"
31 #include "talloc_dict.h"
32 #include "async_smb.h"
33
34 extern char *optarg;
35 extern int optind;
36
37 static fstring host, workgroup, share, password, username, myname;
38 static int max_protocol = PROTOCOL_NT1;
39 static const char *sockops="TCP_NODELAY";
40 static int nprocs=1;
41 static int port_to_use=0;
42 int torture_numops=100;
43 int torture_blocksize=1024*1024;
44 static int procnum; /* records process count number when forking */
45 static struct cli_state *current_cli;
46 static fstring randomfname;
47 static bool use_oplocks;
48 static bool use_level_II_oplocks;
49 static const char *client_txt = "client_oplocks.txt";
50 static bool use_kerberos;
51 static fstring multishare_conn_fname;
52 static bool use_multishare_conn = False;
53 static bool do_encrypt;
54 static const char *local_path = NULL;
55
56 bool torture_showall = False;
57
58 static double create_procs(bool (*fn)(int), bool *result);
59
60
61 /* return a pointer to a anonymous shared memory segment of size "size"
62    which will persist across fork() but will disappear when all processes
63    exit 
64
65    The memory is not zeroed 
66
67    This function uses system5 shared memory. It takes advantage of a property
68    that the memory is not destroyed if it is attached when the id is removed
69    */
70 void *shm_setup(int size)
71 {
72         int shmid;
73         void *ret;
74
75 #ifdef __QNXNTO__
76         shmid = shm_open("private", O_RDWR | O_CREAT | O_EXCL, S_IRUSR | S_IWUSR);
77         if (shmid == -1) {
78                 printf("can't get shared memory\n");
79                 exit(1);
80         }
81         shm_unlink("private");
82         if (ftruncate(shmid, size) == -1) {
83                 printf("can't set shared memory size\n");
84                 exit(1);
85         }
86         ret = mmap(0, size, PROT_READ | PROT_WRITE, MAP_SHARED, shmid, 0);
87         if (ret == MAP_FAILED) {
88                 printf("can't map shared memory\n");
89                 exit(1);
90         }
91 #else
92         shmid = shmget(IPC_PRIVATE, size, S_IRUSR | S_IWUSR);
93         if (shmid == -1) {
94                 printf("can't get shared memory\n");
95                 exit(1);
96         }
97         ret = (void *)shmat(shmid, 0, 0);
98         if (!ret || ret == (void *)-1) {
99                 printf("can't attach to shared memory\n");
100                 return NULL;
101         }
102         /* the following releases the ipc, but note that this process
103            and all its children will still have access to the memory, its
104            just that the shmid is no longer valid for other shm calls. This
105            means we don't leave behind lots of shm segments after we exit 
106
107            See Stevens "advanced programming in unix env" for details
108            */
109         shmctl(shmid, IPC_RMID, 0);
110 #endif
111
112         return ret;
113 }
114
115 /********************************************************************
116  Ensure a connection is encrypted.
117 ********************************************************************/
118
119 static bool force_cli_encryption(struct cli_state *c,
120                         const char *sharename)
121 {
122         uint16 major, minor;
123         uint32 caplow, caphigh;
124         NTSTATUS status;
125
126         if (!SERVER_HAS_UNIX_CIFS(c)) {
127                 d_printf("Encryption required and "
128                         "server that doesn't support "
129                         "UNIX extensions - failing connect\n");
130                         return false;
131         }
132
133         status = cli_unix_extensions_version(c, &major, &minor, &caplow,
134                                              &caphigh);
135         if (!NT_STATUS_IS_OK(status)) {
136                 d_printf("Encryption required and "
137                         "can't get UNIX CIFS extensions "
138                         "version from server: %s\n", nt_errstr(status));
139                 return false;
140         }
141
142         if (!(caplow & CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP)) {
143                 d_printf("Encryption required and "
144                         "share %s doesn't support "
145                         "encryption.\n", sharename);
146                 return false;
147         }
148
149         if (c->use_kerberos) {
150                 status = cli_gss_smb_encryption_start(c);
151         } else {
152                 status = cli_raw_ntlm_smb_encryption_start(c,
153                                                 username,
154                                                 password,
155                                                 workgroup);
156         }
157
158         if (!NT_STATUS_IS_OK(status)) {
159                 d_printf("Encryption required and "
160                         "setup failed with error %s.\n",
161                         nt_errstr(status));
162                 return false;
163         }
164
165         return true;
166 }
167
168
169 static struct cli_state *open_nbt_connection(void)
170 {
171         struct nmb_name called, calling;
172         struct sockaddr_storage ss;
173         struct cli_state *c;
174         NTSTATUS status;
175
176         make_nmb_name(&calling, myname, 0x0);
177         make_nmb_name(&called , host, 0x20);
178
179         zero_sockaddr(&ss);
180
181         if (!(c = cli_initialise())) {
182                 printf("Failed initialize cli_struct to connect with %s\n", host);
183                 return NULL;
184         }
185
186         c->port = port_to_use;
187
188         status = cli_connect(c, host, &ss);
189         if (!NT_STATUS_IS_OK(status)) {
190                 printf("Failed to connect with %s. Error %s\n", host, nt_errstr(status) );
191                 return NULL;
192         }
193
194         c->use_kerberos = use_kerberos;
195
196         c->timeout = 120000; /* set a really long timeout (2 minutes) */
197         if (use_oplocks) c->use_oplocks = True;
198         if (use_level_II_oplocks) c->use_level_II_oplocks = True;
199
200         if (!cli_session_request(c, &calling, &called)) {
201                 /*
202                  * Well, that failed, try *SMBSERVER ...
203                  * However, we must reconnect as well ...
204                  */
205                 status = cli_connect(c, host, &ss);
206                 if (!NT_STATUS_IS_OK(status)) {
207                         printf("Failed to connect with %s. Error %s\n", host, nt_errstr(status) );
208                         return NULL;
209                 }
210
211                 make_nmb_name(&called, "*SMBSERVER", 0x20);
212                 if (!cli_session_request(c, &calling, &called)) {
213                         printf("%s rejected the session\n",host);
214                         printf("We tried with a called name of %s & %s\n",
215                                 host, "*SMBSERVER");
216                         cli_shutdown(c);
217                         return NULL;
218                 }
219         }
220
221         return c;
222 }
223
224 /****************************************************************************
225  Send a corrupt session request. See rfc1002.txt 4.3 and 4.3.2.
226 ****************************************************************************/
227
228 static bool cli_bad_session_request(struct cli_state *cli,
229                          struct nmb_name *calling, struct nmb_name *called)
230 {
231         char *p;
232         int len = 4;
233         int namelen = 0;
234         char *tmp;
235
236         memcpy(&(cli->calling), calling, sizeof(*calling));
237         memcpy(&(cli->called ), called , sizeof(*called ));
238
239         /* put in the destination name */
240
241         tmp = name_mangle(talloc_tos(), cli->called.name,
242                           cli->called.name_type);
243         if (tmp == NULL) {
244                 return false;
245         }
246
247         p = cli->outbuf+len;
248         namelen = name_len((unsigned char *)tmp, talloc_get_size(tmp));
249         if (namelen > 0) {
250                 memcpy(p, tmp, namelen);
251                 len += namelen;
252         }
253         TALLOC_FREE(tmp);
254
255         /* Deliberately corrupt the name len (first byte) */
256         *p = 100;
257
258         /* and my name */
259
260         tmp = name_mangle(talloc_tos(), cli->calling.name,
261                           cli->calling.name_type);
262         if (tmp == NULL) {
263                 return false;
264         }
265
266         p = cli->outbuf+len;
267         namelen = name_len((unsigned char *)tmp, talloc_get_size(tmp));
268         if (namelen > 0) {
269                 memcpy(p, tmp, namelen);
270                 len += namelen;
271         }
272         TALLOC_FREE(tmp);
273         /* Deliberately corrupt the name len (first byte) */
274         *p = 100;
275
276         /* send a session request (RFC 1002) */
277         /* setup the packet length
278          * Remove four bytes from the length count, since the length
279          * field in the NBT Session Service header counts the number
280          * of bytes which follow.  The cli_send_smb() function knows
281          * about this and accounts for those four bytes.
282          * CRH.
283          */
284         len -= 4;
285         _smb_setlen(cli->outbuf,len);
286         SCVAL(cli->outbuf,0,0x81);
287
288         cli_send_smb(cli);
289         DEBUG(5,("Sent session request\n"));
290
291         if (!cli_receive_smb(cli))
292                 return False;
293
294         if (CVAL(cli->inbuf,0) != 0x82) {
295                 /* This is the wrong place to put the error... JRA. */
296                 cli->rap_error = CVAL(cli->inbuf,4);
297                 return False;
298         }
299         return(True);
300 }
301
302 static struct cli_state *open_bad_nbt_connection(void)
303 {
304         struct nmb_name called, calling;
305         struct sockaddr_storage ss;
306         struct cli_state *c;
307         NTSTATUS status;
308
309         make_nmb_name(&calling, myname, 0x0);
310         make_nmb_name(&called , host, 0x20);
311
312         zero_sockaddr(&ss);
313
314         if (!(c = cli_initialise())) {
315                 printf("Failed initialize cli_struct to connect with %s\n", host);
316                 return NULL;
317         }
318
319         c->port = 139;
320
321         status = cli_connect(c, host, &ss);
322         if (!NT_STATUS_IS_OK(status)) {
323                 printf("Failed to connect with %s. Error %s\n", host, nt_errstr(status) );
324                 return NULL;
325         }
326
327         c->timeout = 4000; /* set a short timeout (4 seconds) */
328
329         if (!cli_bad_session_request(c, &calling, &called)) {
330                 printf("Failed to connect with %s. Error %s\n", host, nt_errstr(status) );
331                 return NULL;
332         }
333
334         return c;
335 }
336
337
338 /* Insert a NULL at the first separator of the given path and return a pointer
339  * to the remainder of the string.
340  */
341 static char *
342 terminate_path_at_separator(char * path)
343 {
344         char * p;
345
346         if (!path) {
347                 return NULL;
348         }
349
350         if ((p = strchr_m(path, '/'))) {
351                 *p = '\0';
352                 return p + 1;
353         }
354
355         if ((p = strchr_m(path, '\\'))) {
356                 *p = '\0';
357                 return p + 1;
358         }
359
360         /* No separator. */
361         return NULL;
362 }
363
364 /*
365   parse a //server/share type UNC name
366 */
367 bool smbcli_parse_unc(const char *unc_name, TALLOC_CTX *mem_ctx,
368                       char **hostname, char **sharename)
369 {
370         char *p;
371
372         *hostname = *sharename = NULL;
373
374         if (strncmp(unc_name, "\\\\", 2) &&
375             strncmp(unc_name, "//", 2)) {
376                 return False;
377         }
378
379         *hostname = talloc_strdup(mem_ctx, &unc_name[2]);
380         p = terminate_path_at_separator(*hostname);
381
382         if (p && *p) {
383                 *sharename = talloc_strdup(mem_ctx, p);
384                 terminate_path_at_separator(*sharename);
385         }
386
387         if (*hostname && *sharename) {
388                 return True;
389         }
390
391         TALLOC_FREE(*hostname);
392         TALLOC_FREE(*sharename);
393         return False;
394 }
395
396 static bool torture_open_connection_share(struct cli_state **c,
397                                    const char *hostname, 
398                                    const char *sharename)
399 {
400         bool retry;
401         int flags = 0;
402         NTSTATUS status;
403
404         if (use_kerberos)
405                 flags |= CLI_FULL_CONNECTION_USE_KERBEROS;
406         if (use_oplocks)
407                 flags |= CLI_FULL_CONNECTION_OPLOCKS;
408         if (use_level_II_oplocks)
409                 flags |= CLI_FULL_CONNECTION_LEVEL_II_OPLOCKS;
410
411         status = cli_full_connection(c, myname,
412                                      hostname, NULL, port_to_use, 
413                                      sharename, "?????", 
414                                      username, workgroup, 
415                                      password, flags, Undefined, &retry);
416         if (!NT_STATUS_IS_OK(status)) {
417                 printf("failed to open share connection: //%s/%s port:%d - %s\n",
418                         hostname, sharename, port_to_use, nt_errstr(status));
419                 return False;
420         }
421
422         (*c)->timeout = 120000; /* set a really long timeout (2 minutes) */
423
424         if (do_encrypt) {
425                 return force_cli_encryption(*c,
426                                         sharename);
427         }
428         return True;
429 }
430
431 bool torture_open_connection(struct cli_state **c, int conn_index)
432 {
433         char **unc_list = NULL;
434         int num_unc_names = 0;
435         bool result;
436
437         if (use_multishare_conn==True) {
438                 char *h, *s;
439                 unc_list = file_lines_load(multishare_conn_fname, &num_unc_names, 0, NULL);
440                 if (!unc_list || num_unc_names <= 0) {
441                         printf("Failed to load unc names list from '%s'\n", multishare_conn_fname);
442                         exit(1);
443                 }
444
445                 if (!smbcli_parse_unc(unc_list[conn_index % num_unc_names],
446                                       NULL, &h, &s)) {
447                         printf("Failed to parse UNC name %s\n",
448                                unc_list[conn_index % num_unc_names]);
449                         TALLOC_FREE(unc_list);
450                         exit(1);
451                 }
452
453                 result = torture_open_connection_share(c, h, s);
454
455                 /* h, s were copied earlier */
456                 TALLOC_FREE(unc_list);
457                 return result;
458         }
459
460         return torture_open_connection_share(c, host, share);
461 }
462
463 bool torture_cli_session_setup2(struct cli_state *cli, uint16 *new_vuid)
464 {
465         uint16 old_vuid = cli->vuid;
466         fstring old_user_name;
467         size_t passlen = strlen(password);
468         NTSTATUS status;
469         bool ret;
470
471         fstrcpy(old_user_name, cli->user_name);
472         cli->vuid = 0;
473         ret = NT_STATUS_IS_OK(cli_session_setup(cli, username,
474                                                 password, passlen,
475                                                 password, passlen,
476                                                 workgroup));
477         *new_vuid = cli->vuid;
478         cli->vuid = old_vuid;
479         status = cli_set_username(cli, old_user_name);
480         if (!NT_STATUS_IS_OK(status)) {
481                 return false;
482         }
483         return ret;
484 }
485
486
487 bool torture_close_connection(struct cli_state *c)
488 {
489         bool ret = True;
490         NTSTATUS status;
491
492         status = cli_tdis(c);
493         if (!NT_STATUS_IS_OK(status)) {
494                 printf("tdis failed (%s)\n", nt_errstr(status));
495                 ret = False;
496         }
497
498         cli_shutdown(c);
499
500         return ret;
501 }
502
503
504 /* check if the server produced the expected error code */
505 static bool check_error(int line, struct cli_state *c, 
506                         uint8 eclass, uint32 ecode, NTSTATUS nterr)
507 {
508         if (cli_is_dos_error(c)) {
509                 uint8 cclass;
510                 uint32 num;
511
512                 /* Check DOS error */
513
514                 cli_dos_error(c, &cclass, &num);
515
516                 if (eclass != cclass || ecode != num) {
517                         printf("unexpected error code class=%d code=%d\n", 
518                                (int)cclass, (int)num);
519                         printf(" expected %d/%d %s (line=%d)\n", 
520                                (int)eclass, (int)ecode, nt_errstr(nterr), line);
521                         return False;
522                 }
523
524         } else {
525                 NTSTATUS status;
526
527                 /* Check NT error */
528
529                 status = cli_nt_error(c);
530
531                 if (NT_STATUS_V(nterr) != NT_STATUS_V(status)) {
532                         printf("unexpected error code %s\n", nt_errstr(status));
533                         printf(" expected %s (line=%d)\n", nt_errstr(nterr), line);
534                         return False;
535                 }
536         }
537
538         return True;
539 }
540
541
542 static bool wait_lock(struct cli_state *c, int fnum, uint32 offset, uint32 len)
543 {
544         while (!cli_lock(c, fnum, offset, len, -1, WRITE_LOCK)) {
545                 if (!check_error(__LINE__, c, ERRDOS, ERRlock, NT_STATUS_LOCK_NOT_GRANTED)) return False;
546         }
547         return True;
548 }
549
550
551 static bool rw_torture(struct cli_state *c)
552 {
553         const char *lockfname = "\\torture.lck";
554         fstring fname;
555         uint16_t fnum;
556         uint16_t fnum2;
557         pid_t pid2, pid = getpid();
558         int i, j;
559         char buf[1024];
560         bool correct = True;
561         NTSTATUS status;
562
563         memset(buf, '\0', sizeof(buf));
564
565         status = cli_open(c, lockfname, O_RDWR | O_CREAT | O_EXCL, 
566                          DENY_NONE, &fnum2);
567         if (!NT_STATUS_IS_OK(status)) {
568                 status = cli_open(c, lockfname, O_RDWR, DENY_NONE, &fnum2);
569         }
570         if (!NT_STATUS_IS_OK(status)) {
571                 printf("open of %s failed (%s)\n", lockfname, cli_errstr(c));
572                 return False;
573         }
574
575         for (i=0;i<torture_numops;i++) {
576                 unsigned n = (unsigned)sys_random()%10;
577                 if (i % 10 == 0) {
578                         printf("%d\r", i); fflush(stdout);
579                 }
580                 slprintf(fname, sizeof(fstring) - 1, "\\torture.%u", n);
581
582                 if (!wait_lock(c, fnum2, n*sizeof(int), sizeof(int))) {
583                         return False;
584                 }
585
586                 if (!NT_STATUS_IS_OK(cli_open(c, fname, O_RDWR | O_CREAT | O_TRUNC, DENY_ALL, &fnum))) {
587                         printf("open failed (%s)\n", cli_errstr(c));
588                         correct = False;
589                         break;
590                 }
591
592                 if (cli_write(c, fnum, 0, (char *)&pid, 0, sizeof(pid)) != sizeof(pid)) {
593                         printf("write failed (%s)\n", cli_errstr(c));
594                         correct = False;
595                 }
596
597                 for (j=0;j<50;j++) {
598                         if (cli_write(c, fnum, 0, (char *)buf, 
599                                       sizeof(pid)+(j*sizeof(buf)), 
600                                       sizeof(buf)) != sizeof(buf)) {
601                                 printf("write failed (%s)\n", cli_errstr(c));
602                                 correct = False;
603                         }
604                 }
605
606                 pid2 = 0;
607
608                 if (cli_read(c, fnum, (char *)&pid2, 0, sizeof(pid)) != sizeof(pid)) {
609                         printf("read failed (%s)\n", cli_errstr(c));
610                         correct = False;
611                 }
612
613                 if (pid2 != pid) {
614                         printf("data corruption!\n");
615                         correct = False;
616                 }
617
618                 if (!NT_STATUS_IS_OK(cli_close(c, fnum))) {
619                         printf("close failed (%s)\n", cli_errstr(c));
620                         correct = False;
621                 }
622
623                 if (!NT_STATUS_IS_OK(cli_unlink(c, fname, aSYSTEM | aHIDDEN))) {
624                         printf("unlink failed (%s)\n", cli_errstr(c));
625                         correct = False;
626                 }
627
628                 if (!NT_STATUS_IS_OK(cli_unlock(c, fnum2, n*sizeof(int), sizeof(int)))) {
629                         printf("unlock failed (%s)\n", cli_errstr(c));
630                         correct = False;
631                 }
632         }
633
634         cli_close(c, fnum2);
635         cli_unlink(c, lockfname, aSYSTEM | aHIDDEN);
636
637         printf("%d\n", i);
638
639         return correct;
640 }
641
642 static bool run_torture(int dummy)
643 {
644         struct cli_state *cli;
645         bool ret;
646
647         cli = current_cli;
648
649         cli_sockopt(cli, sockops);
650
651         ret = rw_torture(cli);
652
653         if (!torture_close_connection(cli)) {
654                 ret = False;
655         }
656
657         return ret;
658 }
659
660 static bool rw_torture3(struct cli_state *c, char *lockfname)
661 {
662         uint16_t fnum = (uint16_t)-1;
663         unsigned int i = 0;
664         char buf[131072];
665         char buf_rd[131072];
666         unsigned count;
667         unsigned countprev = 0;
668         ssize_t sent = 0;
669         bool correct = True;
670         NTSTATUS status;
671
672         srandom(1);
673         for (i = 0; i < sizeof(buf); i += sizeof(uint32))
674         {
675                 SIVAL(buf, i, sys_random());
676         }
677
678         if (procnum == 0)
679         {
680                 if (!NT_STATUS_IS_OK(cli_open(c, lockfname, O_RDWR | O_CREAT | O_EXCL, 
681                                  DENY_NONE, &fnum))) {
682                         printf("first open read/write of %s failed (%s)\n",
683                                         lockfname, cli_errstr(c));
684                         return False;
685                 }
686         }
687         else
688         {
689                 for (i = 0; i < 500 && fnum == (uint16_t)-1; i++)
690                 {
691                         status = cli_open(c, lockfname, O_RDONLY, 
692                                          DENY_NONE, &fnum);
693                         if (!NT_STATUS_IS_OK(status)) {
694                                 break;
695                         }
696                         smb_msleep(10);
697                 }
698                 if (!NT_STATUS_IS_OK(status)) {
699                         printf("second open read-only of %s failed (%s)\n",
700                                         lockfname, cli_errstr(c));
701                         return False;
702                 }
703         }
704
705         i = 0;
706         for (count = 0; count < sizeof(buf); count += sent)
707         {
708                 if (count >= countprev) {
709                         printf("%d %8d\r", i, count);
710                         fflush(stdout);
711                         i++;
712                         countprev += (sizeof(buf) / 20);
713                 }
714
715                 if (procnum == 0)
716                 {
717                         sent = ((unsigned)sys_random()%(20))+ 1;
718                         if (sent > sizeof(buf) - count)
719                         {
720                                 sent = sizeof(buf) - count;
721                         }
722
723                         if (cli_write(c, fnum, 0, buf+count, count, (size_t)sent) != sent) {
724                                 printf("write failed (%s)\n", cli_errstr(c));
725                                 correct = False;
726                         }
727                 }
728                 else
729                 {
730                         sent = cli_read(c, fnum, buf_rd+count, count,
731                                                   sizeof(buf)-count);
732                         if (sent < 0)
733                         {
734                                 printf("read failed offset:%d size:%ld (%s)\n",
735                                        count, (unsigned long)sizeof(buf)-count,
736                                        cli_errstr(c));
737                                 correct = False;
738                                 sent = 0;
739                         }
740                         if (sent > 0)
741                         {
742                                 if (memcmp(buf_rd+count, buf+count, sent) != 0)
743                                 {
744                                         printf("read/write compare failed\n");
745                                         printf("offset: %d req %ld recvd %ld\n", count, (unsigned long)sizeof(buf)-count, (unsigned long)sent);
746                                         correct = False;
747                                         break;
748                                 }
749                         }
750                 }
751
752         }
753
754         if (!NT_STATUS_IS_OK(cli_close(c, fnum))) {
755                 printf("close failed (%s)\n", cli_errstr(c));
756                 correct = False;
757         }
758
759         return correct;
760 }
761
762 static bool rw_torture2(struct cli_state *c1, struct cli_state *c2)
763 {
764         const char *lockfname = "\\torture2.lck";
765         uint16_t fnum1;
766         uint16_t fnum2;
767         int i;
768         char buf[131072];
769         char buf_rd[131072];
770         bool correct = True;
771         ssize_t bytes_read;
772
773         if (!NT_STATUS_IS_OK(cli_unlink(c1, lockfname, aSYSTEM | aHIDDEN))) {
774                 printf("unlink failed (%s) (normal, this file should not exist)\n", cli_errstr(c1));
775         }
776
777         if (!NT_STATUS_IS_OK(cli_open(c1, lockfname, O_RDWR | O_CREAT | O_EXCL, 
778                          DENY_NONE, &fnum1))) {
779                 printf("first open read/write of %s failed (%s)\n",
780                                 lockfname, cli_errstr(c1));
781                 return False;
782         }
783         if (!NT_STATUS_IS_OK(cli_open(c2, lockfname, O_RDONLY, 
784                          DENY_NONE, &fnum2))) {
785                 printf("second open read-only of %s failed (%s)\n",
786                                 lockfname, cli_errstr(c2));
787                 cli_close(c1, fnum1);
788                 return False;
789         }
790
791         for (i=0;i<torture_numops;i++)
792         {
793                 size_t buf_size = ((unsigned)sys_random()%(sizeof(buf)-1))+ 1;
794                 if (i % 10 == 0) {
795                         printf("%d\r", i); fflush(stdout);
796                 }
797
798                 generate_random_buffer((unsigned char *)buf, buf_size);
799
800                 if (cli_write(c1, fnum1, 0, buf, 0, buf_size) != buf_size) {
801                         printf("write failed (%s)\n", cli_errstr(c1));
802                         correct = False;
803                         break;
804                 }
805
806                 if ((bytes_read = cli_read(c2, fnum2, buf_rd, 0, buf_size)) != buf_size) {
807                         printf("read failed (%s)\n", cli_errstr(c2));
808                         printf("read %d, expected %ld\n", (int)bytes_read, 
809                                (unsigned long)buf_size); 
810                         correct = False;
811                         break;
812                 }
813
814                 if (memcmp(buf_rd, buf, buf_size) != 0)
815                 {
816                         printf("read/write compare failed\n");
817                         correct = False;
818                         break;
819                 }
820         }
821
822         if (!NT_STATUS_IS_OK(cli_close(c2, fnum2))) {
823                 printf("close failed (%s)\n", cli_errstr(c2));
824                 correct = False;
825         }
826         if (!NT_STATUS_IS_OK(cli_close(c1, fnum1))) {
827                 printf("close failed (%s)\n", cli_errstr(c1));
828                 correct = False;
829         }
830
831         if (!NT_STATUS_IS_OK(cli_unlink(c1, lockfname, aSYSTEM | aHIDDEN))) {
832                 printf("unlink failed (%s)\n", cli_errstr(c1));
833                 correct = False;
834         }
835
836         return correct;
837 }
838
839 static bool run_readwritetest(int dummy)
840 {
841         struct cli_state *cli1, *cli2;
842         bool test1, test2 = False;
843
844         if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
845                 return False;
846         }
847         cli_sockopt(cli1, sockops);
848         cli_sockopt(cli2, sockops);
849
850         printf("starting readwritetest\n");
851
852         test1 = rw_torture2(cli1, cli2);
853         printf("Passed readwritetest v1: %s\n", BOOLSTR(test1));
854
855         if (test1) {
856                 test2 = rw_torture2(cli1, cli1);
857                 printf("Passed readwritetest v2: %s\n", BOOLSTR(test2));
858         }
859
860         if (!torture_close_connection(cli1)) {
861                 test1 = False;
862         }
863
864         if (!torture_close_connection(cli2)) {
865                 test2 = False;
866         }
867
868         return (test1 && test2);
869 }
870
871 static bool run_readwritemulti(int dummy)
872 {
873         struct cli_state *cli;
874         bool test;
875
876         cli = current_cli;
877
878         cli_sockopt(cli, sockops);
879
880         printf("run_readwritemulti: fname %s\n", randomfname);
881         test = rw_torture3(cli, randomfname);
882
883         if (!torture_close_connection(cli)) {
884                 test = False;
885         }
886
887         return test;
888 }
889
890 static bool run_readwritelarge(int dummy)
891 {
892         static struct cli_state *cli1;
893         uint16_t fnum1;
894         const char *lockfname = "\\large.dat";
895         SMB_OFF_T fsize;
896         char buf[126*1024];
897         bool correct = True;
898
899         if (!torture_open_connection(&cli1, 0)) {
900                 return False;
901         }
902         cli_sockopt(cli1, sockops);
903         memset(buf,'\0',sizeof(buf));
904
905         cli1->max_xmit = 128*1024;
906
907         printf("starting readwritelarge\n");
908
909         cli_unlink(cli1, lockfname, aSYSTEM | aHIDDEN);
910
911         if (!NT_STATUS_IS_OK(cli_open(cli1, lockfname, O_RDWR | O_CREAT | O_EXCL, DENY_NONE, &fnum1))) {
912                 printf("open read/write of %s failed (%s)\n", lockfname, cli_errstr(cli1));
913                 return False;
914         }
915
916         cli_write(cli1, fnum1, 0, buf, 0, sizeof(buf));
917
918         if (!NT_STATUS_IS_OK(cli_qfileinfo_basic(
919                                      cli1, fnum1, NULL, &fsize, NULL, NULL,
920                                      NULL, NULL, NULL))) {
921                 printf("qfileinfo failed (%s)\n", cli_errstr(cli1));
922                 correct = False;
923         }
924
925         if (fsize == sizeof(buf))
926                 printf("readwritelarge test 1 succeeded (size = %lx)\n", 
927                        (unsigned long)fsize);
928         else {
929                 printf("readwritelarge test 1 failed (size = %lx)\n", 
930                        (unsigned long)fsize);
931                 correct = False;
932         }
933
934         if (!NT_STATUS_IS_OK(cli_close(cli1, fnum1))) {
935                 printf("close failed (%s)\n", cli_errstr(cli1));
936                 correct = False;
937         }
938
939         if (!NT_STATUS_IS_OK(cli_unlink(cli1, lockfname, aSYSTEM | aHIDDEN))) {
940                 printf("unlink failed (%s)\n", cli_errstr(cli1));
941                 correct = False;
942         }
943
944         if (!NT_STATUS_IS_OK(cli_open(cli1, lockfname, O_RDWR | O_CREAT | O_EXCL, DENY_NONE, &fnum1))) {
945                 printf("open read/write of %s failed (%s)\n", lockfname, cli_errstr(cli1));
946                 return False;
947         }
948
949         cli1->max_xmit = 4*1024;
950
951         cli_smbwrite(cli1, fnum1, buf, 0, sizeof(buf));
952
953         if (!NT_STATUS_IS_OK(cli_qfileinfo_basic(
954                                      cli1, fnum1, NULL, &fsize, NULL, NULL,
955                                      NULL, NULL, NULL))) {
956                 printf("qfileinfo failed (%s)\n", cli_errstr(cli1));
957                 correct = False;
958         }
959
960         if (fsize == sizeof(buf))
961                 printf("readwritelarge test 2 succeeded (size = %lx)\n", 
962                        (unsigned long)fsize);
963         else {
964                 printf("readwritelarge test 2 failed (size = %lx)\n", 
965                        (unsigned long)fsize);
966                 correct = False;
967         }
968
969 #if 0
970         /* ToDo - set allocation. JRA */
971         if(!cli_set_allocation_size(cli1, fnum1, 0)) {
972                 printf("set allocation size to zero failed (%s)\n", cli_errstr(&cli1));
973                 return False;
974         }
975         if (!cli_qfileinfo_basic(cli1, fnum1, NULL, &fsize, NULL, NULL, NULL,
976                                  NULL, NULL)) {
977                 printf("qfileinfo failed (%s)\n", cli_errstr(cli1));
978                 correct = False;
979         }
980         if (fsize != 0)
981                 printf("readwritelarge test 3 (truncate test) succeeded (size = %x)\n", fsize);
982 #endif
983
984         if (!NT_STATUS_IS_OK(cli_close(cli1, fnum1))) {
985                 printf("close failed (%s)\n", cli_errstr(cli1));
986                 correct = False;
987         }
988
989         if (!torture_close_connection(cli1)) {
990                 correct = False;
991         }
992         return correct;
993 }
994
995 int line_count = 0;
996 int nbio_id;
997
998 #define ival(s) strtol(s, NULL, 0)
999
1000 /* run a test that simulates an approximate netbench client load */
1001 static bool run_netbench(int client)
1002 {
1003         struct cli_state *cli;
1004         int i;
1005         char line[1024];
1006         char cname[20];
1007         FILE *f;
1008         const char *params[20];
1009         bool correct = True;
1010
1011         cli = current_cli;
1012
1013         nbio_id = client;
1014
1015         cli_sockopt(cli, sockops);
1016
1017         nb_setup(cli);
1018
1019         slprintf(cname,sizeof(cname)-1, "client%d", client);
1020
1021         f = fopen(client_txt, "r");
1022
1023         if (!f) {
1024                 perror(client_txt);
1025                 return False;
1026         }
1027
1028         while (fgets(line, sizeof(line)-1, f)) {
1029                 char *saveptr;
1030                 line_count++;
1031
1032                 line[strlen(line)-1] = 0;
1033
1034                 /* printf("[%d] %s\n", line_count, line); */
1035
1036                 all_string_sub(line,"client1", cname, sizeof(line));
1037
1038                 /* parse the command parameters */
1039                 params[0] = strtok_r(line, " ", &saveptr);
1040                 i = 0;
1041                 while (params[i]) params[++i] = strtok_r(NULL, " ", &saveptr);
1042
1043                 params[i] = "";
1044
1045                 if (i < 2) continue;
1046
1047                 if (!strncmp(params[0],"SMB", 3)) {
1048                         printf("ERROR: You are using a dbench 1 load file\n");
1049                         exit(1);
1050                 }
1051
1052                 if (!strcmp(params[0],"NTCreateX")) {
1053                         nb_createx(params[1], ival(params[2]), ival(params[3]), 
1054                                    ival(params[4]));
1055                 } else if (!strcmp(params[0],"Close")) {
1056                         nb_close(ival(params[1]));
1057                 } else if (!strcmp(params[0],"Rename")) {
1058                         nb_rename(params[1], params[2]);
1059                 } else if (!strcmp(params[0],"Unlink")) {
1060                         nb_unlink(params[1]);
1061                 } else if (!strcmp(params[0],"Deltree")) {
1062                         nb_deltree(params[1]);
1063                 } else if (!strcmp(params[0],"Rmdir")) {
1064                         nb_rmdir(params[1]);
1065                 } else if (!strcmp(params[0],"QUERY_PATH_INFORMATION")) {
1066                         nb_qpathinfo(params[1]);
1067                 } else if (!strcmp(params[0],"QUERY_FILE_INFORMATION")) {
1068                         nb_qfileinfo(ival(params[1]));
1069                 } else if (!strcmp(params[0],"QUERY_FS_INFORMATION")) {
1070                         nb_qfsinfo(ival(params[1]));
1071                 } else if (!strcmp(params[0],"FIND_FIRST")) {
1072                         nb_findfirst(params[1]);
1073                 } else if (!strcmp(params[0],"WriteX")) {
1074                         nb_writex(ival(params[1]), 
1075                                   ival(params[2]), ival(params[3]), ival(params[4]));
1076                 } else if (!strcmp(params[0],"ReadX")) {
1077                         nb_readx(ival(params[1]), 
1078                                   ival(params[2]), ival(params[3]), ival(params[4]));
1079                 } else if (!strcmp(params[0],"Flush")) {
1080                         nb_flush(ival(params[1]));
1081                 } else {
1082                         printf("Unknown operation %s\n", params[0]);
1083                         exit(1);
1084                 }
1085         }
1086         fclose(f);
1087
1088         nb_cleanup();
1089
1090         if (!torture_close_connection(cli)) {
1091                 correct = False;
1092         }
1093
1094         return correct;
1095 }
1096
1097
1098 /* run a test that simulates an approximate netbench client load */
1099 static bool run_nbench(int dummy)
1100 {
1101         double t;
1102         bool correct = True;
1103
1104         nbio_shmem(nprocs);
1105
1106         nbio_id = -1;
1107
1108         signal(SIGALRM, nb_alarm);
1109         alarm(1);
1110         t = create_procs(run_netbench, &correct);
1111         alarm(0);
1112
1113         printf("\nThroughput %g MB/sec\n", 
1114                1.0e-6 * nbio_total() / t);
1115         return correct;
1116 }
1117
1118
1119 /*
1120   This test checks for two things:
1121
1122   1) correct support for retaining locks over a close (ie. the server
1123      must not use posix semantics)
1124   2) support for lock timeouts
1125  */
1126 static bool run_locktest1(int dummy)
1127 {
1128         struct cli_state *cli1, *cli2;
1129         const char *fname = "\\lockt1.lck";
1130         uint16_t fnum1, fnum2, fnum3;
1131         time_t t1, t2;
1132         unsigned lock_timeout;
1133
1134         if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
1135                 return False;
1136         }
1137         cli_sockopt(cli1, sockops);
1138         cli_sockopt(cli2, sockops);
1139
1140         printf("starting locktest1\n");
1141
1142         cli_unlink(cli1, fname, aSYSTEM | aHIDDEN);
1143
1144         if (!NT_STATUS_IS_OK(cli_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1))) {
1145                 printf("open of %s failed (%s)\n", fname, cli_errstr(cli1));
1146                 return False;
1147         }
1148         if (!NT_STATUS_IS_OK(cli_open(cli1, fname, O_RDWR, DENY_NONE, &fnum2))) {
1149                 printf("open2 of %s failed (%s)\n", fname, cli_errstr(cli1));
1150                 return False;
1151         }
1152         if (!NT_STATUS_IS_OK(cli_open(cli2, fname, O_RDWR, DENY_NONE, &fnum3))) {
1153                 printf("open3 of %s failed (%s)\n", fname, cli_errstr(cli2));
1154                 return False;
1155         }
1156
1157         if (!cli_lock(cli1, fnum1, 0, 4, 0, WRITE_LOCK)) {
1158                 printf("lock1 failed (%s)\n", cli_errstr(cli1));
1159                 return False;
1160         }
1161
1162
1163         if (cli_lock(cli2, fnum3, 0, 4, 0, WRITE_LOCK)) {
1164                 printf("lock2 succeeded! This is a locking bug\n");
1165                 return False;
1166         } else {
1167                 if (!check_error(__LINE__, cli2, ERRDOS, ERRlock, 
1168                                  NT_STATUS_LOCK_NOT_GRANTED)) return False;
1169         }
1170
1171
1172         lock_timeout = (1 + (random() % 20));
1173         printf("Testing lock timeout with timeout=%u\n", lock_timeout);
1174         t1 = time(NULL);
1175         if (cli_lock(cli2, fnum3, 0, 4, lock_timeout * 1000, WRITE_LOCK)) {
1176                 printf("lock3 succeeded! This is a locking bug\n");
1177                 return False;
1178         } else {
1179                 if (!check_error(__LINE__, cli2, ERRDOS, ERRlock, 
1180                                  NT_STATUS_FILE_LOCK_CONFLICT)) return False;
1181         }
1182         t2 = time(NULL);
1183
1184         if (ABS(t2 - t1) < lock_timeout-1) {
1185                 printf("error: This server appears not to support timed lock requests\n");
1186         }
1187
1188         printf("server slept for %u seconds for a %u second timeout\n",
1189                (unsigned int)(t2-t1), lock_timeout);
1190
1191         if (!NT_STATUS_IS_OK(cli_close(cli1, fnum2))) {
1192                 printf("close1 failed (%s)\n", cli_errstr(cli1));
1193                 return False;
1194         }
1195
1196         if (cli_lock(cli2, fnum3, 0, 4, 0, WRITE_LOCK)) {
1197                 printf("lock4 succeeded! This is a locking bug\n");
1198                 return False;
1199         } else {
1200                 if (!check_error(__LINE__, cli2, ERRDOS, ERRlock, 
1201                                  NT_STATUS_FILE_LOCK_CONFLICT)) return False;
1202         }
1203
1204         if (!NT_STATUS_IS_OK(cli_close(cli1, fnum1))) {
1205                 printf("close2 failed (%s)\n", cli_errstr(cli1));
1206                 return False;
1207         }
1208
1209         if (!NT_STATUS_IS_OK(cli_close(cli2, fnum3))) {
1210                 printf("close3 failed (%s)\n", cli_errstr(cli2));
1211                 return False;
1212         }
1213
1214         if (!NT_STATUS_IS_OK(cli_unlink(cli1, fname, aSYSTEM | aHIDDEN))) {
1215                 printf("unlink failed (%s)\n", cli_errstr(cli1));
1216                 return False;
1217         }
1218
1219
1220         if (!torture_close_connection(cli1)) {
1221                 return False;
1222         }
1223
1224         if (!torture_close_connection(cli2)) {
1225                 return False;
1226         }
1227
1228         printf("Passed locktest1\n");
1229         return True;
1230 }
1231
1232 /*
1233   this checks to see if a secondary tconx can use open files from an
1234   earlier tconx
1235  */
1236 static bool run_tcon_test(int dummy)
1237 {
1238         static struct cli_state *cli;
1239         const char *fname = "\\tcontest.tmp";
1240         uint16 fnum1;
1241         uint16 cnum1, cnum2, cnum3;
1242         uint16 vuid1, vuid2;
1243         char buf[4];
1244         bool ret = True;
1245         NTSTATUS status;
1246
1247         memset(buf, '\0', sizeof(buf));
1248
1249         if (!torture_open_connection(&cli, 0)) {
1250                 return False;
1251         }
1252         cli_sockopt(cli, sockops);
1253
1254         printf("starting tcontest\n");
1255
1256         cli_unlink(cli, fname, aSYSTEM | aHIDDEN);
1257
1258         if (!NT_STATUS_IS_OK(cli_open(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1))) {
1259                 printf("open of %s failed (%s)\n", fname, cli_errstr(cli));
1260                 return False;
1261         }
1262
1263         cnum1 = cli->cnum;
1264         vuid1 = cli->vuid;
1265
1266         if (cli_write(cli, fnum1, 0, buf, 130, 4) != 4) {
1267                 printf("initial write failed (%s)", cli_errstr(cli));
1268                 return False;
1269         }
1270
1271         status = cli_tcon_andx(cli, share, "?????",
1272                                password, strlen(password)+1);
1273         if (!NT_STATUS_IS_OK(status)) {
1274                 printf("%s refused 2nd tree connect (%s)\n", host,
1275                        nt_errstr(status));
1276                 cli_shutdown(cli);
1277                 return False;
1278         }
1279
1280         cnum2 = cli->cnum;
1281         cnum3 = MAX(cnum1, cnum2) + 1; /* any invalid number */
1282         vuid2 = cli->vuid + 1;
1283
1284         /* try a write with the wrong tid */
1285         cli->cnum = cnum2;
1286
1287         if (cli_write(cli, fnum1, 0, buf, 130, 4) == 4) {
1288                 printf("* server allows write with wrong TID\n");
1289                 ret = False;
1290         } else {
1291                 printf("server fails write with wrong TID : %s\n", cli_errstr(cli));
1292         }
1293
1294
1295         /* try a write with an invalid tid */
1296         cli->cnum = cnum3;
1297
1298         if (cli_write(cli, fnum1, 0, buf, 130, 4) == 4) {
1299                 printf("* server allows write with invalid TID\n");
1300                 ret = False;
1301         } else {
1302                 printf("server fails write with invalid TID : %s\n", cli_errstr(cli));
1303         }
1304
1305         /* try a write with an invalid vuid */
1306         cli->vuid = vuid2;
1307         cli->cnum = cnum1;
1308
1309         if (cli_write(cli, fnum1, 0, buf, 130, 4) == 4) {
1310                 printf("* server allows write with invalid VUID\n");
1311                 ret = False;
1312         } else {
1313                 printf("server fails write with invalid VUID : %s\n", cli_errstr(cli));
1314         }
1315
1316         cli->cnum = cnum1;
1317         cli->vuid = vuid1;
1318
1319         if (!NT_STATUS_IS_OK(cli_close(cli, fnum1))) {
1320                 printf("close failed (%s)\n", cli_errstr(cli));
1321                 return False;
1322         }
1323
1324         cli->cnum = cnum2;
1325
1326         status = cli_tdis(cli);
1327         if (!NT_STATUS_IS_OK(status)) {
1328                 printf("secondary tdis failed (%s)\n", nt_errstr(status));
1329                 return False;
1330         }
1331
1332         cli->cnum = cnum1;
1333
1334         if (!torture_close_connection(cli)) {
1335                 return False;
1336         }
1337
1338         return ret;
1339 }
1340
1341
1342 /*
1343  checks for old style tcon support
1344  */
1345 static bool run_tcon2_test(int dummy)
1346 {
1347         static struct cli_state *cli;
1348         uint16 cnum, max_xmit;
1349         char *service;
1350         NTSTATUS status;
1351
1352         if (!torture_open_connection(&cli, 0)) {
1353                 return False;
1354         }
1355         cli_sockopt(cli, sockops);
1356
1357         printf("starting tcon2 test\n");
1358
1359         if (asprintf(&service, "\\\\%s\\%s", host, share) == -1) {
1360                 return false;
1361         }
1362
1363         status = cli_raw_tcon(cli, service, password, "?????", &max_xmit, &cnum);
1364
1365         if (!NT_STATUS_IS_OK(status)) {
1366                 printf("tcon2 failed : %s\n", cli_errstr(cli));
1367         } else {
1368                 printf("tcon OK : max_xmit=%d cnum=%d tid=%d\n", 
1369                        (int)max_xmit, (int)cnum, SVAL(cli->inbuf, smb_tid));
1370         }
1371
1372         if (!torture_close_connection(cli)) {
1373                 return False;
1374         }
1375
1376         printf("Passed tcon2 test\n");
1377         return True;
1378 }
1379
1380 static bool tcon_devtest(struct cli_state *cli,
1381                          const char *myshare, const char *devtype,
1382                          const char *return_devtype,
1383                          NTSTATUS expected_error)
1384 {
1385         NTSTATUS status;
1386         bool ret;
1387
1388         status = cli_tcon_andx(cli, myshare, devtype,
1389                                password, strlen(password)+1);
1390
1391         if (NT_STATUS_IS_OK(expected_error)) {
1392                 if (NT_STATUS_IS_OK(status)) {
1393                         if (strcmp(cli->dev, return_devtype) == 0) {
1394                                 ret = True;
1395                         } else { 
1396                                 printf("tconX to share %s with type %s "
1397                                        "succeeded but returned the wrong "
1398                                        "device type (got [%s] but should have got [%s])\n",
1399                                        myshare, devtype, cli->dev, return_devtype);
1400                                 ret = False;
1401                         }
1402                 } else {
1403                         printf("tconX to share %s with type %s "
1404                                "should have succeeded but failed\n",
1405                                myshare, devtype);
1406                         ret = False;
1407                 }
1408                 cli_tdis(cli);
1409         } else {
1410                 if (NT_STATUS_IS_OK(status)) {
1411                         printf("tconx to share %s with type %s "
1412                                "should have failed but succeeded\n",
1413                                myshare, devtype);
1414                         ret = False;
1415                 } else {
1416                         if (NT_STATUS_EQUAL(cli_nt_error(cli),
1417                                             expected_error)) {
1418                                 ret = True;
1419                         } else {
1420                                 printf("Returned unexpected error\n");
1421                                 ret = False;
1422                         }
1423                 }
1424         }
1425         return ret;
1426 }
1427
1428 /*
1429  checks for correct tconX support
1430  */
1431 static bool run_tcon_devtype_test(int dummy)
1432 {
1433         static struct cli_state *cli1 = NULL;
1434         bool retry;
1435         int flags = 0;
1436         NTSTATUS status;
1437         bool ret = True;
1438
1439         status = cli_full_connection(&cli1, myname,
1440                                      host, NULL, port_to_use,
1441                                      NULL, NULL,
1442                                      username, workgroup,
1443                                      password, flags, Undefined, &retry);
1444
1445         if (!NT_STATUS_IS_OK(status)) {
1446                 printf("could not open connection\n");
1447                 return False;
1448         }
1449
1450         if (!tcon_devtest(cli1, "IPC$", "A:", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1451                 ret = False;
1452
1453         if (!tcon_devtest(cli1, "IPC$", "?????", "IPC", NT_STATUS_OK))
1454                 ret = False;
1455
1456         if (!tcon_devtest(cli1, "IPC$", "LPT:", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1457                 ret = False;
1458
1459         if (!tcon_devtest(cli1, "IPC$", "IPC", "IPC", NT_STATUS_OK))
1460                 ret = False;
1461
1462         if (!tcon_devtest(cli1, "IPC$", "FOOBA", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1463                 ret = False;
1464
1465         if (!tcon_devtest(cli1, share, "A:", "A:", NT_STATUS_OK))
1466                 ret = False;
1467
1468         if (!tcon_devtest(cli1, share, "?????", "A:", NT_STATUS_OK))
1469                 ret = False;
1470
1471         if (!tcon_devtest(cli1, share, "LPT:", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1472                 ret = False;
1473
1474         if (!tcon_devtest(cli1, share, "IPC", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1475                 ret = False;
1476
1477         if (!tcon_devtest(cli1, share, "FOOBA", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1478                 ret = False;
1479
1480         cli_shutdown(cli1);
1481
1482         if (ret)
1483                 printf("Passed tcondevtest\n");
1484
1485         return ret;
1486 }
1487
1488
1489 /*
1490   This test checks that 
1491
1492   1) the server supports multiple locking contexts on the one SMB
1493   connection, distinguished by PID.  
1494
1495   2) the server correctly fails overlapping locks made by the same PID (this
1496      goes against POSIX behaviour, which is why it is tricky to implement)
1497
1498   3) the server denies unlock requests by an incorrect client PID
1499 */
1500 static bool run_locktest2(int dummy)
1501 {
1502         static struct cli_state *cli;
1503         const char *fname = "\\lockt2.lck";
1504         uint16_t fnum1, fnum2, fnum3;
1505         bool correct = True;
1506
1507         if (!torture_open_connection(&cli, 0)) {
1508                 return False;
1509         }
1510
1511         cli_sockopt(cli, sockops);
1512
1513         printf("starting locktest2\n");
1514
1515         cli_unlink(cli, fname, aSYSTEM | aHIDDEN);
1516
1517         cli_setpid(cli, 1);
1518
1519         if (!NT_STATUS_IS_OK(cli_open(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1))) {
1520                 printf("open of %s failed (%s)\n", fname, cli_errstr(cli));
1521                 return False;
1522         }
1523
1524         if (!NT_STATUS_IS_OK(cli_open(cli, fname, O_RDWR, DENY_NONE, &fnum2))) {
1525                 printf("open2 of %s failed (%s)\n", fname, cli_errstr(cli));
1526                 return False;
1527         }
1528
1529         cli_setpid(cli, 2);
1530
1531         if (!NT_STATUS_IS_OK(cli_open(cli, fname, O_RDWR, DENY_NONE, &fnum3))) {
1532                 printf("open3 of %s failed (%s)\n", fname, cli_errstr(cli));
1533                 return False;
1534         }
1535
1536         cli_setpid(cli, 1);
1537
1538         if (!cli_lock(cli, fnum1, 0, 4, 0, WRITE_LOCK)) {
1539                 printf("lock1 failed (%s)\n", cli_errstr(cli));
1540                 return False;
1541         }
1542
1543         if (cli_lock(cli, fnum1, 0, 4, 0, WRITE_LOCK)) {
1544                 printf("WRITE lock1 succeeded! This is a locking bug\n");
1545                 correct = False;
1546         } else {
1547                 if (!check_error(__LINE__, cli, ERRDOS, ERRlock, 
1548                                  NT_STATUS_LOCK_NOT_GRANTED)) return False;
1549         }
1550
1551         if (cli_lock(cli, fnum2, 0, 4, 0, WRITE_LOCK)) {
1552                 printf("WRITE lock2 succeeded! This is a locking bug\n");
1553                 correct = False;
1554         } else {
1555                 if (!check_error(__LINE__, cli, ERRDOS, ERRlock, 
1556                                  NT_STATUS_LOCK_NOT_GRANTED)) return False;
1557         }
1558
1559         if (cli_lock(cli, fnum2, 0, 4, 0, READ_LOCK)) {
1560                 printf("READ lock2 succeeded! This is a locking bug\n");
1561                 correct = False;
1562         } else {
1563                 if (!check_error(__LINE__, cli, ERRDOS, ERRlock, 
1564                                  NT_STATUS_FILE_LOCK_CONFLICT)) return False;
1565         }
1566
1567         if (!cli_lock(cli, fnum1, 100, 4, 0, WRITE_LOCK)) {
1568                 printf("lock at 100 failed (%s)\n", cli_errstr(cli));
1569         }
1570         cli_setpid(cli, 2);
1571         if (NT_STATUS_IS_OK(cli_unlock(cli, fnum1, 100, 4))) {
1572                 printf("unlock at 100 succeeded! This is a locking bug\n");
1573                 correct = False;
1574         }
1575
1576         if (NT_STATUS_IS_OK(cli_unlock(cli, fnum1, 0, 4))) {
1577                 printf("unlock1 succeeded! This is a locking bug\n");
1578                 correct = False;
1579         } else {
1580                 if (!check_error(__LINE__, cli, 
1581                                  ERRDOS, ERRlock, 
1582                                  NT_STATUS_RANGE_NOT_LOCKED)) return False;
1583         }
1584
1585         if (NT_STATUS_IS_OK(cli_unlock(cli, fnum1, 0, 8))) {
1586                 printf("unlock2 succeeded! This is a locking bug\n");
1587                 correct = False;
1588         } else {
1589                 if (!check_error(__LINE__, cli, 
1590                                  ERRDOS, ERRlock, 
1591                                  NT_STATUS_RANGE_NOT_LOCKED)) return False;
1592         }
1593
1594         if (cli_lock(cli, fnum3, 0, 4, 0, WRITE_LOCK)) {
1595                 printf("lock3 succeeded! This is a locking bug\n");
1596                 correct = False;
1597         } else {
1598                 if (!check_error(__LINE__, cli, ERRDOS, ERRlock, NT_STATUS_LOCK_NOT_GRANTED)) return False;
1599         }
1600
1601         cli_setpid(cli, 1);
1602
1603         if (!NT_STATUS_IS_OK(cli_close(cli, fnum1))) {
1604                 printf("close1 failed (%s)\n", cli_errstr(cli));
1605                 return False;
1606         }
1607
1608         if (!NT_STATUS_IS_OK(cli_close(cli, fnum2))) {
1609                 printf("close2 failed (%s)\n", cli_errstr(cli));
1610                 return False;
1611         }
1612
1613         if (!NT_STATUS_IS_OK(cli_close(cli, fnum3))) {
1614                 printf("close3 failed (%s)\n", cli_errstr(cli));
1615                 return False;
1616         }
1617
1618         if (!torture_close_connection(cli)) {
1619                 correct = False;
1620         }
1621
1622         printf("locktest2 finished\n");
1623
1624         return correct;
1625 }
1626
1627
1628 /*
1629   This test checks that 
1630
1631   1) the server supports the full offset range in lock requests
1632 */
1633 static bool run_locktest3(int dummy)
1634 {
1635         static struct cli_state *cli1, *cli2;
1636         const char *fname = "\\lockt3.lck";
1637         uint16_t fnum1, fnum2;
1638         int i;
1639         uint32 offset;
1640         bool correct = True;
1641
1642 #define NEXT_OFFSET offset += (~(uint32)0) / torture_numops
1643
1644         if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
1645                 return False;
1646         }
1647         cli_sockopt(cli1, sockops);
1648         cli_sockopt(cli2, sockops);
1649
1650         printf("starting locktest3\n");
1651
1652         cli_unlink(cli1, fname, aSYSTEM | aHIDDEN);
1653
1654         if (!NT_STATUS_IS_OK(cli_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1))) {
1655                 printf("open of %s failed (%s)\n", fname, cli_errstr(cli1));
1656                 return False;
1657         }
1658         if (!NT_STATUS_IS_OK(cli_open(cli2, fname, O_RDWR, DENY_NONE, &fnum2))) {
1659                 printf("open2 of %s failed (%s)\n", fname, cli_errstr(cli2));
1660                 return False;
1661         }
1662
1663         for (offset=i=0;i<torture_numops;i++) {
1664                 NEXT_OFFSET;
1665                 if (!cli_lock(cli1, fnum1, offset-1, 1, 0, WRITE_LOCK)) {
1666                         printf("lock1 %d failed (%s)\n", 
1667                                i,
1668                                cli_errstr(cli1));
1669                         return False;
1670                 }
1671
1672                 if (!cli_lock(cli2, fnum2, offset-2, 1, 0, WRITE_LOCK)) {
1673                         printf("lock2 %d failed (%s)\n", 
1674                                i,
1675                                cli_errstr(cli1));
1676                         return False;
1677                 }
1678         }
1679
1680         for (offset=i=0;i<torture_numops;i++) {
1681                 NEXT_OFFSET;
1682
1683                 if (cli_lock(cli1, fnum1, offset-2, 1, 0, WRITE_LOCK)) {
1684                         printf("error: lock1 %d succeeded!\n", i);
1685                         return False;
1686                 }
1687
1688                 if (cli_lock(cli2, fnum2, offset-1, 1, 0, WRITE_LOCK)) {
1689                         printf("error: lock2 %d succeeded!\n", i);
1690                         return False;
1691                 }
1692
1693                 if (cli_lock(cli1, fnum1, offset-1, 1, 0, WRITE_LOCK)) {
1694                         printf("error: lock3 %d succeeded!\n", i);
1695                         return False;
1696                 }
1697
1698                 if (cli_lock(cli2, fnum2, offset-2, 1, 0, WRITE_LOCK)) {
1699                         printf("error: lock4 %d succeeded!\n", i);
1700                         return False;
1701                 }
1702         }
1703
1704         for (offset=i=0;i<torture_numops;i++) {
1705                 NEXT_OFFSET;
1706
1707                 if (!NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, offset-1, 1))) {
1708                         printf("unlock1 %d failed (%s)\n", 
1709                                i,
1710                                cli_errstr(cli1));
1711                         return False;
1712                 }
1713
1714                 if (!NT_STATUS_IS_OK(cli_unlock(cli2, fnum2, offset-2, 1))) {
1715                         printf("unlock2 %d failed (%s)\n", 
1716                                i,
1717                                cli_errstr(cli1));
1718                         return False;
1719                 }
1720         }
1721
1722         if (!NT_STATUS_IS_OK(cli_close(cli1, fnum1))) {
1723                 printf("close1 failed (%s)\n", cli_errstr(cli1));
1724                 return False;
1725         }
1726
1727         if (!NT_STATUS_IS_OK(cli_close(cli2, fnum2))) {
1728                 printf("close2 failed (%s)\n", cli_errstr(cli2));
1729                 return False;
1730         }
1731
1732         if (!NT_STATUS_IS_OK(cli_unlink(cli1, fname, aSYSTEM | aHIDDEN))) {
1733                 printf("unlink failed (%s)\n", cli_errstr(cli1));
1734                 return False;
1735         }
1736
1737         if (!torture_close_connection(cli1)) {
1738                 correct = False;
1739         }
1740
1741         if (!torture_close_connection(cli2)) {
1742                 correct = False;
1743         }
1744
1745         printf("finished locktest3\n");
1746
1747         return correct;
1748 }
1749
1750 #define EXPECTED(ret, v) if ((ret) != (v)) { \
1751         printf("** "); correct = False; \
1752         }
1753
1754 /*
1755   looks at overlapping locks
1756 */
1757 static bool run_locktest4(int dummy)
1758 {
1759         static struct cli_state *cli1, *cli2;
1760         const char *fname = "\\lockt4.lck";
1761         uint16_t fnum1, fnum2, f;
1762         bool ret;
1763         char buf[1000];
1764         bool correct = True;
1765
1766         if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
1767                 return False;
1768         }
1769
1770         cli_sockopt(cli1, sockops);
1771         cli_sockopt(cli2, sockops);
1772
1773         printf("starting locktest4\n");
1774
1775         cli_unlink(cli1, fname, aSYSTEM | aHIDDEN);
1776
1777         cli_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
1778         cli_open(cli2, fname, O_RDWR, DENY_NONE, &fnum2);
1779
1780         memset(buf, 0, sizeof(buf));
1781
1782         if (cli_write(cli1, fnum1, 0, buf, 0, sizeof(buf)) != sizeof(buf)) {
1783                 printf("Failed to create file\n");
1784                 correct = False;
1785                 goto fail;
1786         }
1787
1788         ret = cli_lock(cli1, fnum1, 0, 4, 0, WRITE_LOCK) &&
1789               cli_lock(cli1, fnum1, 2, 4, 0, WRITE_LOCK);
1790         EXPECTED(ret, False);
1791         printf("the same process %s set overlapping write locks\n", ret?"can":"cannot");
1792
1793         ret = cli_lock(cli1, fnum1, 10, 4, 0, READ_LOCK) &&
1794               cli_lock(cli1, fnum1, 12, 4, 0, READ_LOCK);
1795         EXPECTED(ret, True);
1796         printf("the same process %s set overlapping read locks\n", ret?"can":"cannot");
1797
1798         ret = cli_lock(cli1, fnum1, 20, 4, 0, WRITE_LOCK) &&
1799               cli_lock(cli2, fnum2, 22, 4, 0, WRITE_LOCK);
1800         EXPECTED(ret, False);
1801         printf("a different connection %s set overlapping write locks\n", ret?"can":"cannot");
1802
1803         ret = cli_lock(cli1, fnum1, 30, 4, 0, READ_LOCK) &&
1804               cli_lock(cli2, fnum2, 32, 4, 0, READ_LOCK);
1805         EXPECTED(ret, True);
1806         printf("a different connection %s set overlapping read locks\n", ret?"can":"cannot");
1807
1808         ret = (cli_setpid(cli1, 1), cli_lock(cli1, fnum1, 40, 4, 0, WRITE_LOCK)) &&
1809               (cli_setpid(cli1, 2), cli_lock(cli1, fnum1, 42, 4, 0, WRITE_LOCK));
1810         EXPECTED(ret, False);
1811         printf("a different pid %s set overlapping write locks\n", ret?"can":"cannot");
1812
1813         ret = (cli_setpid(cli1, 1), cli_lock(cli1, fnum1, 50, 4, 0, READ_LOCK)) &&
1814               (cli_setpid(cli1, 2), cli_lock(cli1, fnum1, 52, 4, 0, READ_LOCK));
1815         EXPECTED(ret, True);
1816         printf("a different pid %s set overlapping read locks\n", ret?"can":"cannot");
1817
1818         ret = cli_lock(cli1, fnum1, 60, 4, 0, READ_LOCK) &&
1819               cli_lock(cli1, fnum1, 60, 4, 0, READ_LOCK);
1820         EXPECTED(ret, True);
1821         printf("the same process %s set the same read lock twice\n", ret?"can":"cannot");
1822
1823         ret = cli_lock(cli1, fnum1, 70, 4, 0, WRITE_LOCK) &&
1824               cli_lock(cli1, fnum1, 70, 4, 0, WRITE_LOCK);
1825         EXPECTED(ret, False);
1826         printf("the same process %s set the same write lock twice\n", ret?"can":"cannot");
1827
1828         ret = cli_lock(cli1, fnum1, 80, 4, 0, READ_LOCK) &&
1829               cli_lock(cli1, fnum1, 80, 4, 0, WRITE_LOCK);
1830         EXPECTED(ret, False);
1831         printf("the same process %s overlay a read lock with a write lock\n", ret?"can":"cannot");
1832
1833         ret = cli_lock(cli1, fnum1, 90, 4, 0, WRITE_LOCK) &&
1834               cli_lock(cli1, fnum1, 90, 4, 0, READ_LOCK);
1835         EXPECTED(ret, True);
1836         printf("the same process %s overlay a write lock with a read lock\n", ret?"can":"cannot");
1837
1838         ret = (cli_setpid(cli1, 1), cli_lock(cli1, fnum1, 100, 4, 0, WRITE_LOCK)) &&
1839               (cli_setpid(cli1, 2), cli_lock(cli1, fnum1, 100, 4, 0, READ_LOCK));
1840         EXPECTED(ret, False);
1841         printf("a different pid %s overlay a write lock with a read lock\n", ret?"can":"cannot");
1842
1843         ret = cli_lock(cli1, fnum1, 110, 4, 0, READ_LOCK) &&
1844               cli_lock(cli1, fnum1, 112, 4, 0, READ_LOCK) &&
1845               NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 110, 6));
1846         EXPECTED(ret, False);
1847         printf("the same process %s coalesce read locks\n", ret?"can":"cannot");
1848
1849
1850         ret = cli_lock(cli1, fnum1, 120, 4, 0, WRITE_LOCK) &&
1851               (cli_read(cli2, fnum2, buf, 120, 4) == 4);
1852         EXPECTED(ret, False);
1853         printf("this server %s strict write locking\n", ret?"doesn't do":"does");
1854
1855         ret = cli_lock(cli1, fnum1, 130, 4, 0, READ_LOCK) &&
1856               (cli_write(cli2, fnum2, 0, buf, 130, 4) == 4);
1857         EXPECTED(ret, False);
1858         printf("this server %s strict read locking\n", ret?"doesn't do":"does");
1859
1860
1861         ret = cli_lock(cli1, fnum1, 140, 4, 0, READ_LOCK) &&
1862               cli_lock(cli1, fnum1, 140, 4, 0, READ_LOCK) &&
1863               NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 140, 4)) &&
1864               NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 140, 4));
1865         EXPECTED(ret, True);
1866         printf("this server %s do recursive read locking\n", ret?"does":"doesn't");
1867
1868
1869         ret = cli_lock(cli1, fnum1, 150, 4, 0, WRITE_LOCK) &&
1870               cli_lock(cli1, fnum1, 150, 4, 0, READ_LOCK) &&
1871               NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 150, 4)) &&
1872               (cli_read(cli2, fnum2, buf, 150, 4) == 4) &&
1873               !(cli_write(cli2, fnum2, 0, buf, 150, 4) == 4) &&
1874               NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 150, 4));
1875         EXPECTED(ret, True);
1876         printf("this server %s do recursive lock overlays\n", ret?"does":"doesn't");
1877
1878         ret = cli_lock(cli1, fnum1, 160, 4, 0, READ_LOCK) &&
1879               NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 160, 4)) &&
1880               (cli_write(cli2, fnum2, 0, buf, 160, 4) == 4) &&          
1881               (cli_read(cli2, fnum2, buf, 160, 4) == 4);                
1882         EXPECTED(ret, True);
1883         printf("the same process %s remove a read lock using write locking\n", ret?"can":"cannot");
1884
1885         ret = cli_lock(cli1, fnum1, 170, 4, 0, WRITE_LOCK) &&
1886               NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 170, 4)) &&
1887               (cli_write(cli2, fnum2, 0, buf, 170, 4) == 4) &&          
1888               (cli_read(cli2, fnum2, buf, 170, 4) == 4);                
1889         EXPECTED(ret, True);
1890         printf("the same process %s remove a write lock using read locking\n", ret?"can":"cannot");
1891
1892         ret = cli_lock(cli1, fnum1, 190, 4, 0, WRITE_LOCK) &&
1893               cli_lock(cli1, fnum1, 190, 4, 0, READ_LOCK) &&
1894               NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 190, 4)) &&
1895               !(cli_write(cli2, fnum2, 0, buf, 190, 4) == 4) &&         
1896               (cli_read(cli2, fnum2, buf, 190, 4) == 4);                
1897         EXPECTED(ret, True);
1898         printf("the same process %s remove the first lock first\n", ret?"does":"doesn't");
1899
1900         cli_close(cli1, fnum1);
1901         cli_close(cli2, fnum2);
1902         cli_open(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
1903         cli_open(cli1, fname, O_RDWR, DENY_NONE, &f);
1904         ret = cli_lock(cli1, fnum1, 0, 8, 0, READ_LOCK) &&
1905               cli_lock(cli1, f, 0, 1, 0, READ_LOCK) &&
1906               NT_STATUS_IS_OK(cli_close(cli1, fnum1)) &&
1907               NT_STATUS_IS_OK(cli_open(cli1, fname, O_RDWR, DENY_NONE, &fnum1)) &&
1908               cli_lock(cli1, fnum1, 7, 1, 0, WRITE_LOCK);
1909         cli_close(cli1, f);
1910         cli_close(cli1, fnum1);
1911         EXPECTED(ret, True);
1912         printf("the server %s have the NT byte range lock bug\n", !ret?"does":"doesn't");
1913
1914  fail:
1915         cli_close(cli1, fnum1);
1916         cli_close(cli2, fnum2);
1917         cli_unlink(cli1, fname, aSYSTEM | aHIDDEN);
1918         torture_close_connection(cli1);
1919         torture_close_connection(cli2);
1920
1921         printf("finished locktest4\n");
1922         return correct;
1923 }
1924
1925 /*
1926   looks at lock upgrade/downgrade.
1927 */
1928 static bool run_locktest5(int dummy)
1929 {
1930         static struct cli_state *cli1, *cli2;
1931         const char *fname = "\\lockt5.lck";
1932         uint16_t fnum1, fnum2, fnum3;
1933         bool ret;
1934         char buf[1000];
1935         bool correct = True;
1936
1937         if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
1938                 return False;
1939         }
1940
1941         cli_sockopt(cli1, sockops);
1942         cli_sockopt(cli2, sockops);
1943
1944         printf("starting locktest5\n");
1945
1946         cli_unlink(cli1, fname, aSYSTEM | aHIDDEN);
1947
1948         cli_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
1949         cli_open(cli2, fname, O_RDWR, DENY_NONE, &fnum2);
1950         cli_open(cli1, fname, O_RDWR, DENY_NONE, &fnum3);
1951
1952         memset(buf, 0, sizeof(buf));
1953
1954         if (cli_write(cli1, fnum1, 0, buf, 0, sizeof(buf)) != sizeof(buf)) {
1955                 printf("Failed to create file\n");
1956                 correct = False;
1957                 goto fail;
1958         }
1959
1960         /* Check for NT bug... */
1961         ret = cli_lock(cli1, fnum1, 0, 8, 0, READ_LOCK) &&
1962                   cli_lock(cli1, fnum3, 0, 1, 0, READ_LOCK);
1963         cli_close(cli1, fnum1);
1964         cli_open(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
1965         ret = cli_lock(cli1, fnum1, 7, 1, 0, WRITE_LOCK);
1966         EXPECTED(ret, True);
1967         printf("this server %s the NT locking bug\n", ret ? "doesn't have" : "has");
1968         cli_close(cli1, fnum1);
1969         cli_open(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
1970         cli_unlock(cli1, fnum3, 0, 1);
1971
1972         ret = cli_lock(cli1, fnum1, 0, 4, 0, WRITE_LOCK) &&
1973               cli_lock(cli1, fnum1, 1, 1, 0, READ_LOCK);
1974         EXPECTED(ret, True);
1975         printf("the same process %s overlay a write with a read lock\n", ret?"can":"cannot");
1976
1977         ret = cli_lock(cli2, fnum2, 0, 4, 0, READ_LOCK);
1978         EXPECTED(ret, False);
1979
1980         printf("a different processs %s get a read lock on the first process lock stack\n", ret?"can":"cannot");
1981
1982         /* Unlock the process 2 lock. */
1983         cli_unlock(cli2, fnum2, 0, 4);
1984
1985         ret = cli_lock(cli1, fnum3, 0, 4, 0, READ_LOCK);
1986         EXPECTED(ret, False);
1987
1988         printf("the same processs on a different fnum %s get a read lock\n", ret?"can":"cannot");
1989
1990         /* Unlock the process 1 fnum3 lock. */
1991         cli_unlock(cli1, fnum3, 0, 4);
1992
1993         /* Stack 2 more locks here. */
1994         ret = cli_lock(cli1, fnum1, 0, 4, 0, READ_LOCK) &&
1995                   cli_lock(cli1, fnum1, 0, 4, 0, READ_LOCK);
1996
1997         EXPECTED(ret, True);
1998         printf("the same process %s stack read locks\n", ret?"can":"cannot");
1999
2000         /* Unlock the first process lock, then check this was the WRITE lock that was
2001                 removed. */
2002
2003         ret = NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 0, 4)) &&
2004                         cli_lock(cli2, fnum2, 0, 4, 0, READ_LOCK);
2005
2006         EXPECTED(ret, True);
2007         printf("the first unlock removes the %s lock\n", ret?"WRITE":"READ");
2008
2009         /* Unlock the process 2 lock. */
2010         cli_unlock(cli2, fnum2, 0, 4);
2011
2012         /* We should have 3 stacked locks here. Ensure we need to do 3 unlocks. */
2013
2014         ret = NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 1, 1)) &&
2015                   NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 0, 4)) &&
2016                   NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 0, 4));
2017
2018         EXPECTED(ret, True);
2019         printf("the same process %s unlock the stack of 4 locks\n", ret?"can":"cannot"); 
2020
2021         /* Ensure the next unlock fails. */
2022         ret = NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 0, 4));
2023         EXPECTED(ret, False);
2024         printf("the same process %s count the lock stack\n", !ret?"can":"cannot"); 
2025
2026         /* Ensure connection 2 can get a write lock. */
2027         ret = cli_lock(cli2, fnum2, 0, 4, 0, WRITE_LOCK);
2028         EXPECTED(ret, True);
2029
2030         printf("a different processs %s get a write lock on the unlocked stack\n", ret?"can":"cannot");
2031
2032
2033  fail:
2034         cli_close(cli1, fnum1);
2035         cli_close(cli2, fnum2);
2036         cli_unlink(cli1, fname, aSYSTEM | aHIDDEN);
2037         if (!torture_close_connection(cli1)) {
2038                 correct = False;
2039         }
2040         if (!torture_close_connection(cli2)) {
2041                 correct = False;
2042         }
2043
2044         printf("finished locktest5\n");
2045
2046         return correct;
2047 }
2048
2049 /*
2050   tries the unusual lockingX locktype bits
2051 */
2052 static bool run_locktest6(int dummy)
2053 {
2054         static struct cli_state *cli;
2055         const char *fname[1] = { "\\lock6.txt" };
2056         int i;
2057         uint16_t fnum;
2058         NTSTATUS status;
2059
2060         if (!torture_open_connection(&cli, 0)) {
2061                 return False;
2062         }
2063
2064         cli_sockopt(cli, sockops);
2065
2066         printf("starting locktest6\n");
2067
2068         for (i=0;i<1;i++) {
2069                 printf("Testing %s\n", fname[i]);
2070
2071                 cli_unlink(cli, fname[i], aSYSTEM | aHIDDEN);
2072
2073                 cli_open(cli, fname[i], O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
2074                 status = cli_locktype(cli, fnum, 0, 8, 0, LOCKING_ANDX_CHANGE_LOCKTYPE);
2075                 cli_close(cli, fnum);
2076                 printf("CHANGE_LOCKTYPE gave %s\n", nt_errstr(status));
2077
2078                 cli_open(cli, fname[i], O_RDWR, DENY_NONE, &fnum);
2079                 status = cli_locktype(cli, fnum, 0, 8, 0, LOCKING_ANDX_CANCEL_LOCK);
2080                 cli_close(cli, fnum);
2081                 printf("CANCEL_LOCK gave %s\n", nt_errstr(status));
2082
2083                 cli_unlink(cli, fname[i], aSYSTEM | aHIDDEN);
2084         }
2085
2086         torture_close_connection(cli);
2087
2088         printf("finished locktest6\n");
2089         return True;
2090 }
2091
2092 static bool run_locktest7(int dummy)
2093 {
2094         struct cli_state *cli1;
2095         const char *fname = "\\lockt7.lck";
2096         uint16_t fnum1;
2097         char buf[200];
2098         bool correct = False;
2099
2100         if (!torture_open_connection(&cli1, 0)) {
2101                 return False;
2102         }
2103
2104         cli_sockopt(cli1, sockops);
2105
2106         printf("starting locktest7\n");
2107
2108         cli_unlink(cli1, fname, aSYSTEM | aHIDDEN);
2109
2110         cli_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
2111
2112         memset(buf, 0, sizeof(buf));
2113
2114         if (cli_write(cli1, fnum1, 0, buf, 0, sizeof(buf)) != sizeof(buf)) {
2115                 printf("Failed to create file\n");
2116                 goto fail;
2117         }
2118
2119         cli_setpid(cli1, 1);
2120
2121         if (!cli_lock(cli1, fnum1, 130, 4, 0, READ_LOCK)) {
2122                 printf("Unable to apply read lock on range 130:4, error was %s\n", cli_errstr(cli1));
2123                 goto fail;
2124         } else {
2125                 printf("pid1 successfully locked range 130:4 for READ\n");
2126         }
2127
2128         if (cli_read(cli1, fnum1, buf, 130, 4) != 4) {
2129                 printf("pid1 unable to read the range 130:4, error was %s\n", cli_errstr(cli1));
2130                 goto fail;
2131         } else {
2132                 printf("pid1 successfully read the range 130:4\n");
2133         }
2134
2135         if (cli_write(cli1, fnum1, 0, buf, 130, 4) != 4) {
2136                 printf("pid1 unable to write to the range 130:4, error was %s\n", cli_errstr(cli1));
2137                 if (NT_STATUS_V(cli_nt_error(cli1)) != NT_STATUS_V(NT_STATUS_FILE_LOCK_CONFLICT)) {
2138                         printf("Incorrect error (should be NT_STATUS_FILE_LOCK_CONFLICT)\n");
2139                         goto fail;
2140                 }
2141         } else {
2142                 printf("pid1 successfully wrote to the range 130:4 (should be denied)\n");
2143                 goto fail;
2144         }
2145
2146         cli_setpid(cli1, 2);
2147
2148         if (cli_read(cli1, fnum1, buf, 130, 4) != 4) {
2149                 printf("pid2 unable to read the range 130:4, error was %s\n", cli_errstr(cli1));
2150         } else {
2151                 printf("pid2 successfully read the range 130:4\n");
2152         }
2153
2154         if (cli_write(cli1, fnum1, 0, buf, 130, 4) != 4) {
2155                 printf("pid2 unable to write to the range 130:4, error was %s\n", cli_errstr(cli1));
2156                 if (NT_STATUS_V(cli_nt_error(cli1)) != NT_STATUS_V(NT_STATUS_FILE_LOCK_CONFLICT)) {
2157                         printf("Incorrect error (should be NT_STATUS_FILE_LOCK_CONFLICT)\n");
2158                         goto fail;
2159                 }
2160         } else {
2161                 printf("pid2 successfully wrote to the range 130:4 (should be denied)\n");
2162                 goto fail;
2163         }
2164
2165         cli_setpid(cli1, 1);
2166         cli_unlock(cli1, fnum1, 130, 4);
2167
2168         if (!cli_lock(cli1, fnum1, 130, 4, 0, WRITE_LOCK)) {
2169                 printf("Unable to apply write lock on range 130:4, error was %s\n", cli_errstr(cli1));
2170                 goto fail;
2171         } else {
2172                 printf("pid1 successfully locked range 130:4 for WRITE\n");
2173         }
2174
2175         if (cli_read(cli1, fnum1, buf, 130, 4) != 4) {
2176                 printf("pid1 unable to read the range 130:4, error was %s\n", cli_errstr(cli1));
2177                 goto fail;
2178         } else {
2179                 printf("pid1 successfully read the range 130:4\n");
2180         }
2181
2182         if (cli_write(cli1, fnum1, 0, buf, 130, 4) != 4) {
2183                 printf("pid1 unable to write to the range 130:4, error was %s\n", cli_errstr(cli1));
2184                 goto fail;
2185         } else {
2186                 printf("pid1 successfully wrote to the range 130:4\n");
2187         }
2188
2189         cli_setpid(cli1, 2);
2190
2191         if (cli_read(cli1, fnum1, buf, 130, 4) != 4) {
2192                 printf("pid2 unable to read the range 130:4, error was %s\n", cli_errstr(cli1));
2193                 if (NT_STATUS_V(cli_nt_error(cli1)) != NT_STATUS_V(NT_STATUS_FILE_LOCK_CONFLICT)) {
2194                         printf("Incorrect error (should be NT_STATUS_FILE_LOCK_CONFLICT)\n");
2195                         goto fail;
2196                 }
2197         } else {
2198                 printf("pid2 successfully read the range 130:4 (should be denied)\n");
2199                 goto fail;
2200         }
2201
2202         if (cli_write(cli1, fnum1, 0, buf, 130, 4) != 4) {
2203                 printf("pid2 unable to write to the range 130:4, error was %s\n", cli_errstr(cli1));
2204                 if (NT_STATUS_V(cli_nt_error(cli1)) != NT_STATUS_V(NT_STATUS_FILE_LOCK_CONFLICT)) {
2205                         printf("Incorrect error (should be NT_STATUS_FILE_LOCK_CONFLICT)\n");
2206                         goto fail;
2207                 }
2208         } else {
2209                 printf("pid2 successfully wrote to the range 130:4 (should be denied)\n");
2210                 goto fail;
2211         }
2212
2213         cli_unlock(cli1, fnum1, 130, 0);
2214         correct = True;
2215
2216 fail:
2217         cli_close(cli1, fnum1);
2218         cli_unlink(cli1, fname, aSYSTEM | aHIDDEN);
2219         torture_close_connection(cli1);
2220
2221         printf("finished locktest7\n");
2222         return correct;
2223 }
2224
2225 /*
2226  * This demonstrates a problem with our use of GPFS share modes: A file
2227  * descriptor sitting in the pending close queue holding a GPFS share mode
2228  * blocks opening a file another time. Happens with Word 2007 temp files.
2229  * With "posix locking = yes" and "gpfs:sharemodes = yes" enabled, the third
2230  * open is denied with NT_STATUS_SHARING_VIOLATION.
2231  */
2232
2233 static bool run_locktest8(int dummy)
2234 {
2235         struct cli_state *cli1;
2236         const char *fname = "\\lockt8.lck";
2237         uint16_t fnum1, fnum2;
2238         char buf[200];
2239         bool correct = False;
2240         NTSTATUS status;
2241
2242         if (!torture_open_connection(&cli1, 0)) {
2243                 return False;
2244         }
2245
2246         cli_sockopt(cli1, sockops);
2247
2248         printf("starting locktest8\n");
2249
2250         cli_unlink(cli1, fname, aSYSTEM | aHIDDEN);
2251
2252         status = cli_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_WRITE,
2253                           &fnum1);
2254         if (!NT_STATUS_IS_OK(status)) {
2255                 d_fprintf(stderr, "cli_open returned %s\n", cli_errstr(cli1));
2256                 return false;
2257         }
2258
2259         memset(buf, 0, sizeof(buf));
2260
2261         status = cli_open(cli1, fname, O_RDONLY, DENY_NONE, &fnum2);
2262         if (!NT_STATUS_IS_OK(status)) {
2263                 d_fprintf(stderr, "cli_open second time returned %s\n",
2264                           cli_errstr(cli1));
2265                 goto fail;
2266         }
2267
2268         if (!cli_lock(cli1, fnum2, 1, 1, 0, READ_LOCK)) {
2269                 printf("Unable to apply read lock on range 1:1, error was "
2270                        "%s\n", cli_errstr(cli1));
2271                 goto fail;
2272         }
2273
2274         status = cli_close(cli1, fnum1);
2275         if (!NT_STATUS_IS_OK(status)) {
2276                 d_fprintf(stderr, "cli_close(fnum1) %s\n", cli_errstr(cli1));
2277                 goto fail;
2278         }
2279
2280         status = cli_open(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
2281         if (!NT_STATUS_IS_OK(status)) {
2282                 d_fprintf(stderr, "cli_open third time returned %s\n",
2283                           cli_errstr(cli1));
2284                 goto fail;
2285         }
2286
2287         correct = true;
2288
2289 fail:
2290         cli_close(cli1, fnum1);
2291         cli_close(cli1, fnum2);
2292         cli_unlink(cli1, fname, aSYSTEM | aHIDDEN);
2293         torture_close_connection(cli1);
2294
2295         printf("finished locktest8\n");
2296         return correct;
2297 }
2298
2299 /*
2300  * This test is designed to be run in conjunction with
2301  * external NFS or POSIX locks taken in the filesystem.
2302  * It checks that the smbd server will block until the
2303  * lock is released and then acquire it. JRA.
2304  */
2305
2306 static bool got_alarm;
2307 static int alarm_fd;
2308
2309 static void alarm_handler(int dummy)
2310 {
2311         got_alarm = True;
2312 }
2313
2314 static void alarm_handler_parent(int dummy)
2315 {
2316         close(alarm_fd);
2317 }
2318
2319 static void do_local_lock(int read_fd, int write_fd)
2320 {
2321         int fd;
2322         char c = '\0';
2323         struct flock lock;
2324         const char *local_pathname = NULL;
2325         int ret;
2326
2327         local_pathname = talloc_asprintf(talloc_tos(),
2328                         "%s/lockt9.lck", local_path);
2329         if (!local_pathname) {
2330                 printf("child: alloc fail\n");
2331                 exit(1);
2332         }
2333
2334         unlink(local_pathname);
2335         fd = open(local_pathname, O_RDWR|O_CREAT, 0666);
2336         if (fd == -1) {
2337                 printf("child: open of %s failed %s.\n",
2338                         local_pathname, strerror(errno));
2339                 exit(1);
2340         }
2341
2342         /* Now take a fcntl lock. */
2343         lock.l_type = F_WRLCK;
2344         lock.l_whence = SEEK_SET;
2345         lock.l_start = 0;
2346         lock.l_len = 4;
2347         lock.l_pid = getpid();
2348
2349         ret = fcntl(fd,F_SETLK,&lock);
2350         if (ret == -1) {
2351                 printf("child: failed to get lock 0:4 on file %s. Error %s\n",
2352                         local_pathname, strerror(errno));
2353                 exit(1);
2354         } else {
2355                 printf("child: got lock 0:4 on file %s.\n",
2356                         local_pathname );
2357                 fflush(stdout);
2358         }
2359
2360         CatchSignal(SIGALRM, alarm_handler);
2361         alarm(5);
2362         /* Signal the parent. */
2363         if (write(write_fd, &c, 1) != 1) {
2364                 printf("child: start signal fail %s.\n",
2365                         strerror(errno));
2366                 exit(1);
2367         }
2368         alarm(0);
2369
2370         alarm(10);
2371         /* Wait for the parent to be ready. */
2372         if (read(read_fd, &c, 1) != 1) {
2373                 printf("child: reply signal fail %s.\n",
2374                         strerror(errno));
2375                 exit(1);
2376         }
2377         alarm(0);
2378
2379         sleep(5);
2380         close(fd);
2381         printf("child: released lock 0:4 on file %s.\n",
2382                 local_pathname );
2383         fflush(stdout);
2384         exit(0);
2385 }
2386
2387 static bool run_locktest9(int dummy)
2388 {
2389         struct cli_state *cli1;
2390         const char *fname = "\\lockt9.lck";
2391         uint16_t fnum;
2392         bool correct = False;
2393         int pipe_in[2], pipe_out[2];
2394         pid_t child_pid;
2395         char c = '\0';
2396         int ret;
2397         struct timeval start;
2398         double seconds;
2399         NTSTATUS status;
2400
2401         printf("starting locktest9\n");
2402
2403         if (local_path == NULL) {
2404                 d_fprintf(stderr, "locktest9 must be given a local path via -l <localpath>\n");
2405                 return false;
2406         }
2407
2408         if (pipe(pipe_in) == -1 || pipe(pipe_out) == -1) {
2409                 return false;
2410         }
2411
2412         child_pid = fork();
2413         if (child_pid == -1) {
2414                 return false;
2415         }
2416
2417         if (child_pid == 0) {
2418                 /* Child. */
2419                 do_local_lock(pipe_out[0], pipe_in[1]);
2420                 exit(0);
2421         }
2422
2423         close(pipe_out[0]);
2424         close(pipe_in[1]);
2425         pipe_out[0] = -1;
2426         pipe_in[1] = -1;
2427
2428         /* Parent. */
2429         ret = read(pipe_in[0], &c, 1);
2430         if (ret != 1) {
2431                 d_fprintf(stderr, "failed to read start signal from child. %s\n",
2432                         strerror(errno));
2433                 return false;
2434         }
2435
2436         if (!torture_open_connection(&cli1, 0)) {
2437                 return false;
2438         }
2439
2440         cli_sockopt(cli1, sockops);
2441
2442         status = cli_open(cli1, fname, O_RDWR, DENY_NONE,
2443                           &fnum);
2444         if (!NT_STATUS_IS_OK(status)) {
2445                 d_fprintf(stderr, "cli_open returned %s\n", cli_errstr(cli1));
2446                 return false;
2447         }
2448
2449         /* Ensure the child has the lock. */
2450         if (cli_lock(cli1, fnum, 0, 4, 0, WRITE_LOCK)) {
2451                 d_fprintf(stderr, "Got the lock on range 0:4 - this should not happen !\n");
2452                 goto fail;
2453         } else {
2454                 d_printf("Child has the lock.\n");
2455         }
2456
2457         /* Tell the child to wait 5 seconds then exit. */
2458         ret = write(pipe_out[1], &c, 1);
2459         if (ret != 1) {
2460                 d_fprintf(stderr, "failed to send exit signal to child. %s\n",
2461                         strerror(errno));
2462                 goto fail;
2463         }
2464
2465         /* Wait 20 seconds for the lock. */
2466         alarm_fd = cli1->fd;
2467         CatchSignal(SIGALRM, alarm_handler_parent);
2468         alarm(20);
2469
2470         start = timeval_current();
2471
2472         if (!cli_lock(cli1, fnum, 0, 4, -1, WRITE_LOCK)) {
2473                 d_fprintf(stderr, "Unable to apply write lock on range 0:4, error was "
2474                        "%s\n", cli_errstr(cli1));
2475                 goto fail_nofd;
2476         }
2477         alarm(0);
2478
2479         seconds = timeval_elapsed(&start);
2480
2481         printf("Parent got the lock after %.2f seconds.\n",
2482                 seconds);
2483
2484         status = cli_close(cli1, fnum);
2485         if (!NT_STATUS_IS_OK(status)) {
2486                 d_fprintf(stderr, "cli_close(fnum1) %s\n", cli_errstr(cli1));
2487                 goto fail;
2488         }
2489
2490         correct = true;
2491
2492 fail:
2493         cli_close(cli1, fnum);
2494         torture_close_connection(cli1);
2495
2496 fail_nofd:
2497
2498         printf("finished locktest9\n");
2499         return correct;
2500 }
2501
2502 /*
2503 test whether fnums and tids open on one VC are available on another (a major
2504 security hole)
2505 */
2506 static bool run_fdpasstest(int dummy)
2507 {
2508         struct cli_state *cli1, *cli2;
2509         const char *fname = "\\fdpass.tst";
2510         uint16_t fnum1;
2511         char buf[1024];
2512
2513         if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
2514                 return False;
2515         }
2516         cli_sockopt(cli1, sockops);
2517         cli_sockopt(cli2, sockops);
2518
2519         printf("starting fdpasstest\n");
2520
2521         cli_unlink(cli1, fname, aSYSTEM | aHIDDEN);
2522
2523         if (!NT_STATUS_IS_OK(cli_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1))) {
2524                 printf("open of %s failed (%s)\n", fname, cli_errstr(cli1));
2525                 return False;
2526         }
2527
2528         if (cli_write(cli1, fnum1, 0, "hello world\n", 0, 13) != 13) {
2529                 printf("write failed (%s)\n", cli_errstr(cli1));
2530                 return False;
2531         }
2532
2533         cli2->vuid = cli1->vuid;
2534         cli2->cnum = cli1->cnum;
2535         cli2->pid = cli1->pid;
2536
2537         if (cli_read(cli2, fnum1, buf, 0, 13) == 13) {
2538                 printf("read succeeded! nasty security hole [%s]\n",
2539                        buf);
2540                 return False;
2541         }
2542
2543         cli_close(cli1, fnum1);
2544         cli_unlink(cli1, fname, aSYSTEM | aHIDDEN);
2545
2546         torture_close_connection(cli1);
2547         torture_close_connection(cli2);
2548
2549         printf("finished fdpasstest\n");
2550         return True;
2551 }
2552
2553 static bool run_fdsesstest(int dummy)
2554 {
2555         struct cli_state *cli;
2556         uint16 new_vuid;
2557         uint16 saved_vuid;
2558         uint16 new_cnum;
2559         uint16 saved_cnum;
2560         const char *fname = "\\fdsess.tst";
2561         const char *fname1 = "\\fdsess1.tst";
2562         uint16_t fnum1;
2563         uint16_t fnum2;
2564         char buf[1024];
2565         bool ret = True;
2566
2567         if (!torture_open_connection(&cli, 0))
2568                 return False;
2569         cli_sockopt(cli, sockops);
2570
2571         if (!torture_cli_session_setup2(cli, &new_vuid))
2572                 return False;
2573
2574         saved_cnum = cli->cnum;
2575         if (!NT_STATUS_IS_OK(cli_tcon_andx(cli, share, "?????", "", 1)))
2576                 return False;
2577         new_cnum = cli->cnum;
2578         cli->cnum = saved_cnum;
2579
2580         printf("starting fdsesstest\n");
2581
2582         cli_unlink(cli, fname, aSYSTEM | aHIDDEN);
2583         cli_unlink(cli, fname1, aSYSTEM | aHIDDEN);
2584
2585         if (!NT_STATUS_IS_OK(cli_open(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1))) {
2586                 printf("open of %s failed (%s)\n", fname, cli_errstr(cli));
2587                 return False;
2588         }
2589
2590         if (cli_write(cli, fnum1, 0, "hello world\n", 0, 13) != 13) {
2591                 printf("write failed (%s)\n", cli_errstr(cli));
2592                 return False;
2593         }
2594
2595         saved_vuid = cli->vuid;
2596         cli->vuid = new_vuid;
2597
2598         if (cli_read(cli, fnum1, buf, 0, 13) == 13) {
2599                 printf("read succeeded with different vuid! nasty security hole [%s]\n",
2600                        buf);
2601                 ret = False;
2602         }
2603         /* Try to open a file with different vuid, samba cnum. */
2604         if (NT_STATUS_IS_OK(cli_open(cli, fname1, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum2))) {
2605                 printf("create with different vuid, same cnum succeeded.\n");
2606                 cli_close(cli, fnum2);
2607                 cli_unlink(cli, fname1, aSYSTEM | aHIDDEN);
2608         } else {
2609                 printf("create with different vuid, same cnum failed.\n");
2610                 printf("This will cause problems with service clients.\n");
2611                 ret = False;
2612         }
2613
2614         cli->vuid = saved_vuid;
2615
2616         /* Try with same vuid, different cnum. */
2617         cli->cnum = new_cnum;
2618
2619         if (cli_read(cli, fnum1, buf, 0, 13) == 13) {
2620                 printf("read succeeded with different cnum![%s]\n",
2621                        buf);
2622                 ret = False;
2623         }
2624
2625         cli->cnum = saved_cnum;
2626         cli_close(cli, fnum1);
2627         cli_unlink(cli, fname, aSYSTEM | aHIDDEN);
2628
2629         torture_close_connection(cli);
2630
2631         printf("finished fdsesstest\n");
2632         return ret;
2633 }
2634
2635 /*
2636   This test checks that 
2637
2638   1) the server does not allow an unlink on a file that is open
2639 */
2640 static bool run_unlinktest(int dummy)
2641 {
2642         struct cli_state *cli;
2643         const char *fname = "\\unlink.tst";
2644         uint16_t fnum;
2645         bool correct = True;
2646
2647         if (!torture_open_connection(&cli, 0)) {
2648                 return False;
2649         }
2650
2651         cli_sockopt(cli, sockops);
2652
2653         printf("starting unlink test\n");
2654
2655         cli_unlink(cli, fname, aSYSTEM | aHIDDEN);
2656
2657         cli_setpid(cli, 1);
2658
2659         if (!NT_STATUS_IS_OK(cli_open(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum))) {
2660                 printf("open of %s failed (%s)\n", fname, cli_errstr(cli));
2661                 return False;
2662         }
2663
2664         if (NT_STATUS_IS_OK(cli_unlink(cli, fname, aSYSTEM | aHIDDEN))) {
2665                 printf("error: server allowed unlink on an open file\n");
2666                 correct = False;
2667         } else {
2668                 correct = check_error(__LINE__, cli, ERRDOS, ERRbadshare, 
2669                                       NT_STATUS_SHARING_VIOLATION);
2670         }
2671
2672         cli_close(cli, fnum);
2673         cli_unlink(cli, fname, aSYSTEM | aHIDDEN);
2674
2675         if (!torture_close_connection(cli)) {
2676                 correct = False;
2677         }
2678
2679         printf("unlink test finished\n");
2680
2681         return correct;
2682 }
2683
2684
2685 /*
2686 test how many open files this server supports on the one socket
2687 */
2688 static bool run_maxfidtest(int dummy)
2689 {
2690         struct cli_state *cli;
2691         const char *ftemplate = "\\maxfid.%d.%d";
2692         fstring fname;
2693         uint16_t fnums[0x11000];
2694         int i;
2695         int retries=4;
2696         bool correct = True;
2697
2698         cli = current_cli;
2699
2700         if (retries <= 0) {
2701                 printf("failed to connect\n");
2702                 return False;
2703         }
2704
2705         cli_sockopt(cli, sockops);
2706
2707         for (i=0; i<0x11000; i++) {
2708                 slprintf(fname,sizeof(fname)-1,ftemplate, i,(int)getpid());
2709                 if (!NT_STATUS_IS_OK(cli_open(cli, fname, 
2710                                         O_RDWR|O_CREAT|O_TRUNC, DENY_NONE, &fnums[i]))) {
2711                         printf("open of %s failed (%s)\n", 
2712                                fname, cli_errstr(cli));
2713                         printf("maximum fnum is %d\n", i);
2714                         break;
2715                 }
2716                 printf("%6d\r", i);
2717         }
2718         printf("%6d\n", i);
2719         i--;
2720
2721         printf("cleaning up\n");
2722         for (;i>=0;i--) {
2723                 slprintf(fname,sizeof(fname)-1,ftemplate, i,(int)getpid());
2724                 cli_close(cli, fnums[i]);
2725                 if (!NT_STATUS_IS_OK(cli_unlink(cli, fname, aSYSTEM | aHIDDEN))) {
2726                         printf("unlink of %s failed (%s)\n", 
2727                                fname, cli_errstr(cli));
2728                         correct = False;
2729                 }
2730                 printf("%6d\r", i);
2731         }
2732         printf("%6d\n", 0);
2733
2734         printf("maxfid test finished\n");
2735         if (!torture_close_connection(cli)) {
2736                 correct = False;
2737         }
2738         return correct;
2739 }
2740
2741 /* generate a random buffer */
2742 static void rand_buf(char *buf, int len)
2743 {
2744         while (len--) {
2745                 *buf = (char)sys_random();
2746                 buf++;
2747         }
2748 }
2749
2750 /* send smb negprot commands, not reading the response */
2751 static bool run_negprot_nowait(int dummy)
2752 {
2753         int i;
2754         static struct cli_state *cli;
2755         bool correct = True;
2756
2757         printf("starting negprot nowait test\n");
2758
2759         if (!(cli = open_nbt_connection())) {
2760                 return False;
2761         }
2762
2763         for (i=0;i<50000;i++) {
2764                 cli_negprot_sendsync(cli);
2765         }
2766
2767         if (!torture_close_connection(cli)) {
2768                 correct = False;
2769         }
2770
2771         printf("finished negprot nowait test\n");
2772
2773         return correct;
2774 }
2775
2776 /* send smb negprot commands, not reading the response */
2777 static bool run_bad_nbt_session(int dummy)
2778 {
2779         static struct cli_state *cli;
2780
2781         printf("starting bad nbt session test\n");
2782
2783         if (!(cli = open_bad_nbt_connection())) {
2784                 return False;
2785         }
2786
2787         cli_shutdown(cli);
2788         printf("finished bad nbt session test\n");
2789         return true;
2790 }
2791
2792 /* send random IPC commands */
2793 static bool run_randomipc(int dummy)
2794 {
2795         char *rparam = NULL;
2796         char *rdata = NULL;
2797         unsigned int rdrcnt,rprcnt;
2798         char param[1024];
2799         int api, param_len, i;
2800         struct cli_state *cli;
2801         bool correct = True;
2802         int count = 50000;
2803
2804         printf("starting random ipc test\n");
2805
2806         if (!torture_open_connection(&cli, 0)) {
2807                 return False;
2808         }
2809
2810         for (i=0;i<count;i++) {
2811                 api = sys_random() % 500;
2812                 param_len = (sys_random() % 64);
2813
2814                 rand_buf(param, param_len);
2815
2816                 SSVAL(param,0,api); 
2817
2818                 cli_api(cli, 
2819                         param, param_len, 8,  
2820                         NULL, 0, BUFFER_SIZE, 
2821                         &rparam, &rprcnt,     
2822                         &rdata, &rdrcnt);
2823                 if (i % 100 == 0) {
2824                         printf("%d/%d\r", i,count);
2825                 }
2826         }
2827         printf("%d/%d\n", i, count);
2828
2829         if (!torture_close_connection(cli)) {
2830                 correct = False;
2831         }
2832
2833         printf("finished random ipc test\n");
2834
2835         return correct;
2836 }
2837
2838
2839
2840 static void browse_callback(const char *sname, uint32 stype, 
2841                             const char *comment, void *state)
2842 {
2843         printf("\t%20.20s %08x %s\n", sname, stype, comment);
2844 }
2845
2846
2847
2848 /*
2849   This test checks the browse list code
2850
2851 */
2852 static bool run_browsetest(int dummy)
2853 {
2854         static struct cli_state *cli;
2855         bool correct = True;
2856
2857         printf("starting browse test\n");
2858
2859         if (!torture_open_connection(&cli, 0)) {
2860                 return False;
2861         }
2862
2863         printf("domain list:\n");
2864         cli_NetServerEnum(cli, cli->server_domain, 
2865                           SV_TYPE_DOMAIN_ENUM,
2866                           browse_callback, NULL);
2867
2868         printf("machine list:\n");
2869         cli_NetServerEnum(cli, cli->server_domain, 
2870                           SV_TYPE_ALL,
2871                           browse_callback, NULL);
2872
2873         if (!torture_close_connection(cli)) {
2874                 correct = False;
2875         }
2876
2877         printf("browse test finished\n");
2878
2879         return correct;
2880
2881 }
2882
2883
2884 /*
2885   This checks how the getatr calls works
2886 */
2887 static bool run_attrtest(int dummy)
2888 {
2889         struct cli_state *cli;
2890         uint16_t fnum;
2891         time_t t, t2;
2892         const char *fname = "\\attrib123456789.tst";
2893         bool correct = True;
2894
2895         printf("starting attrib test\n");
2896
2897         if (!torture_open_connection(&cli, 0)) {
2898                 return False;
2899         }
2900
2901         cli_unlink(cli, fname, aSYSTEM | aHIDDEN);
2902         cli_open(cli, fname, 
2903                         O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum);
2904         cli_close(cli, fnum);
2905         if (!NT_STATUS_IS_OK(cli_getatr(cli, fname, NULL, NULL, &t))) {
2906                 printf("getatr failed (%s)\n", cli_errstr(cli));
2907                 correct = False;
2908         }
2909
2910         if (abs(t - time(NULL)) > 60*60*24*10) {
2911                 printf("ERROR: SMBgetatr bug. time is %s",
2912                        ctime(&t));
2913                 t = time(NULL);
2914                 correct = True;
2915         }
2916
2917         t2 = t-60*60*24; /* 1 day ago */
2918
2919         if (!NT_STATUS_IS_OK(cli_setatr(cli, fname, 0, t2))) {
2920                 printf("setatr failed (%s)\n", cli_errstr(cli));
2921                 correct = True;
2922         }
2923
2924         if (!NT_STATUS_IS_OK(cli_getatr(cli, fname, NULL, NULL, &t))) {
2925                 printf("getatr failed (%s)\n", cli_errstr(cli));
2926                 correct = True;
2927         }
2928
2929         if (t != t2) {
2930                 printf("ERROR: getatr/setatr bug. times are\n%s",
2931                        ctime(&t));
2932                 printf("%s", ctime(&t2));
2933                 correct = True;
2934         }
2935
2936         cli_unlink(cli, fname, aSYSTEM | aHIDDEN);
2937
2938         if (!torture_close_connection(cli)) {
2939                 correct = False;
2940         }
2941
2942         printf("attrib test finished\n");
2943
2944         return correct;
2945 }
2946
2947
2948 /*
2949   This checks a couple of trans2 calls
2950 */
2951 static bool run_trans2test(int dummy)
2952 {
2953         struct cli_state *cli;
2954         uint16_t fnum;
2955         SMB_OFF_T size;
2956         time_t c_time, a_time, m_time;
2957         struct timespec c_time_ts, a_time_ts, m_time_ts, w_time_ts, m_time2_ts;
2958         const char *fname = "\\trans2.tst";
2959         const char *dname = "\\trans2";
2960         const char *fname2 = "\\trans2\\trans2.tst";
2961         char pname[1024];
2962         bool correct = True;
2963         NTSTATUS status;
2964         uint32_t fs_attr;
2965
2966         printf("starting trans2 test\n");
2967
2968         if (!torture_open_connection(&cli, 0)) {
2969                 return False;
2970         }
2971
2972         status = cli_get_fs_attr_info(cli, &fs_attr);
2973         if (!NT_STATUS_IS_OK(status)) {
2974                 printf("ERROR: cli_get_fs_attr_info returned %s\n",
2975                        nt_errstr(status));
2976                 correct = false;
2977         }
2978
2979         cli_unlink(cli, fname, aSYSTEM | aHIDDEN);
2980         cli_open(cli, fname, 
2981                         O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum);
2982         if (!NT_STATUS_IS_OK(cli_qfileinfo_basic(
2983                                      cli, fnum, NULL, &size, &c_time_ts,
2984                                      &a_time_ts, &w_time_ts,
2985                                      &m_time_ts, NULL))) {
2986                 printf("ERROR: qfileinfo failed (%s)\n", cli_errstr(cli));
2987                 correct = False;
2988         }
2989
2990         if (!NT_STATUS_IS_OK(cli_qfilename(cli, fnum, pname, sizeof(pname)))) {
2991                 printf("ERROR: qfilename failed (%s)\n", cli_errstr(cli));
2992                 correct = False;
2993         }
2994
2995         if (strcmp(pname, fname)) {
2996                 printf("qfilename gave different name? [%s] [%s]\n",
2997                        fname, pname);
2998                 correct = False;
2999         }
3000
3001         cli_close(cli, fnum);
3002
3003         sleep(2);
3004
3005         cli_unlink(cli, fname, aSYSTEM | aHIDDEN);
3006         if (!NT_STATUS_IS_OK(cli_open(cli, fname, 
3007                         O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum))) {
3008                 printf("open of %s failed (%s)\n", fname, cli_errstr(cli));
3009                 return False;
3010         }
3011         cli_close(cli, fnum);
3012
3013         status = cli_qpathinfo1(cli, fname, &c_time, &a_time, &m_time, &size,
3014                                 NULL);
3015         if (!NT_STATUS_IS_OK(status)) {
3016                 printf("ERROR: qpathinfo failed (%s)\n", nt_errstr(status));
3017                 correct = False;
3018         } else {
3019                 if (c_time != m_time) {
3020                         printf("create time=%s", ctime(&c_time));
3021                         printf("modify time=%s", ctime(&m_time));
3022                         printf("This system appears to have sticky create times\n");
3023                 }
3024                 if (a_time % (60*60) == 0) {
3025                         printf("access time=%s", ctime(&a_time));
3026                         printf("This system appears to set a midnight access time\n");
3027                         correct = False;
3028                 }
3029
3030                 if (abs(m_time - time(NULL)) > 60*60*24*7) {
3031                         printf("ERROR: totally incorrect times - maybe word reversed? mtime=%s", ctime(&m_time));
3032                         correct = False;
3033                 }
3034         }
3035
3036
3037         cli_unlink(cli, fname, aSYSTEM | aHIDDEN);
3038         cli_open(cli, fname, 
3039                         O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum);
3040         cli_close(cli, fnum);
3041         status = cli_qpathinfo2(cli, fname, &c_time_ts, &a_time_ts, &w_time_ts,
3042                                 &m_time_ts, &size, NULL, NULL);
3043         if (!NT_STATUS_IS_OK(status)) {
3044                 printf("ERROR: qpathinfo2 failed (%s)\n", nt_errstr(status));
3045                 correct = False;
3046         } else {
3047                 if (w_time_ts.tv_sec < 60*60*24*2) {
3048                         printf("write time=%s", ctime(&w_time_ts.tv_sec));
3049                         printf("This system appears to set a initial 0 write time\n");
3050                         correct = False;
3051                 }
3052         }
3053
3054         cli_unlink(cli, fname, aSYSTEM | aHIDDEN);
3055
3056
3057         /* check if the server updates the directory modification time
3058            when creating a new file */
3059         if (!NT_STATUS_IS_OK(cli_mkdir(cli, dname))) {
3060                 printf("ERROR: mkdir failed (%s)\n", cli_errstr(cli));
3061                 correct = False;
3062         }
3063         sleep(3);
3064         status = cli_qpathinfo2(cli, "\\trans2\\", &c_time_ts, &a_time_ts,
3065                                 &w_time_ts, &m_time_ts, &size, NULL, NULL);
3066         if (!NT_STATUS_IS_OK(status)) {
3067                 printf("ERROR: qpathinfo2 failed (%s)\n", nt_errstr(status));
3068                 correct = False;
3069         }
3070
3071         cli_open(cli, fname2, 
3072                         O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum);
3073         cli_write(cli, fnum,  0, (char *)&fnum, 0, sizeof(fnum));
3074         cli_close(cli, fnum);
3075         status = cli_qpathinfo2(cli, "\\trans2\\", &c_time_ts, &a_time_ts,
3076                                 &w_time_ts, &m_time2_ts, &size, NULL, NULL);
3077         if (!NT_STATUS_IS_OK(status)) {
3078                 printf("ERROR: qpathinfo2 failed (%s)\n", nt_errstr(status));
3079                 correct = False;
3080         } else {
3081                 if (memcmp(&m_time_ts, &m_time2_ts, sizeof(struct timespec))
3082                     == 0) {
3083                         printf("This system does not update directory modification times\n");
3084                         correct = False;
3085                 }
3086         }
3087         cli_unlink(cli, fname2, aSYSTEM | aHIDDEN);
3088         cli_rmdir(cli, dname);
3089
3090         if (!torture_close_connection(cli)) {
3091                 correct = False;
3092         }
3093
3094         printf("trans2 test finished\n");
3095
3096         return correct;
3097 }
3098
3099 /*
3100   This checks new W2K calls.
3101 */
3102
3103 static NTSTATUS new_trans(struct cli_state *pcli, int fnum, int level)
3104 {
3105         uint8_t *buf = NULL;
3106         uint32 len;
3107         NTSTATUS status;
3108
3109         status = cli_qfileinfo(talloc_tos(), pcli, fnum, level, 0,
3110                                pcli->max_xmit, &buf, &len);
3111         if (!NT_STATUS_IS_OK(status)) {
3112                 printf("ERROR: qfileinfo (%d) failed (%s)\n", level,
3113                        nt_errstr(status));
3114         } else {
3115                 printf("qfileinfo: level %d, len = %u\n", level, len);
3116                 dump_data(0, (uint8 *)buf, len);
3117                 printf("\n");
3118         }
3119         TALLOC_FREE(buf);
3120         return status;
3121 }
3122
3123 static bool run_w2ktest(int dummy)
3124 {
3125         struct cli_state *cli;
3126         uint16_t fnum;
3127         const char *fname = "\\w2ktest\\w2k.tst";
3128         int level;
3129         bool correct = True;
3130
3131         printf("starting w2k test\n");
3132
3133         if (!torture_open_connection(&cli, 0)) {
3134                 return False;
3135         }
3136
3137         cli_open(cli, fname, 
3138                         O_RDWR | O_CREAT , DENY_NONE, &fnum);
3139
3140         for (level = 1004; level < 1040; level++) {
3141                 new_trans(cli, fnum, level);
3142         }
3143
3144         cli_close(cli, fnum);
3145
3146         if (!torture_close_connection(cli)) {
3147                 correct = False;
3148         }
3149
3150         printf("w2k test finished\n");
3151
3152         return correct;
3153 }
3154
3155
3156 /*
3157   this is a harness for some oplock tests
3158  */
3159 static bool run_oplock1(int dummy)
3160 {
3161         struct cli_state *cli1;
3162         const char *fname = "\\lockt1.lck";
3163         uint16_t fnum1;
3164         bool correct = True;
3165
3166         printf("starting oplock test 1\n");
3167
3168         if (!torture_open_connection(&cli1, 0)) {
3169                 return False;
3170         }
3171
3172         cli_unlink(cli1, fname, aSYSTEM | aHIDDEN);
3173
3174         cli_sockopt(cli1, sockops);
3175
3176         cli1->use_oplocks = True;
3177
3178         if (!NT_STATUS_IS_OK(cli_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1))) {
3179                 printf("open of %s failed (%s)\n", fname, cli_errstr(cli1));
3180                 return False;
3181         }
3182
3183         cli1->use_oplocks = False;
3184
3185         cli_unlink(cli1, fname, aSYSTEM | aHIDDEN);
3186         cli_unlink(cli1, fname, aSYSTEM | aHIDDEN);
3187
3188         if (!NT_STATUS_IS_OK(cli_close(cli1, fnum1))) {
3189                 printf("close2 failed (%s)\n", cli_errstr(cli1));
3190                 return False;
3191         }
3192
3193         if (!NT_STATUS_IS_OK(cli_unlink(cli1, fname, aSYSTEM | aHIDDEN))) {
3194                 printf("unlink failed (%s)\n", cli_errstr(cli1));
3195                 return False;
3196         }
3197
3198         if (!torture_close_connection(cli1)) {
3199                 correct = False;
3200         }
3201
3202         printf("finished oplock test 1\n");
3203
3204         return correct;
3205 }
3206
3207 static bool run_oplock2(int dummy)
3208 {
3209         struct cli_state *cli1, *cli2;
3210         const char *fname = "\\lockt2.lck";
3211         uint16_t fnum1, fnum2;
3212         int saved_use_oplocks = use_oplocks;
3213         char buf[4];
3214         bool correct = True;
3215         volatile bool *shared_correct;
3216
3217         shared_correct = (volatile bool *)shm_setup(sizeof(bool));
3218         *shared_correct = True;
3219
3220         use_level_II_oplocks = True;
3221         use_oplocks = True;
3222
3223         printf("starting oplock test 2\n");
3224
3225         if (!torture_open_connection(&cli1, 0)) {
3226                 use_level_II_oplocks = False;
3227                 use_oplocks = saved_use_oplocks;
3228                 return False;
3229         }
3230
3231         cli1->use_oplocks = True;
3232         cli1->use_level_II_oplocks = True;
3233
3234         if (!torture_open_connection(&cli2, 1)) {
3235                 use_level_II_oplocks = False;
3236                 use_oplocks = saved_use_oplocks;
3237                 return False;
3238         }
3239
3240         cli2->use_oplocks = True;
3241         cli2->use_level_II_oplocks = True;
3242
3243         cli_unlink(cli1, fname, aSYSTEM | aHIDDEN);
3244
3245         cli_sockopt(cli1, sockops);
3246         cli_sockopt(cli2, sockops);
3247
3248         if (!NT_STATUS_IS_OK(cli_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1))) {
3249                 printf("open of %s failed (%s)\n", fname, cli_errstr(cli1));
3250                 return False;
3251         }
3252
3253         /* Don't need the globals any more. */
3254         use_level_II_oplocks = False;
3255         use_oplocks = saved_use_oplocks;
3256
3257         if (fork() == 0) {
3258                 /* Child code */
3259                 if (!NT_STATUS_IS_OK(cli_open(cli2, fname, O_RDWR, DENY_NONE, &fnum2))) {
3260                         printf("second open of %s failed (%s)\n", fname, cli_errstr(cli1));
3261                         *shared_correct = False;
3262                         exit(0);
3263                 }
3264
3265                 sleep(2);
3266
3267                 if (!NT_STATUS_IS_OK(cli_close(cli2, fnum2))) {
3268                         printf("close2 failed (%s)\n", cli_errstr(cli1));
3269                         *shared_correct = False;
3270                 }
3271
3272                 exit(0);
3273         }
3274
3275         sleep(2);
3276
3277         /* Ensure cli1 processes the break. Empty file should always return 0
3278          * bytes.  */
3279
3280         if (cli_read(cli1, fnum1, buf, 0, 4) != 0) {
3281                 printf("read on fnum1 failed (%s)\n", cli_errstr(cli1));
3282                 correct = False;
3283         }
3284
3285         /* Should now be at level II. */
3286         /* Test if sending a write locks causes a break to none. */
3287
3288         if (!cli_lock(cli1, fnum1, 0, 4, 0, READ_LOCK)) {
3289                 printf("lock failed (%s)\n", cli_errstr(cli1));
3290                 correct = False;
3291         }
3292
3293         cli_unlock(cli1, fnum1, 0, 4);
3294
3295         sleep(2);
3296
3297         if (!cli_lock(cli1, fnum1, 0, 4, 0, WRITE_LOCK)) {
3298                 printf("lock failed (%s)\n", cli_errstr(cli1));
3299                 correct = False;
3300         }
3301
3302         cli_unlock(cli1, fnum1, 0, 4);
3303
3304         sleep(2);
3305
3306         cli_read(cli1, fnum1, buf, 0, 4);
3307
3308 #if 0
3309         if (cli_write(cli1, fnum1, 0, buf, 0, 4) != 4) {
3310                 printf("write on fnum1 failed (%s)\n", cli_errstr(cli1));
3311                 correct = False;
3312         }
3313 #endif
3314
3315         if (!NT_STATUS_IS_OK(cli_close(cli1, fnum1))) {
3316                 printf("close1 failed (%s)\n", cli_errstr(cli1));
3317                 correct = False;
3318         }
3319
3320         sleep(4);
3321
3322         if (!NT_STATUS_IS_OK(cli_unlink(cli1, fname, aSYSTEM | aHIDDEN))) {
3323                 printf("unlink failed (%s)\n", cli_errstr(cli1));
3324                 correct = False;
3325         }
3326
3327         if (!torture_close_connection(cli1)) {
3328                 correct = False;
3329         }
3330
3331         if (!*shared_correct) {
3332                 correct = False;
3333         }
3334
3335         printf("finished oplock test 2\n");
3336
3337         return correct;
3338 }
3339
3340 /* handler for oplock 3 tests */
3341 static NTSTATUS oplock3_handler(struct cli_state *cli, uint16_t fnum, unsigned char level)
3342 {
3343         printf("got oplock break fnum=%d level=%d\n",
3344                fnum, level);
3345         return cli_oplock_ack(cli, fnum, level);
3346 }
3347
3348 static bool run_oplock3(int dummy)
3349 {
3350         struct cli_state *cli;
3351         const char *fname = "\\oplockt3.dat";
3352         uint16_t fnum;
3353         char buf[4] = "abcd";
3354         bool correct = True;
3355         volatile bool *shared_correct;
3356
3357         shared_correct = (volatile bool *)shm_setup(sizeof(bool));
3358         *shared_correct = True;
3359
3360         printf("starting oplock test 3\n");
3361
3362         if (fork() == 0) {
3363                 /* Child code */
3364                 use_oplocks = True;
3365                 use_level_II_oplocks = True;
3366                 if (!torture_open_connection(&cli, 0)) {
3367                         *shared_correct = False;
3368                         exit(0);
3369                 } 
3370                 sleep(2);
3371                 /* try to trigger a oplock break in parent */
3372                 cli_open(cli, fname, O_RDWR, DENY_NONE, &fnum);
3373                 cli_write(cli, fnum, 0, buf, 0, 4);
3374                 exit(0);
3375         }
3376
3377         /* parent code */
3378         use_oplocks = True;
3379         use_level_II_oplocks = True;
3380         if (!torture_open_connection(&cli, 1)) { /* other is forked */
3381                 return False;
3382         }
3383         cli_oplock_handler(cli, oplock3_handler);
3384         cli_open(cli, fname, O_RDWR|O_CREAT, DENY_NONE, &fnum);
3385         cli_write(cli, fnum, 0, buf, 0, 4);
3386         cli_close(cli, fnum);
3387         cli_open(cli, fname, O_RDWR, DENY_NONE, &fnum);
3388         cli->timeout = 20000;
3389         cli_receive_smb(cli);
3390         printf("finished oplock test 3\n");
3391
3392         return (correct && *shared_correct);
3393
3394 /* What are we looking for here?  What's sucess and what's FAILURE? */
3395 }
3396
3397
3398
3399 /*
3400   Test delete on close semantics.
3401  */
3402 static bool run_deletetest(int dummy)
3403 {
3404         struct cli_state *cli1 = NULL;
3405         struct cli_state *cli2 = NULL;
3406         const char *fname = "\\delete.file";
3407         uint16_t fnum1 = (uint16_t)-1;
3408         uint16_t fnum2 = (uint16_t)-1;
3409         bool correct = True;
3410
3411         printf("starting delete test\n");
3412
3413         if (!torture_open_connection(&cli1, 0)) {
3414                 return False;
3415         }
3416
3417         cli_sockopt(cli1, sockops);
3418
3419         /* Test 1 - this should delete the file on close. */
3420
3421         cli_setatr(cli1, fname, 0, 0);
3422         cli_unlink(cli1, fname, aSYSTEM | aHIDDEN);
3423
3424         if (!NT_STATUS_IS_OK(cli_ntcreate(cli1, fname, 0, GENERIC_ALL_ACCESS|DELETE_ACCESS, FILE_ATTRIBUTE_NORMAL,
3425                                    0, FILE_OVERWRITE_IF, 
3426                                    FILE_DELETE_ON_CLOSE, 0, &fnum1))) {
3427                 printf("[1] open of %s failed (%s)\n", fname, cli_errstr(cli1));
3428                 correct = False;
3429                 goto fail;
3430         }
3431
3432         if (!NT_STATUS_IS_OK(cli_close(cli1, fnum1))) {
3433                 printf("[1] close failed (%s)\n", cli_errstr(cli1));
3434                 correct = False;
3435                 goto fail;
3436         }
3437
3438         if (NT_STATUS_IS_OK(cli_open(cli1, fname, O_RDWR, DENY_NONE, &fnum1))) {
3439                 printf("[1] open of %s succeeded (should fail)\n", fname);
3440                 correct = False;
3441                 goto fail;
3442         }
3443
3444         printf("first delete on close test succeeded.\n");
3445
3446         /* Test 2 - this should delete the file on close. */
3447
3448         cli_setatr(cli1, fname, 0, 0);
3449         cli_unlink(cli1, fname, aSYSTEM | aHIDDEN);
3450
3451         if (!NT_STATUS_IS_OK(cli_ntcreate(cli1, fname, 0, GENERIC_ALL_ACCESS,
3452                                    FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE, 
3453                                    FILE_OVERWRITE_IF, 0, 0, &fnum1))) {
3454                 printf("[2] open of %s failed (%s)\n", fname, cli_errstr(cli1));
3455                 correct = False;
3456                 goto fail;
3457         }
3458
3459         if (!NT_STATUS_IS_OK(cli_nt_delete_on_close(cli1, fnum1, true))) {
3460                 printf("[2] setting delete_on_close failed (%s)\n", cli_errstr(cli1));
3461                 correct = False;
3462                 goto fail;
3463         }
3464
3465         if (!NT_STATUS_IS_OK(cli_close(cli1, fnum1))) {
3466                 printf("[2] close failed (%s)\n", cli_errstr(cli1));
3467                 correct = False;
3468                 goto fail;
3469         }
3470
3471         if (NT_STATUS_IS_OK(cli_open(cli1, fname, O_RDONLY, DENY_NONE, &fnum1))) {
3472                 printf("[2] open of %s succeeded should have been deleted on close !\n", fname);
3473                 if (!NT_STATUS_IS_OK(cli_close(cli1, fnum1))) {
3474                         printf("[2] close failed (%s)\n", cli_errstr(cli1));
3475                         correct = False;
3476                         goto fail;
3477                 }
3478                 cli_unlink(cli1, fname, aSYSTEM | aHIDDEN);
3479         } else
3480                 printf("second delete on close test succeeded.\n");
3481
3482         /* Test 3 - ... */
3483         cli_setatr(cli1, fname, 0, 0);
3484         cli_unlink(cli1, fname, aSYSTEM | aHIDDEN);
3485
3486         if (!NT_STATUS_IS_OK(cli_ntcreate(cli1, fname, 0, GENERIC_ALL_ACCESS, FILE_ATTRIBUTE_NORMAL,
3487                                    FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OVERWRITE_IF, 0, 0, &fnum1))) {
3488                 printf("[3] open - 1 of %s failed (%s)\n", fname, cli_errstr(cli1));
3489                 correct = False;
3490                 goto fail;
3491         }
3492
3493         /* This should fail with a sharing violation - open for delete is only compatible
3494            with SHARE_DELETE. */
3495
3496         if (NT_STATUS_IS_OK(cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS, FILE_ATTRIBUTE_NORMAL,
3497                         FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OPEN, 0, 0, &fnum2))) {
3498                 printf("[3] open  - 2 of %s succeeded - should have failed.\n", fname);
3499                 correct = False;
3500                 goto fail;
3501         }
3502
3503         /* This should succeed. */
3504
3505         if (!NT_STATUS_IS_OK(cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS, FILE_ATTRIBUTE_NORMAL,
3506                         FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE, FILE_OPEN, 0, 0, &fnum2))) {
3507                 printf("[3] open  - 2 of %s failed (%s)\n", fname, cli_errstr(cli1));
3508                 correct = False;
3509                 goto fail;
3510         }
3511
3512         if (!NT_STATUS_IS_OK(cli_nt_delete_on_close(cli1, fnum1, true))) {
3513                 printf("[3] setting delete_on_close failed (%s)\n", cli_errstr(cli1));
3514                 correct = False;
3515                 goto fail;
3516         }
3517
3518         if (!NT_STATUS_IS_OK(cli_close(cli1, fnum1))) {
3519                 printf("[3] close 1 failed (%s)\n", cli_errstr(cli1));
3520                 correct = False;
3521                 goto fail;
3522         }
3523
3524         if (!NT_STATUS_IS_OK(cli_close(cli1, fnum2))) {
3525                 printf("[3] close 2 failed (%s)\n", cli_errstr(cli1));
3526                 correct = False;
3527                 goto fail;
3528         }
3529
3530         /* This should fail - file should no longer be there. */
3531
3532         if (NT_STATUS_IS_OK(cli_open(cli1, fname, O_RDONLY, DENY_NONE, &fnum1))) {
3533                 printf("[3] open of %s succeeded should have been deleted on close !\n", fname);
3534                 if (!NT_STATUS_IS_OK(cli_close(cli1, fnum1))) {
3535                         printf("[3] close failed (%s)\n", cli_errstr(cli1));
3536                 }
3537                 cli_unlink(cli1, fname, aSYSTEM | aHIDDEN);
3538                 correct = False;
3539                 goto fail;
3540         } else
3541                 printf("third delete on close test succeeded.\n");
3542
3543         /* Test 4 ... */
3544         cli_setatr(cli1, fname, 0, 0);
3545         cli_unlink(cli1, fname, aSYSTEM | aHIDDEN);
3546
3547         if (!NT_STATUS_IS_OK(cli_ntcreate(cli1, fname, 0, FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
3548                         FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OVERWRITE_IF, 0, 0, &fnum1))) {
3549                 printf("[4] open of %s failed (%s)\n", fname, cli_errstr(cli1));
3550                 correct = False;
3551                 goto fail;
3552         }
3553
3554         /* This should succeed. */
3555         if (!NT_STATUS_IS_OK(cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
3556                         FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE, FILE_OPEN, 0, 0, &fnum2))) {
3557                 printf("[4] open  - 2 of %s failed (%s)\n", fname, cli_errstr(cli1));
3558                 correct = False;
3559                 goto fail;
3560         }
3561
3562         if (!NT_STATUS_IS_OK(cli_close(cli1, fnum2))) {
3563                 printf("[4] close - 1 failed (%s)\n", cli_errstr(cli1));
3564                 correct = False;
3565                 goto fail;
3566         }
3567
3568         if (!NT_STATUS_IS_OK(cli_nt_delete_on_close(cli1, fnum1, true))) {
3569                 printf("[4] setting delete_on_close failed (%s)\n", cli_errstr(cli1));
3570                 correct = False;
3571                 goto fail;
3572         }
3573
3574         /* This should fail - no more opens once delete on close set. */
3575         if (NT_STATUS_IS_OK(cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
3576                                    FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
3577                                    FILE_OPEN, 0, 0, &fnum2))) {
3578                 printf("[4] open  - 3 of %s succeeded ! Should have failed.\n", fname );
3579                 correct = False;
3580                 goto fail;
3581         } else
3582                 printf("fourth delete on close test succeeded.\n");
3583
3584         if (!NT_STATUS_IS_OK(cli_close(cli1, fnum1))) {
3585                 printf("[4] close - 2 failed (%s)\n", cli_errstr(cli1));
3586                 correct = False;
3587                 goto fail;
3588         }
3589
3590         /* Test 5 ... */
3591         cli_setatr(cli1, fname, 0, 0);
3592         cli_unlink(cli1, fname, aSYSTEM | aHIDDEN);
3593
3594         if (!NT_STATUS_IS_OK(cli_open(cli1, fname, O_RDWR|O_CREAT, DENY_NONE, &fnum1))) {
3595                 printf("[5] open of %s failed (%s)\n", fname, cli_errstr(cli1));
3596                 correct = False;
3597                 goto fail;
3598         }
3599
3600         /* This should fail - only allowed on NT opens with DELETE access. */
3601
3602         if (NT_STATUS_IS_OK(cli_nt_delete_on_close(cli1, fnum1, true))) {
3603                 printf("[5] setting delete_on_close on OpenX file succeeded - should fail !\n");
3604                 correct = False;
3605                 goto fail;
3606         }
3607
3608         if (!NT_STATUS_IS_OK(cli_close(cli1, fnum1))) {
3609                 printf("[5] close - 2 failed (%s)\n", cli_errstr(cli1));
3610                 correct = False;
3611                 goto fail;
3612         }
3613
3614         printf("fifth delete on close test succeeded.\n");
3615
3616         /* Test 6 ... */
3617         cli_setatr(cli1, fname, 0, 0);
3618         cli_unlink(cli1, fname, aSYSTEM | aHIDDEN);
3619
3620         if (!NT_STATUS_IS_OK(cli_ntcreate(cli1, fname, 0, FILE_READ_DATA|FILE_WRITE_DATA,
3621                                    FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
3622                                    FILE_OVERWRITE_IF, 0, 0, &fnum1))) {
3623                 printf("[6] open of %s failed (%s)\n", fname, cli_errstr(cli1));
3624                 correct = False;
3625                 goto fail;
3626         }
3627
3628         /* This should fail - only allowed on NT opens with DELETE access. */
3629
3630         if (NT_STATUS_IS_OK(cli_nt_delete_on_close(cli1, fnum1, true))) {
3631                 printf("[6] setting delete_on_close on file with no delete access succeeded - should fail !\n");
3632                 correct = False;
3633                 goto fail;
3634         }
3635
3636         if (!NT_STATUS_IS_OK(cli_close(cli1, fnum1))) {
3637                 printf("[6] close - 2 failed (%s)\n", cli_errstr(cli1));
3638                 correct = False;
3639                 goto fail;
3640         }
3641
3642         printf("sixth delete on close test succeeded.\n");
3643
3644         /* Test 7 ... */
3645         cli_setatr(cli1, fname, 0, 0);
3646         cli_unlink(cli1, fname, aSYSTEM | aHIDDEN);
3647
3648         if (!NT_STATUS_IS_OK(cli_ntcreate(cli1, fname, 0, FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
3649                                    FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF, 0, 0, &fnum1))) {
3650                 printf("[7] open of %s failed (%s)\n", fname, cli_errstr(cli1));
3651                 correct = False;
3652                 goto fail;
3653         }
3654
3655         if (!NT_STATUS_IS_OK(cli_nt_delete_on_close(cli1, fnum1, true))) {
3656                 printf("[7] setting delete_on_close on file failed !\n");
3657                 correct = False;
3658                 goto fail;
3659         }
3660
3661         if (!NT_STATUS_IS_OK(cli_nt_delete_on_close(cli1, fnum1, false))) {
3662                 printf("[7] unsetting delete_on_close on file failed !\n");
3663                 correct = False;
3664                 goto fail;
3665         }
3666
3667         if (!NT_STATUS_IS_OK(cli_close(cli1, fnum1))) {
3668                 printf("[7] close - 2 failed (%s)\n", cli_errstr(cli1));
3669                 correct = False;
3670                 goto fail;
3671         }
3672
3673         /* This next open should succeed - we reset the flag. */
3674
3675         if (!NT_STATUS_IS_OK(cli_open(cli1, fname, O_RDONLY, DENY_NONE, &fnum1))) {
3676                 printf("[5] open of %s failed (%s)\n", fname, cli_errstr(cli1));
3677                 correct = False;
3678                 goto fail;
3679         }
3680
3681         if (!NT_STATUS_IS_OK(cli_close(cli1, fnum1))) {
3682                 printf("[7] close - 2 failed (%s)\n", cli_errstr(cli1));
3683                 correct = False;
3684                 goto fail;
3685         }
3686
3687         printf("seventh delete on close test succeeded.\n");
3688
3689         /* Test 7 ... */
3690         cli_setatr(cli1, fname, 0, 0);
3691         cli_unlink(cli1, fname, aSYSTEM | aHIDDEN);
3692
3693         if (!torture_open_connection(&cli2, 1)) {
3694                 printf("[8] failed to open second connection.\n");
3695                 correct = False;
3696                 goto fail;
3697         }
3698
3699         cli_sockopt(cli1, sockops);
3700
3701         if (!NT_STATUS_IS_OK(cli_ntcreate(cli1, fname, 0, FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
3702                                    FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
3703                                    FILE_OVERWRITE_IF, 0, 0, &fnum1))) {
3704                 printf("[8] open 1 of %s failed (%s)\n", fname, cli_errstr(cli1));
3705                 correct = False;
3706                 goto fail;
3707         }
3708
3709         if (!NT_STATUS_IS_OK(cli_ntcreate(cli2, fname, 0, FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
3710                                    FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
3711                                    FILE_OPEN, 0, 0, &fnum2))) {
3712                 printf("[8] open 2 of %s failed (%s)\n", fname, cli_errstr(cli2));
3713                 correct = False;
3714                 goto fail;
3715         }
3716
3717         if (!NT_STATUS_IS_OK(cli_nt_delete_on_close(cli1, fnum1, true))) {
3718                 printf("[8] setting delete_on_close on file failed !\n");
3719                 correct = False;
3720                 goto fail;
3721         }
3722
3723         if (!NT_STATUS_IS_OK(cli_close(cli1, fnum1))) {
3724                 printf("[8] close - 1 failed (%s)\n", cli_errstr(cli1));
3725                 correct = False;
3726                 goto fail;
3727         }
3728
3729         if (!NT_STATUS_IS_OK(cli_close(cli2, fnum2))) {
3730                 printf("[8] close - 2 failed (%s)\n", cli_errstr(cli2));
3731                 correct = False;
3732                 goto fail;
3733         }
3734
3735         /* This should fail.. */
3736         if (NT_STATUS_IS_OK(cli_open(cli1, fname, O_RDONLY, DENY_NONE, &fnum1))) {
3737                 printf("[8] open of %s succeeded should have been deleted on close !\n", fname);
3738                 goto fail;
3739                 correct = False;
3740         } else
3741                 printf("eighth delete on close test succeeded.\n");
3742
3743         /* This should fail - we need to set DELETE_ACCESS. */
3744         if (NT_STATUS_IS_OK(cli_ntcreate(cli1, fname, 0,FILE_READ_DATA|FILE_WRITE_DATA,
3745                                    FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE, FILE_OVERWRITE_IF, FILE_DELETE_ON_CLOSE, 0, &fnum1))) {
3746                 printf("[9] open of %s succeeded should have failed!\n", fname);
3747                 correct = False;
3748                 goto fail;
3749         }
3750
3751         printf("ninth delete on close test succeeded.\n");
3752
3753         if (!NT_STATUS_IS_OK(cli_ntcreate(cli1, fname, 0, FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
3754                                    FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE, FILE_OVERWRITE_IF, FILE_DELETE_ON_CLOSE, 0, &fnum1))) {
3755                 printf("[10] open of %s failed (%s)\n", fname, cli_errstr(cli1));
3756                 correct = False;
3757                 goto fail;
3758         }
3759
3760         /* This should delete the file. */
3761         if (!NT_STATUS_IS_OK(cli_close(cli1, fnum1))) {
3762                 printf("[10] close failed (%s)\n", cli_errstr(cli1));
3763                 correct = False;
3764                 goto fail;
3765         }
3766
3767         /* This should fail.. */
3768         if (NT_STATUS_IS_OK(cli_open(cli1, fname, O_RDONLY, DENY_NONE, &fnum1))) {
3769                 printf("[10] open of %s succeeded should have been deleted on close !\n", fname);
3770                 goto fail;
3771                 correct = False;
3772         } else
3773                 printf("tenth delete on close test succeeded.\n");
3774
3775         cli_setatr(cli1, fname, 0, 0);
3776         cli_unlink(cli1, fname, aSYSTEM | aHIDDEN);
3777
3778         /* What error do we get when attempting to open a read-only file with
3779            delete access ? */
3780
3781         /* Create a readonly file. */
3782         if (!NT_STATUS_IS_OK(cli_ntcreate(cli1, fname, 0, FILE_READ_DATA|FILE_WRITE_DATA,
3783                                    FILE_ATTRIBUTE_READONLY, FILE_SHARE_NONE, FILE_OVERWRITE_IF, 0, 0, &fnum1))) {
3784                 printf("[11] open of %s failed (%s)\n", fname, cli_errstr(cli1));
3785                 correct = False;
3786                 goto fail;
3787         }
3788
3789         if (!NT_STATUS_IS_OK(cli_close(cli1, fnum1))) {
3790                 printf("[11] close failed (%s)\n", cli_errstr(cli1));
3791                 correct = False;
3792                 goto fail;
3793         }
3794
3795         /* Now try open for delete access. */
3796         if (NT_STATUS_IS_OK(cli_ntcreate(cli1, fname, 0, FILE_READ_ATTRIBUTES|DELETE_ACCESS,
3797                                    0, FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
3798                                    FILE_OVERWRITE_IF, 0, 0, &fnum1))) {
3799                 printf("[11] open of %s succeeded should have been denied with ACCESS_DENIED!\n", fname);
3800                 cli_close(cli1, fnum1);
3801                 goto fail;
3802                 correct = False;
3803         } else {
3804                 NTSTATUS nterr = cli_nt_error(cli1);
3805                 if (!NT_STATUS_EQUAL(nterr,NT_STATUS_ACCESS_DENIED)) {
3806                         printf("[11] open of %s should have been denied with ACCESS_DENIED! Got error %s\n", fname, nt_errstr(nterr));
3807                         goto fail;
3808                         correct = False;
3809                 } else {
3810                         printf("eleventh delete on close test succeeded.\n");
3811                 }
3812         }
3813
3814         printf("finished delete test\n");
3815
3816   fail:
3817         /* FIXME: This will crash if we aborted before cli2 got
3818          * intialized, because these functions don't handle
3819          * uninitialized connections. */
3820
3821         if (fnum1 != (uint16_t)-1) cli_close(cli1, fnum1);
3822         if (fnum2 != (uint16_t)-1) cli_close(cli1, fnum2);
3823         cli_setatr(cli1, fname, 0, 0);
3824         cli_unlink(cli1, fname, aSYSTEM | aHIDDEN);
3825
3826         if (cli1 && !torture_close_connection(cli1)) {
3827                 correct = False;
3828         }
3829         if (cli2 && !torture_close_connection(cli2)) {
3830                 correct = False;
3831         }
3832         return correct;
3833 }
3834
3835
3836 /*
3837   print out server properties
3838  */
3839 static bool run_properties(int dummy)
3840 {
3841         struct cli_state *cli;
3842         bool correct = True;
3843
3844         printf("starting properties test\n");
3845
3846         ZERO_STRUCT(cli);
3847
3848         if (!torture_open_connection(&cli, 0)) {
3849                 return False;
3850         }
3851
3852         cli_sockopt(cli, sockops);
3853
3854         d_printf("Capabilities 0x%08x\n", cli->capabilities);
3855
3856         if (!torture_close_connection(cli)) {
3857                 correct = False;
3858         }
3859
3860         return correct;
3861 }
3862
3863
3864
3865 /* FIRST_DESIRED_ACCESS   0xf019f */
3866 #define FIRST_DESIRED_ACCESS   FILE_READ_DATA|FILE_WRITE_DATA|FILE_APPEND_DATA|\
3867                                FILE_READ_EA|                           /* 0xf */ \
3868                                FILE_WRITE_EA|FILE_READ_ATTRIBUTES|     /* 0x90 */ \
3869                                FILE_WRITE_ATTRIBUTES|                  /* 0x100 */ \
3870                                DELETE_ACCESS|READ_CONTROL_ACCESS|\
3871                                WRITE_DAC_ACCESS|WRITE_OWNER_ACCESS     /* 0xf0000 */
3872 /* SECOND_DESIRED_ACCESS  0xe0080 */
3873 #define SECOND_DESIRED_ACCESS  FILE_READ_ATTRIBUTES|                   /* 0x80 */ \
3874                                READ_CONTROL_ACCESS|WRITE_DAC_ACCESS|\
3875                                WRITE_OWNER_ACCESS                      /* 0xe0000 */
3876
3877 #if 0
3878 #define THIRD_DESIRED_ACCESS   FILE_READ_ATTRIBUTES|                   /* 0x80 */ \
3879                                READ_CONTROL_ACCESS|WRITE_DAC_ACCESS|\
3880                                FILE_READ_DATA|\
3881                                WRITE_OWNER_ACCESS                      /* */
3882 #endif
3883
3884 /*
3885   Test ntcreate calls made by xcopy
3886  */
3887 static bool run_xcopy(int dummy)
3888 {
3889         static struct cli_state *cli1;
3890         const char *fname = "\\test.txt";
3891         bool correct = True;
3892         uint16_t fnum1, fnum2;
3893
3894         printf("starting xcopy test\n");
3895
3896         if (!torture_open_connection(&cli1, 0)) {
3897                 return False;
3898         }
3899
3900         if (!NT_STATUS_IS_OK(cli_ntcreate(cli1, fname, 0,
3901                                    FIRST_DESIRED_ACCESS, FILE_ATTRIBUTE_ARCHIVE,
3902                                    FILE_SHARE_NONE, FILE_OVERWRITE_IF, 
3903                                    0x4044, 0, &fnum1))) {
3904                 printf("First open failed - %s\n", cli_errstr(cli1));
3905                 return False;
3906         }
3907
3908         if (!NT_STATUS_IS_OK(cli_ntcreate(cli1, fname, 0,
3909                                    SECOND_DESIRED_ACCESS, 0,
3910                                    FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE, FILE_OPEN, 
3911                                    0x200000, 0, &fnum2))) {
3912                 printf("second open failed - %s\n", cli_errstr(cli1));
3913                 return False;
3914         }
3915
3916         if (!torture_close_connection(cli1)) {
3917                 correct = False;
3918         }
3919
3920         return correct;
3921 }
3922
3923 /*
3924   Test rename on files open with share delete and no share delete.
3925  */
3926 static bool run_rename(int dummy)
3927 {
3928         static struct cli_state *cli1;
3929         const char *fname = "\\test.txt";
3930         const char *fname1 = "\\test1.txt";
3931         bool correct = True;
3932         uint16_t fnum1;
3933         uint16_t attr;
3934         NTSTATUS status;
3935
3936         printf("starting rename test\n");
3937
3938         if (!torture_open_connection(&cli1, 0)) {
3939                 return False;
3940         }
3941
3942         cli_unlink(cli1, fname, aSYSTEM | aHIDDEN);
3943         cli_unlink(cli1, fname1, aSYSTEM | aHIDDEN);
3944         if (!NT_STATUS_IS_OK(cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS, FILE_ATTRIBUTE_NORMAL,
3945                                    FILE_SHARE_READ, FILE_OVERWRITE_IF, 0, 0, &fnum1))) {
3946                 printf("First open failed - %s\n", cli_errstr(cli1));
3947                 return False;
3948         }
3949
3950         if (!NT_STATUS_IS_OK(cli_rename(cli1, fname, fname1))) {
3951                 printf("First rename failed (SHARE_READ) (this is correct) - %s\n", cli_errstr(cli1));
3952         } else {
3953                 printf("First rename succeeded (SHARE_READ) - this should have failed !\n");
3954                 correct = False;
3955         }
3956
3957         if (!NT_STATUS_IS_OK(cli_close(cli1, fnum1))) {
3958                 printf("close - 1 failed (%s)\n", cli_errstr(cli1));
3959                 return False;
3960         }
3961
3962         cli_unlink(cli1, fname, aSYSTEM | aHIDDEN);
3963         cli_unlink(cli1, fname1, aSYSTEM | aHIDDEN);
3964         status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS, FILE_ATTRIBUTE_NORMAL,
3965 #if 0
3966                               FILE_SHARE_DELETE|FILE_SHARE_NONE,
3967 #else
3968                               FILE_SHARE_DELETE|FILE_SHARE_READ,
3969 #endif
3970                               FILE_OVERWRITE_IF, 0, 0, &fnum1);
3971         if (!NT_STATUS_IS_OK(status)) {
3972                 printf("Second open failed - %s\n", cli_errstr(cli1));
3973                 return False;
3974         }
3975
3976         if (!NT_STATUS_IS_OK(cli_rename(cli1, fname, fname1))) {
3977                 printf("Second rename failed (SHARE_DELETE | SHARE_READ) - this should have succeeded - %s\n", cli_errstr(cli1));
3978                 correct = False;
3979         } else {
3980                 printf("Second rename succeeded (SHARE_DELETE | SHARE_READ)\n");
3981         }
3982
3983         if (!NT_STATUS_IS_OK(cli_close(cli1, fnum1))) {
3984                 printf("close - 2 failed (%s)\n", cli_errstr(cli1));
3985                 return False;
3986         }
3987
3988         cli_unlink(cli1, fname, aSYSTEM | aHIDDEN);
3989         cli_unlink(cli1, fname1, aSYSTEM | aHIDDEN);
3990
3991         if (!NT_STATUS_IS_OK(cli_ntcreate(cli1, fname, 0, READ_CONTROL_ACCESS, FILE_ATTRIBUTE_NORMAL,
3992                                    FILE_SHARE_NONE, FILE_OVERWRITE_IF, 0, 0, &fnum1))) {
3993                 printf("Third open failed - %s\n", cli_errstr(cli1));
3994                 return False;
3995         }
3996
3997
3998 #if 0
3999   {
4000         uint16_t fnum2;
4001
4002         if (!NT_STATUS_IS_OK(cli_ntcreate(cli1, fname, 0, DELETE_ACCESS, FILE_ATTRIBUTE_NORMAL,
4003                                    FILE_SHARE_NONE, FILE_OVERWRITE_IF, 0, 0, &fnum2))) {
4004                 printf("Fourth open failed - %s\n", cli_errstr(cli1));
4005                 return False;
4006         }
4007         if (!NT_STATUS_IS_OK(cli_nt_delete_on_close(cli1, fnum2, true))) {
4008                 printf("[8] setting delete_on_close on file failed !\n");
4009                 return False;
4010         }
4011
4012         if (!NT_STATUS_IS_OK(cli_close(cli1, fnum2))) {
4013                 printf("close - 4 failed (%s)\n", cli_errstr(cli1));
4014                 return False;
4015         }
4016   }
4017 #endif
4018
4019         if (!NT_STATUS_IS_OK(cli_rename(cli1, fname, fname1))) {
4020                 printf("Third rename failed (SHARE_NONE) - this should have succeeded - %s\n", cli_errstr(cli1));
4021                 correct = False;
4022         } else {
4023                 printf("Third rename succeeded (SHARE_NONE)\n");
4024         }
4025
4026         if (!NT_STATUS_IS_OK(cli_close(cli1, fnum1))) {
4027                 printf("close - 3 failed (%s)\n", cli_errstr(cli1));
4028                 return False;
4029         }
4030
4031         cli_unlink(cli1, fname, aSYSTEM | aHIDDEN);
4032         cli_unlink(cli1, fname1, aSYSTEM | aHIDDEN);
4033
4034         /*----*/
4035
4036         if (!NT_STATUS_IS_OK(cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS, FILE_ATTRIBUTE_NORMAL,
4037                                    FILE_SHARE_READ | FILE_SHARE_WRITE, FILE_OVERWRITE_IF, 0, 0, &fnum1))) {
4038                 printf("Fourth open failed - %s\n", cli_errstr(cli1));
4039                 return False;
4040         }
4041
4042         if (!NT_STATUS_IS_OK(cli_rename(cli1, fname, fname1))) {
4043                 printf("Fourth rename failed (SHARE_READ | SHARE_WRITE) (this is correct) - %s\n", cli_errstr(cli1));
4044         } else {
4045                 printf("Fourth rename succeeded (SHARE_READ | SHARE_WRITE) - this should have failed !\n");
4046                 correct = False;
4047         }
4048
4049         if (!NT_STATUS_IS_OK(cli_close(cli1, fnum1))) {
4050                 printf("close - 4 failed (%s)\n", cli_errstr(cli1));
4051                 return False;
4052         }
4053
4054         cli_unlink(cli1, fname, aSYSTEM | aHIDDEN);
4055         cli_unlink(cli1, fname1, aSYSTEM | aHIDDEN);
4056
4057         /*--*/
4058
4059         if (!NT_STATUS_IS_OK(cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS, FILE_ATTRIBUTE_NORMAL,
4060                                    FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, FILE_OVERWRITE_IF, 0, 0, &fnum1))) {
4061                 printf("Fifth open failed - %s\n", cli_errstr(cli1));
4062                 return False;
4063         }
4064
4065         if (!NT_STATUS_IS_OK(cli_rename(cli1, fname, fname1))) {
4066                 printf("Fifth rename failed (SHARE_READ | SHARE_WRITE | SHARE_DELETE) - this should have succeeded - %s ! \n",
4067                         cli_errstr(cli1));
4068                 correct = False;
4069         } else {
4070                 printf("Fifth rename succeeded (SHARE_READ | SHARE_WRITE | SHARE_DELETE) (this is correct) - %s\n", cli_errstr(cli1));
4071         }
4072
4073         /*
4074          * Now check if the first name still exists ...
4075          */
4076
4077         /* if (!NT_STATUS_OP(cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS, FILE_ATTRIBUTE_NORMAL,
4078                                    FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, FILE_OVERWRITE_IF, 0, 0, &fnum2))) {
4079           printf("Opening original file after rename of open file fails: %s\n",
4080               cli_errstr(cli1));
4081         }
4082         else {
4083           printf("Opening original file after rename of open file works ...\n");
4084           (void)cli_close(cli1, fnum2);
4085           } */
4086
4087         /*--*/
4088         if (!NT_STATUS_IS_OK(cli_close(cli1, fnum1))) {
4089                 printf("close - 5 failed (%s)\n", cli_errstr(cli1));
4090                 return False;
4091         }
4092
4093         /* Check that the renamed file has FILE_ATTRIBUTE_ARCHIVE. */
4094         if (!NT_STATUS_IS_OK(cli_getatr(cli1, fname1, &attr, NULL, NULL))) {
4095                 printf("getatr on file %s failed - %s ! \n",
4096                         fname1,
4097                         cli_errstr(cli1));
4098                 correct = False;
4099         } else {
4100                 if (attr != FILE_ATTRIBUTE_ARCHIVE) {
4101                         printf("Renamed file %s has wrong attr 0x%x "
4102                                 "(should be 0x%x)\n",
4103                                 fname1,
4104                                 attr,
4105                                 (unsigned int)FILE_ATTRIBUTE_ARCHIVE);
4106                         correct = False;
4107                 } else {
4108                         printf("Renamed file %s has archive bit set\n", fname1);
4109                 }
4110         }
4111
4112         cli_unlink(cli1, fname, aSYSTEM | aHIDDEN);
4113         cli_unlink(cli1, fname1, aSYSTEM | aHIDDEN);
4114
4115         if (!torture_close_connection(cli1)) {
4116                 correct = False;
4117         }
4118
4119         return correct;
4120 }
4121
4122 static bool run_pipe_number(int dummy)
4123 {
4124         struct cli_state *cli1;
4125         const char *pipe_name = "\\SPOOLSS";
4126         uint16_t fnum;
4127         int num_pipes = 0;
4128
4129         printf("starting pipenumber test\n");
4130         if (!torture_open_connection(&cli1, 0)) {
4131                 return False;
4132         }
4133
4134         cli_sockopt(cli1, sockops);
4135         while(1) {
4136                 if (!NT_STATUS_IS_OK(cli_ntcreate(cli1, pipe_name, 0, FILE_READ_DATA, FILE_ATTRIBUTE_NORMAL,
4137                                    FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OPEN_IF, 0, 0, &fnum))) {
4138                         printf("Open of pipe %s failed with error (%s)\n", pipe_name, cli_errstr(cli1));
4139                         break;
4140                 }
4141                 num_pipes++;
4142                 printf("\r%6d", num_pipes);
4143         }
4144
4145         printf("pipe_number test - we can open %d %s pipes.\n", num_pipes, pipe_name );
4146         torture_close_connection(cli1);
4147         return True;
4148 }
4149
4150 /*
4151   Test open mode returns on read-only files.
4152  */
4153 static bool run_opentest(int dummy)
4154 {
4155         static struct cli_state *cli1;
4156         static struct cli_state *cli2;
4157         const char *fname = "\\readonly.file";
4158         uint16_t fnum1, fnum2;
4159         char buf[20];
4160         SMB_OFF_T fsize;
4161         bool correct = True;
4162         char *tmp_path;
4163
4164         printf("starting open test\n");
4165
4166         if (!torture_open_connection(&cli1, 0)) {
4167                 return False;
4168         }
4169
4170         cli_setatr(cli1, fname, 0, 0);
4171         cli_unlink(cli1, fname, aSYSTEM | aHIDDEN);
4172
4173         cli_sockopt(cli1, sockops);
4174
4175         if (!NT_STATUS_IS_OK(cli_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1))) {
4176                 printf("open of %s failed (%s)\n", fname, cli_errstr(cli1));
4177                 return False;
4178         }
4179
4180         if (!NT_STATUS_IS_OK(cli_close(cli1, fnum1))) {
4181                 printf("close2 failed (%s)\n", cli_errstr(cli1));
4182                 return False;
4183         }
4184
4185         if (!NT_STATUS_IS_OK(cli_setatr(cli1, fname, aRONLY, 0))) {
4186                 printf("cli_setatr failed (%s)\n", cli_errstr(cli1));
4187                 return False;
4188         }
4189
4190         if (!NT_STATUS_IS_OK(cli_open(cli1, fname, O_RDONLY, DENY_WRITE, &fnum1))) {
4191                 printf("open of %s failed (%s)\n", fname, cli_errstr(cli1));
4192                 return False;
4193         }
4194
4195         /* This will fail - but the error should be ERRnoaccess, not ERRbadshare. */
4196         cli_open(cli1, fname, O_RDWR, DENY_ALL, &fnum2);
4197
4198         if (check_error(__LINE__, cli1, ERRDOS, ERRnoaccess, 
4199                         NT_STATUS_ACCESS_DENIED)) {
4200                 printf("correct error code ERRDOS/ERRnoaccess returned\n");
4201         }
4202
4203         printf("finished open test 1\n");
4204
4205         cli_close(cli1, fnum1);
4206
4207         /* Now try not readonly and ensure ERRbadshare is returned. */
4208
4209         cli_setatr(cli1, fname, 0, 0);
4210
4211         if (!NT_STATUS_IS_OK(cli_open(cli1, fname, O_RDONLY, DENY_WRITE, &fnum1))) {
4212                 printf("open of %s failed (%s)\n", fname, cli_errstr(cli1));
4213                 return False;
4214         }
4215
4216         /* This will fail - but the error should be ERRshare. */
4217         cli_open(cli1, fname, O_RDWR, DENY_ALL, &fnum2);
4218
4219         if (check_error(__LINE__, cli1, ERRDOS, ERRbadshare, 
4220                         NT_STATUS_SHARING_VIOLATION)) {
4221                 printf("correct error code ERRDOS/ERRbadshare returned\n");
4222         }
4223
4224         if (!NT_STATUS_IS_OK(cli_close(cli1, fnum1))) {
4225                 printf("close2 failed (%s)\n", cli_errstr(cli1));
4226                 return False;
4227         }
4228
4229         cli_unlink(cli1, fname, aSYSTEM | aHIDDEN);
4230
4231         printf("finished open test 2\n");
4232
4233         /* Test truncate open disposition on file opened for read. */
4234
4235         if (!NT_STATUS_IS_OK(cli_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1))) {
4236                 printf("(3) open (1) of %s failed (%s)\n", fname, cli_errstr(cli1));
4237                 return False;
4238         }
4239
4240         /* write 20 bytes. */
4241
4242         memset(buf, '\0', 20);
4243
4244         if (cli_write(cli1, fnum1, 0, buf, 0, 20) != 20) {
4245                 printf("write failed (%s)\n", cli_errstr(cli1));
4246                 correct = False;
4247         }
4248
4249         if (!NT_STATUS_IS_OK(cli_close(cli1, fnum1))) {
4250                 printf("(3) close1 failed (%s)\n", cli_errstr(cli1));
4251                 return False;
4252         }
4253
4254         /* Ensure size == 20. */
4255         if (!NT_STATUS_IS_OK(cli_getatr(cli1, fname, NULL, &fsize, NULL))) {
4256                 printf("(3) getatr failed (%s)\n", cli_errstr(cli1));
4257                 return False;
4258         }
4259
4260         if (fsize != 20) {
4261                 printf("(3) file size != 20\n");
4262                 return False;
4263         }
4264
4265         /* Now test if we can truncate a file opened for readonly. */
4266
4267         if (!NT_STATUS_IS_OK(cli_open(cli1, fname, O_RDONLY|O_TRUNC, DENY_NONE, &fnum1))) {
4268                 printf("(3) open (2) of %s failed (%s)\n", fname, cli_errstr(cli1));
4269                 return False;
4270         }
4271
4272         if (!NT_STATUS_IS_OK(cli_close(cli1, fnum1))) {
4273                 printf("close2 failed (%s)\n", cli_errstr(cli1));
4274                 return False;
4275         }
4276
4277         /* Ensure size == 0. */
4278         if (!NT_STATUS_IS_OK(cli_getatr(cli1, fname, NULL, &fsize, NULL))) {
4279                 printf("(3) getatr failed (%s)\n", cli_errstr(cli1));
4280                 return False;
4281         }
4282
4283         if (fsize != 0) {
4284                 printf("(3) file size != 0\n");
4285                 return False;
4286         }
4287         printf("finished open test 3\n");
4288
4289         cli_unlink(cli1, fname, aSYSTEM | aHIDDEN);
4290
4291         printf("Do ctemp tests\n");
4292         if (!NT_STATUS_IS_OK(cli_ctemp(cli1, talloc_tos(), "\\", &fnum1, &tmp_path))) {
4293                 printf("ctemp failed (%s)\n", cli_errstr(cli1));
4294                 return False;
4295         }
4296         printf("ctemp gave path %s\n", tmp_path);
4297         if (!NT_STATUS_IS_OK(cli_close(cli1, fnum1))) {
4298                 printf("close of temp failed (%s)\n", cli_errstr(cli1));
4299         }
4300         if (!NT_STATUS_IS_OK(cli_unlink(cli1, tmp_path, aSYSTEM | aHIDDEN))) {
4301                 printf("unlink of temp failed (%s)\n", cli_errstr(cli1));
4302         }
4303
4304         /* Test the non-io opens... */
4305
4306         if (!torture_open_connection(&cli2, 1)) {
4307                 return False;
4308         }
4309
4310         cli_setatr(cli2, fname, 0, 0);
4311         cli_unlink(cli2, fname, aSYSTEM | aHIDDEN);
4312
4313         cli_sockopt(cli2, sockops);
4314
4315         printf("TEST #1 testing 2 non-io opens (no delete)\n");
4316
4317         if (!NT_STATUS_IS_OK(cli_ntcreate(cli1, fname, 0, FILE_READ_ATTRIBUTES, FILE_ATTRIBUTE_NORMAL,
4318                                    FILE_SHARE_NONE, FILE_OVERWRITE_IF, 0, 0, &fnum1))) {
4319                 printf("TEST #1 open 1 of %s failed (%s)\n", fname, cli_errstr(cli1));
4320                 return False;
4321         }
4322
4323         if (!NT_STATUS_IS_OK(cli_ntcreate(cli2, fname, 0, FILE_READ_ATTRIBUTES, FILE_ATTRIBUTE_NORMAL,
4324                                    FILE_SHARE_NONE, FILE_OPEN_IF, 0, 0, &fnum2))) {
4325                 printf("TEST #1 open 2 of %s failed (%s)\n", fname, cli_errstr(cli2));
4326                 return False;
4327         }
4328
4329         if (!NT_STATUS_IS_OK(cli_close(cli1, fnum1))) {
4330                 printf("TEST #1 close 1 of %s failed (%s)\n", fname, cli_errstr(cli1));
4331                 return False;
4332         }
4333         if (!NT_STATUS_IS_OK(cli_close(cli2, fnum2))) {
4334                 printf("TEST #1 close 2 of %s failed (%s)\n", fname, cli_errstr(cli2));
4335                 return False;
4336         }
4337
4338         printf("non-io open test #1 passed.\n");
4339
4340         cli_unlink(cli1, fname, aSYSTEM | aHIDDEN);
4341
4342         printf("TEST #2 testing 2 non-io opens (first with delete)\n");
4343
4344         if (!NT_STATUS_IS_OK(cli_ntcreate(cli1, fname, 0, DELETE_ACCESS|FILE_READ_ATTRIBUTES, FILE_ATTRIBUTE_NORMAL,
4345                                    FILE_SHARE_NONE, FILE_OVERWRITE_IF, 0, 0, &fnum1))) {
4346                 printf("TEST #2 open 1 of %s failed (%s)\n", fname, cli_errstr(cli1));
4347                 return False;
4348         }
4349
4350         if (!NT_STATUS_IS_OK(cli_ntcreate(cli2, fname, 0, FILE_READ_ATTRIBUTES, FILE_ATTRIBUTE_NORMAL,
4351                                    FILE_SHARE_NONE, FILE_OPEN_IF, 0, 0, &fnum2))) {
4352                 printf("TEST #2 open 2 of %s failed (%s)\n", fname, cli_errstr(cli2));
4353                 return False;
4354         }
4355
4356         if (!NT_STATUS_IS_OK(cli_close(cli1, fnum1))) {
4357                 printf("TEST #2 close 1 of %s failed (%s)\n", fname, cli_errstr(cli1));
4358                 return False;
4359         }
4360         if (!NT_STATUS_IS_OK(cli_close(cli2, fnum2))) {
4361                 printf("TEST #2 close 2 of %s failed (%s)\n", fname, cli_errstr(cli1));
4362                 return False;
4363         }
4364
4365         printf("non-io open test #2 passed.\n");
4366
4367         cli_unlink(cli1, fname, aSYSTEM | aHIDDEN);
4368
4369         printf("TEST #3 testing 2 non-io opens (second with delete)\n");
4370
4371         if (!NT_STATUS_IS_OK(cli_ntcreate(cli1, fname, 0, FILE_READ_ATTRIBUTES, FILE_ATTRIBUTE_NORMAL,
4372                                    FILE_SHARE_NONE, FILE_OVERWRITE_IF, 0, 0, &fnum1))) {
4373                 printf("TEST #3 open 1 of %s failed (%s)\n", fname, cli_errstr(cli1));
4374                 return False;
4375         }
4376
4377         if (!NT_STATUS_IS_OK(cli_ntcreate(cli2, fname, 0, DELETE_ACCESS|FILE_READ_ATTRIBUTES, FILE_ATTRIBUTE_NORMAL,
4378                                    FILE_SHARE_NONE, FILE_OPEN_IF, 0, 0, &fnum2))) {
4379                 printf("TEST #3 open 2 of %s failed (%s)\n", fname, cli_errstr(cli2));
4380                 return False;
4381         }
4382
4383         if (!NT_STATUS_IS_OK(cli_close(cli1, fnum1))) {
4384                 printf("TEST #3 close 1 of %s failed (%s)\n", fname, cli_errstr(cli1));
4385                 return False;
4386         }
4387         if (!NT_STATUS_IS_OK(cli_close(cli2, fnum2))) {
4388                 printf("TEST #3 close 2 of %s failed (%s)\n", fname, cli_errstr(cli2));
4389                 return False;
4390         }
4391
4392         printf("non-io open test #3 passed.\n");
4393
4394         cli_unlink(cli1, fname, aSYSTEM | aHIDDEN);
4395
4396         printf("TEST #4 testing 2 non-io opens (both with delete)\n");
4397
4398         if (!NT_STATUS_IS_OK(cli_ntcreate(cli1, fname, 0, DELETE_ACCESS|FILE_READ_ATTRIBUTES, FILE_ATTRIBUTE_NORMAL,
4399                                    FILE_SHARE_NONE, FILE_OVERWRITE_IF, 0, 0, &fnum1))) {
4400                 printf("TEST #4 open 1 of %s failed (%s)\n", fname, cli_errstr(cli1));
4401                 return False;
4402         }
4403
4404         if (NT_STATUS_IS_OK(cli_ntcreate(cli2, fname, 0, DELETE_ACCESS|FILE_READ_ATTRIBUTES, FILE_ATTRIBUTE_NORMAL,
4405                                    FILE_SHARE_NONE, FILE_OPEN_IF, 0, 0, &fnum2))) {
4406                 printf("TEST #4 open 2 of %s SUCCEEDED - should have failed (%s)\n", fname, cli_errstr(cli2));
4407                 return False;
4408         }
4409
4410         printf("TEST #4 open 2 of %s gave %s (correct error should be %s)\n", fname, cli_errstr(cli2), "sharing violation");
4411
4412         if (!NT_STATUS_IS_OK(cli_close(cli1, fnum1))) {
4413                 printf("TEST #4 close 1 of %s failed (%s)\n", fname, cli_errstr(cli1));
4414                 return False;
4415         }
4416
4417         printf("non-io open test #4 passed.\n");
4418
4419         cli_unlink(cli1, fname, aSYSTEM | aHIDDEN);
4420
4421         printf("TEST #5 testing 2 non-io opens (both with delete - both with file share delete)\n");
4422
4423         if (!NT_STATUS_IS_OK(cli_ntcreate(cli1, fname, 0, DELETE_ACCESS|FILE_READ_ATTRIBUTES, FILE_ATTRIBUTE_NORMAL,
4424                                    FILE_SHARE_DELETE, FILE_OVERWRITE_IF, 0, 0, &fnum1))) {
4425                 printf("TEST #5 open 1 of %s failed (%s)\n", fname, cli_errstr(cli1));
4426                 return False;
4427         }
4428
4429         if (!NT_STATUS_IS_OK(cli_ntcreate(cli2, fname, 0, DELETE_ACCESS|FILE_READ_ATTRIBUTES, FILE_ATTRIBUTE_NORMAL,
4430                                    FILE_SHARE_DELETE, FILE_OPEN_IF, 0, 0, &fnum2))) {
4431                 printf("TEST #5 open 2 of %s failed (%s)\n", fname, cli_errstr(cli2));
4432                 return False;
4433         }
4434
4435         if (!NT_STATUS_IS_OK(cli_close(cli1, fnum1))) {
4436                 printf("TEST #5 close 1 of %s failed (%s)\n", fname, cli_errstr(cli1));
4437                 return False;
4438         }
4439
4440         if (!NT_STATUS_IS_OK(cli_close(cli2, fnum2))) {
4441                 printf("TEST #5 close 2 of %s failed (%s)\n", fname, cli_errstr(cli2));
4442                 return False;
4443         }
4444
4445         printf("non-io open test #5 passed.\n");
4446
4447         printf("TEST #6 testing 1 non-io open, one io open\n");
4448
4449         cli_unlink(cli1, fname, aSYSTEM | aHIDDEN);
4450
4451         if (!NT_STATUS_IS_OK(cli_ntcreate(cli1, fname, 0, FILE_READ_DATA, FILE_ATTRIBUTE_NORMAL,
4452                                    FILE_SHARE_NONE, FILE_OVERWRITE_IF, 0, 0, &fnum1))) {
4453                 printf("TEST #6 open 1 of %s failed (%s)\n", fname, cli_errstr(cli1));
4454                 return False;
4455         }
4456
4457         if (!NT_STATUS_IS_OK(cli_ntcreate(cli2, fname, 0, FILE_READ_ATTRIBUTES, FILE_ATTRIBUTE_NORMAL,
4458                                    FILE_SHARE_READ, FILE_OPEN_IF, 0, 0, &fnum2))) {
4459                 printf("TEST #6 open 2 of %s failed (%s)\n", fname, cli_errstr(cli2));
4460                 return False;
4461         }
4462
4463         if (!NT_STATUS_IS_OK(cli_close(cli1, fnum1))) {
4464                 printf("TEST #6 close 1 of %s failed (%s)\n", fname, cli_errstr(cli1));
4465                 return False;
4466         }
4467
4468         if (!NT_STATUS_IS_OK(cli_close(cli2, fnum2))) {
4469                 printf("TEST #6 close 2 of %s failed (%s)\n", fname, cli_errstr(cli2));
4470                 return False;
4471         }
4472
4473         printf("non-io open test #6 passed.\n");
4474
4475         printf("TEST #7 testing 1 non-io open, one io open with delete\n");
4476
4477         cli_unlink(cli1, fname, aSYSTEM | aHIDDEN);
4478
4479         if (!NT_STATUS_IS_OK(cli_ntcreate(cli1, fname, 0, FILE_READ_DATA, FILE_ATTRIBUTE_NORMAL,
4480                                    FILE_SHARE_NONE, FILE_OVERWRITE_IF, 0, 0, &fnum1))) {
4481                 printf("TEST #7 open 1 of %s failed (%s)\n", fname, cli_errstr(cli1));
4482                 return False;
4483         }
4484
4485         if (NT_STATUS_IS_OK(cli_ntcreate(cli2, fname, 0, DELETE_ACCESS|FILE_READ_ATTRIBUTES, FILE_ATTRIBUTE_NORMAL,
4486                                    FILE_SHARE_READ|FILE_SHARE_DELETE, FILE_OPEN_IF, 0, 0, &fnum2))) {
4487                 printf("TEST #7 open 2 of %s SUCCEEDED - should have failed (%s)\n", fname, cli_errstr(cli2));
4488                 return False;
4489         }
4490
4491         printf("TEST #7 open 2 of %s gave %s (correct error should be %s)\n", fname, cli_errstr(cli2), "sharing violation");
4492
4493         if (!NT_STATUS_IS_OK(cli_close(cli1, fnum1))) {
4494                 printf("TEST #7 close 1 of %s failed (%s)\n", fname, cli_errstr(cli1));
4495                 return False;
4496         }
4497
4498         printf("non-io open test #7 passed.\n");
4499
4500         cli_unlink(cli1, fname, aSYSTEM | aHIDDEN);
4501
4502         if (!torture_close_connection(cli1)) {
4503                 correct = False;
4504         }
4505         if (!torture_close_connection(cli2)) {
4506                 correct = False;
4507         }
4508
4509         return correct;
4510 }
4511
4512 NTSTATUS torture_setup_unix_extensions(struct cli_state *cli)
4513 {
4514         uint16 major, minor;
4515         uint32 caplow, caphigh;
4516         NTSTATUS status;
4517
4518         if (!SERVER_HAS_UNIX_CIFS(cli)) {
4519                 printf("Server doesn't support UNIX CIFS extensions.\n");
4520                 return NT_STATUS_NOT_SUPPORTED;
4521         }
4522
4523         status = cli_unix_extensions_version(cli, &major, &minor, &caplow,
4524                                              &caphigh);
4525         if (!NT_STATUS_IS_OK(status)) {
4526                 printf("Server didn't return UNIX CIFS extensions: %s\n",
4527                        nt_errstr(status));
4528                 return status;
4529         }
4530
4531         status = cli_set_unix_extensions_capabilities(cli, major, minor,
4532                                                       caplow, caphigh);
4533         if (!NT_STATUS_IS_OK(status)) {
4534                 printf("Server doesn't support setting UNIX CIFS extensions: "
4535                        "%s.\n", nt_errstr(status));
4536                 return status;
4537         }
4538
4539         return NT_STATUS_OK;
4540 }
4541
4542 /*
4543   Test POSIX open /mkdir calls.
4544  */
4545 static bool run_simple_posix_open_test(int dummy)
4546 {
4547         static struct cli_state *cli1;
4548         const char *fname = "posix:file";
4549         const char *hname = "posix:hlink";
4550         const char *sname = "posix:symlink";
4551         const char *dname = "posix:dir";
4552         char buf[10];
4553         char namebuf[11];
4554         uint16_t fnum1 = (uint16_t)-1;
4555         SMB_STRUCT_STAT sbuf;
4556         bool correct = false;
4557         NTSTATUS status;
4558
4559         printf("Starting simple POSIX open test\n");
4560
4561         if (!torture_open_connection(&cli1, 0)) {
4562                 return false;
4563         }
4564
4565         cli_sockopt(cli1, sockops);
4566
4567         status = torture_setup_unix_extensions(cli1);
4568         if (!NT_STATUS_IS_OK(status)) {
4569                 return false;
4570         }
4571
4572         cli_setatr(cli1, fname, 0, 0);
4573         cli_posix_unlink(cli1, fname);
4574         cli_setatr(cli1, dname, 0, 0);
4575         cli_posix_rmdir(cli1, dname);
4576         cli_setatr(cli1, hname, 0, 0);
4577         cli_posix_unlink(cli1, hname);
4578         cli_setatr(cli1, sname, 0, 0);
4579         cli_posix_unlink(cli1, sname);
4580
4581         /* Create a directory. */
4582         if (!NT_STATUS_IS_OK(cli_posix_mkdir(cli1, dname, 0777))) {
4583                 printf("POSIX mkdir of %s failed (%s)\n", dname, cli_errstr(cli1));
4584                 goto out;
4585         }
4586
4587         if (!NT_STATUS_IS_OK(cli_posix_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL, 0600, &fnum1))) {
4588                 printf("POSIX create of %s failed (%s)\n", fname, cli_errstr(cli1));
4589                 goto out;
4590         }
4591
4592         /* Test ftruncate - set file size. */
4593         if (!NT_STATUS_IS_OK(cli_ftruncate(cli1, fnum1, 1000))) {
4594                 printf("ftruncate failed (%s)\n", cli_errstr(cli1));
4595                 goto out;
4596         }
4597
4598         /* Ensure st_size == 1000 */
4599         if (!NT_STATUS_IS_OK(cli_posix_stat(cli1, fname, &sbuf))) {
4600                 printf("stat failed (%s)\n", cli_errstr(cli1));
4601                 goto out;
4602         }
4603
4604         if (sbuf.st_ex_size != 1000) {
4605                 printf("ftruncate - stat size (%u) != 1000\n", (unsigned int)sbuf.st_ex_size);
4606                 goto out;
4607         }
4608
4609         /* Test ftruncate - set file size back to zero. */
4610         if (!NT_STATUS_IS_OK(cli_ftruncate(cli1, fnum1, 0))) {
4611                 printf("ftruncate failed (%s)\n", cli_errstr(cli1));
4612                 goto out;
4613         }
4614
4615         if (!NT_STATUS_IS_OK(cli_close(cli1, fnum1))) {
4616                 printf("close failed (%s)\n", cli_errstr(cli1));
4617                 goto out;
4618         }
4619
4620         /* Now open the file again for read only. */
4621         if (!NT_STATUS_IS_OK(cli_posix_open(cli1, fname, O_RDONLY, 0, &fnum1))) {
4622                 printf("POSIX open of %s failed (%s)\n", fname, cli_errstr(cli1));
4623                 goto out;
4624         }
4625
4626         /* Now unlink while open. */
4627         if (!NT_STATUS_IS_OK(cli_posix_unlink(cli1, fname))) {
4628                 printf("POSIX unlink of %s failed (%s)\n", fname, cli_errstr(cli1));
4629                 goto out;
4630         }
4631
4632         if (!NT_STATUS_IS_OK(cli_close(cli1, fnum1))) {
4633                 printf("close(2) failed (%s)\n", cli_errstr(cli1));
4634                 goto out;
4635         }
4636
4637         /* Ensure the file has gone. */
4638         if (NT_STATUS_IS_OK(cli_posix_open(cli1, fname, O_RDONLY, 0, &fnum1))) {
4639                 printf("POSIX open of %s succeeded, should have been deleted.\n", fname);
4640                 goto out;
4641         }
4642
4643         /* What happens when we try and POSIX open a directory ? */
4644         if (NT_STATUS_IS_OK(cli_posix_open(cli1, dname, O_RDONLY, 0, &fnum1))) {
4645                 printf("POSIX open of directory %s succeeded, should have failed.\n", fname);
4646                 goto out;
4647         } else {
4648                 if (!check_error(__LINE__, cli1, ERRDOS, EISDIR,
4649                                 NT_STATUS_FILE_IS_A_DIRECTORY)) {
4650                         goto out;
4651                 }
4652         }
4653
4654         /* Create the file. */
4655         if (!NT_STATUS_IS_OK(cli_posix_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL, 0600, &fnum1))) {
4656                 printf("POSIX create of %s failed (%s)\n", fname, cli_errstr(cli1));
4657                 goto out;
4658         }
4659
4660         /* Write some data into it. */
4661         if (cli_write(cli1, fnum1, 0, "TEST DATA\n", 0, 10) != 10) {
4662                 printf("cli_write failed: %s\n", cli_errstr(cli1));
4663                 goto out;
4664         }
4665
4666         cli_close(cli1, fnum1);
4667
4668         /* Now create a hardlink. */
4669         if (!NT_STATUS_IS_OK(cli_posix_hardlink(cli1, fname, hname))) {
4670                 printf("POSIX hardlink of %s failed (%s)\n", hname, cli_errstr(cli1));
4671                 goto out;
4672         }
4673
4674         /* Now create a symlink. */
4675         if (!NT_STATUS_IS_OK(cli_posix_symlink(cli1, fname, sname))) {
4676                 printf("POSIX symlink of %s failed (%s)\n", sname, cli_errstr(cli1));
4677                 goto out;
4678         }
4679
4680         /* Open the hardlink for read. */
4681         if (!NT_STATUS_IS_OK(cli_posix_open(cli1, hname, O_RDONLY, 0, &fnum1))) {
4682                 printf("POSIX open of %s failed (%s)\n", hname, cli_errstr(cli1));
4683                 goto out;
4684         }
4685
4686         if (cli_read(cli1, fnum1, buf, 0, 10) != 10) {
4687                 printf("POSIX read of %s failed (%s)\n", hname, cli_errstr(cli1));
4688                 goto out;
4689         }
4690
4691         if (memcmp(buf, "TEST DATA\n", 10)) {
4692                 printf("invalid data read from hardlink\n");
4693                 goto out;
4694         }
4695
4696         /* Do a POSIX lock/unlock. */
4697         if (!NT_STATUS_IS_OK(cli_posix_lock(cli1, fnum1, 0, 100, true, READ_LOCK))) {
4698                 printf("POSIX lock failed %s\n", cli_errstr(cli1));
4699                 goto out;
4700         }
4701
4702         /* Punch a hole in the locked area. */
4703         if (!NT_STATUS_IS_OK(cli_posix_unlock(cli1, fnum1, 10, 80))) {
4704                 printf("POSIX unlock failed %s\n", cli_errstr(cli1));
4705                 goto out;
4706         }
4707
4708         cli_close(cli1, fnum1);
4709
4710         /* Open the symlink for read - this should fail. A POSIX
4711            client should not be doing opens on a symlink. */
4712         if (NT_STATUS_IS_OK(cli_posix_open(cli1, sname, O_RDONLY, 0, &fnum1))) {
4713                 printf("POSIX open of %s succeeded (should have failed)\n", sname);
4714                 goto out;
4715         } else {
4716                 if (!check_error(__LINE__, cli1, ERRDOS, ERRbadpath,
4717                                 NT_STATUS_OBJECT_PATH_NOT_FOUND)) {
4718                         printf("POSIX open of %s should have failed "
4719                                 "with NT_STATUS_OBJECT_PATH_NOT_FOUND, "
4720                                 "failed with %s instead.\n",
4721                                 sname, cli_errstr(cli1));
4722                         goto out;
4723                 }
4724         }
4725
4726         if (!NT_STATUS_IS_OK(cli_posix_readlink(cli1, sname, namebuf, sizeof(namebuf)))) {
4727                 printf("POSIX readlink on %s failed (%s)\n", sname, cli_errstr(cli1));
4728                 goto out;
4729         }
4730
4731         if (strcmp(namebuf, fname) != 0) {
4732                 printf("POSIX readlink on %s failed to match name %s (read %s)\n",
4733                         sname, fname, namebuf);
4734                 goto out;
4735         }
4736
4737         if (!NT_STATUS_IS_OK(cli_posix_rmdir(cli1, dname))) {
4738                 printf("POSIX rmdir failed (%s)\n", cli_errstr(cli1));
4739                 goto out;
4740         }
4741
4742         printf("Simple POSIX open test passed\n");
4743         correct = true;
4744
4745   out:
4746
4747         if (fnum1 != (uint16_t)-1) {
4748                 cli_close(cli1, fnum1);
4749                 fnum1 = (uint16_t)-1;
4750         }
4751
4752         cli_setatr(cli1, sname, 0, 0);
4753         cli_posix_unlink(cli1, sname);
4754         cli_setatr(cli1, hname, 0, 0);
4755         cli_posix_unlink(cli1, hname);
4756         cli_setatr(cli1, fname, 0, 0);
4757         cli_posix_unlink(cli1, fname);
4758         cli_setatr(cli1, dname, 0, 0);
4759         cli_posix_rmdir(cli1, dname);
4760
4761         if (!torture_close_connection(cli1)) {
4762                 correct = false;
4763         }
4764
4765         return correct;
4766 }
4767
4768
4769 static uint32 open_attrs_table[] = {
4770                 FILE_ATTRIBUTE_NORMAL,
4771                 FILE_ATTRIBUTE_ARCHIVE,
4772                 FILE_ATTRIBUTE_READONLY,
4773                 FILE_ATTRIBUTE_HIDDEN,
4774                 FILE_ATTRIBUTE_SYSTEM,
4775
4776                 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY,
4777                 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN,
4778                 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM,
4779                 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN,
4780                 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM,
4781                 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM,
4782
4783                 FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN,
4784                 FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM,
4785                 FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM,
4786                 FILE_ATTRIBUTE_HIDDEN,FILE_ATTRIBUTE_SYSTEM,
4787 };
4788
4789 struct trunc_open_results {
4790         unsigned int num;
4791         uint32 init_attr;
4792         uint32 trunc_attr;
4793         uint32 result_attr;
4794 };
4795
4796 static struct trunc_open_results attr_results[] = {
4797         { 0, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_ARCHIVE },
4798         { 1, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_ARCHIVE },
4799         { 2, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_READONLY, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY },
4800         { 16, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_ARCHIVE },
4801         { 17, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_ARCHIVE },
4802         { 18, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_READONLY, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY },
4803         { 51, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
4804         { 54, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
4805         { 56, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN },
4806         { 68, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
4807         { 71, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
4808         { 73, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM },
4809         { 99, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_HIDDEN,FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
4810         { 102, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
4811         { 104, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN },
4812         { 116, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
4813         { 119,  FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM,  FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
4814         { 121, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM },
4815         { 170, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM|FILE_ATTRIBUTE_HIDDEN },
4816         { 173, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM },
4817         { 227, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
4818         { 230, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
4819         { 232, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN },
4820         { 244, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
4821         { 247, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
4822         { 249, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM }
4823 };
4824
4825 static bool run_openattrtest(int dummy)
4826 {
4827         static struct cli_state *cli1;
4828         const char *fname = "\\openattr.file";
4829         uint16_t fnum1;
4830         bool correct = True;
4831         uint16 attr;
4832         unsigned int i, j, k, l;
4833
4834         printf("starting open attr test\n");
4835
4836         if (!torture_open_connection(&cli1, 0)) {
4837                 return False;
4838         }
4839
4840         cli_sockopt(cli1, sockops);
4841
4842         for (k = 0, i = 0; i < sizeof(open_attrs_table)/sizeof(uint32); i++) {
4843                 cli_setatr(cli1, fname, 0, 0);
4844                 cli_unlink(cli1, fname, aSYSTEM | aHIDDEN);
4845                 if (!NT_STATUS_IS_OK(cli_ntcreate(cli1, fname, 0, FILE_WRITE_DATA, open_attrs_table[i],
4846                                    FILE_SHARE_NONE, FILE_OVERWRITE_IF, 0, 0, &fnum1))) {
4847                         printf("open %d (1) of %s failed (%s)\n", i, fname, cli_errstr(cli1));
4848                         return False;
4849                 }
4850
4851                 if (!NT_STATUS_IS_OK(cli_close(cli1, fnum1))) {
4852                         printf("close %d (1) of %s failed (%s)\n", i, fname, cli_errstr(cli1));
4853                         return False;
4854                 }
4855
4856                 for (j = 0; j < sizeof(open_attrs_table)/sizeof(uint32); j++) {
4857                         if (!NT_STATUS_IS_OK(cli_ntcreate(cli1, fname, 0, FILE_READ_DATA|FILE_WRITE_DATA, open_attrs_table[j],
4858                                            FILE_SHARE_NONE, FILE_OVERWRITE, 0, 0, &fnum1))) {
4859                                 for (l = 0; l < sizeof(attr_results)/sizeof(struct trunc_open_results); l++) {
4860                                         if (attr_results[l].num == k) {
4861                                                 printf("[%d] trunc open 0x%x -> 0x%x of %s failed - should have succeeded !(0x%x:%s)\n",
4862                                                                 k, open_attrs_table[i],
4863                                                                 open_attrs_table[j],
4864                                                                 fname, NT_STATUS_V(cli_nt_error(cli1)), cli_errstr(cli1));
4865                                                 correct = False;
4866                                         }
4867                                 }
4868                                 if (NT_STATUS_V(cli_nt_error(cli1)) != NT_STATUS_V(NT_STATUS_ACCESS_DENIED)) {
4869                                         printf("[%d] trunc open 0x%x -> 0x%x failed with wrong error code %s\n",
4870                                                         k, open_attrs_table[i], open_attrs_table[j],
4871                                                         cli_errstr(cli1));
4872                                         correct = False;
4873                                 }
4874 #if 0
4875                                 printf("[%d] trunc open 0x%x -> 0x%x failed\n", k, open_attrs_table[i], open_attrs_table[j]);
4876 #endif
4877                                 k++;
4878                                 continue;
4879                         }
4880
4881                         if (!NT_STATUS_IS_OK(cli_close(cli1, fnum1))) {
4882                                 printf("close %d (2) of %s failed (%s)\n", j, fname, cli_errstr(cli1));
4883                                 return False;
4884                         }
4885
4886                         if (!NT_STATUS_IS_OK(cli_getatr(cli1, fname, &attr, NULL, NULL))) {
4887                                 printf("getatr(2) failed (%s)\n", cli_errstr(cli1));
4888                                 return False;
4889                         }
4890
4891 #if 0
4892                         printf("[%d] getatr check [0x%x] trunc [0x%x] got attr 0x%x\n",
4893                                         k,  open_attrs_table[i],  open_attrs_table[j], attr );
4894 #endif
4895
4896                         for (l = 0; l < sizeof(attr_results)/sizeof(struct trunc_open_results); l++) {
4897                                 if (attr_results[l].num == k) {
4898                                         if (attr != attr_results[l].result_attr ||
4899                                                         open_attrs_table[i] != attr_results[l].init_attr ||
4900                                                         open_attrs_table[j] != attr_results[l].trunc_attr) {
4901                                                 printf("getatr check failed. [0x%x] trunc [0x%x] got attr 0x%x, should be 0x%x\n",
4902                                                 open_attrs_table[i],
4903                                                 open_attrs_table[j],
4904                                                 (unsigned int)attr,
4905                                                 attr_results[l].result_attr);
4906                                                 correct = False;
4907                                         }
4908                                         break;
4909                                 }
4910                         }
4911                         k++;
4912                 }
4913         }
4914
4915         cli_setatr(cli1, fname, 0, 0);
4916         cli_unlink(cli1, fname, aSYSTEM | aHIDDEN);
4917
4918         printf("open attr test %s.\n", correct ? "passed" : "failed");
4919
4920         if (!torture_close_connection(cli1)) {
4921                 correct = False;
4922         }
4923         return correct;
4924 }
4925
4926 static NTSTATUS list_fn(const char *mnt, struct file_info *finfo,
4927                     const char *name, void *state)
4928 {
4929         int *matched = (int *)state;
4930         if (matched != NULL) {
4931                 *matched += 1;
4932         }
4933         return NT_STATUS_OK;
4934 }
4935
4936 /*
4937   test directory listing speed
4938  */
4939 static bool run_dirtest(int dummy)
4940 {
4941         int i;
4942         static struct cli_state *cli;
4943         uint16_t fnum;
4944         struct timeval core_start;
4945         bool correct = True;
4946         int matched;
4947
4948         printf("starting directory test\n");
4949
4950         if (!torture_open_connection(&cli, 0)) {
4951                 return False;
4952         }
4953
4954         cli_sockopt(cli, sockops);
4955
4956         srandom(0);
4957         for (i=0;i<torture_numops;i++) {
4958                 fstring fname;
4959                 slprintf(fname, sizeof(fname), "\\%x", (int)random());
4960                 if (!NT_STATUS_IS_OK(cli_open(cli, fname, O_RDWR|O_CREAT, DENY_NONE, &fnum))) {
4961                         fprintf(stderr,"Failed to open %s\n", fname);
4962                         return False;
4963                 }
4964                 cli_close(cli, fnum);
4965         }
4966
4967         core_start = timeval_current();
4968
4969         matched = 0;
4970         cli_list(cli, "a*.*", 0, list_fn, &matched);
4971         printf("Matched %d\n", matched);
4972
4973         matched = 0;
4974         cli_list(cli, "b*.*", 0, list_fn, &matched);
4975         printf("Matched %d\n", matched);
4976
4977         matched = 0;
4978         cli_list(cli, "xyzabc", 0, list_fn, &matched);
4979         printf("Matched %d\n", matched);
4980
4981         printf("dirtest core %g seconds\n", timeval_elapsed(&core_start));
4982
4983         srandom(0);
4984         for (i=0;i<torture_numops;i++) {
4985                 fstring fname;
4986                 slprintf(fname, sizeof(fname), "\\%x", (int)random());
4987                 cli_unlink(cli, fname, aSYSTEM | aHIDDEN);
4988         }
4989
4990         if (!torture_close_connection(cli)) {
4991                 correct = False;
4992         }
4993
4994         printf("finished dirtest\n");
4995
4996         return correct;
4997 }
4998
4999 static NTSTATUS del_fn(const char *mnt, struct file_info *finfo, const char *mask,
5000                    void *state)
5001 {
5002         struct cli_state *pcli = (struct cli_state *)state;
5003         fstring fname;
5004         slprintf(fname, sizeof(fname), "\\LISTDIR\\%s", finfo->name);
5005
5006         if (strcmp(finfo->name, ".") == 0 || strcmp(finfo->name, "..") == 0)
5007                 return NT_STATUS_OK;
5008
5009         if (finfo->mode & aDIR) {
5010                 if (!NT_STATUS_IS_OK(cli_rmdir(pcli, fname)))
5011                         printf("del_fn: failed to rmdir %s\n,", fname );
5012         } else {
5013                 if (!NT_STATUS_IS_OK(cli_unlink(pcli, fname, aSYSTEM | aHIDDEN)))
5014                         printf("del_fn: failed to unlink %s\n,", fname );
5015         }
5016         return NT_STATUS_OK;
5017 }
5018
5019
5020 /*
5021   sees what IOCTLs are supported
5022  */
5023 bool torture_ioctl_test(int dummy)
5024 {
5025         static struct cli_state *cli;
5026         uint16_t device, function;
5027         uint16_t fnum;
5028         const char *fname = "\\ioctl.dat";
5029         DATA_BLOB blob;
5030         NTSTATUS status;
5031
5032         if (!torture_open_connection(&cli, 0)) {
5033                 return False;
5034         }
5035
5036         printf("starting ioctl test\n");
5037
5038         cli_unlink(cli, fname, aSYSTEM | aHIDDEN);
5039
5040         if (!NT_STATUS_IS_OK(cli_open(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum))) {
5041                 printf("open of %s failed (%s)\n", fname, cli_errstr(cli));
5042                 return False;
5043         }
5044
5045         status = cli_raw_ioctl(cli, fnum, 0x2d0000 | (0x0420<<2), &blob);
5046         printf("ioctl device info: %s\n", nt_errstr(status));
5047
5048         status = cli_raw_ioctl(cli, fnum, IOCTL_QUERY_JOB_INFO, &blob);
5049         printf("ioctl job info: %s\n", nt_errstr(status));
5050
5051         for (device=0;device<0x100;device++) {
5052                 printf("ioctl test with device = 0x%x\n", device);
5053                 for (function=0;function<0x100;function++) {
5054                         uint32 code = (device<<16) | function;
5055
5056                         status = cli_raw_ioctl(cli, fnum, code, &blob);
5057
5058                         if (NT_STATUS_IS_OK(status)) {
5059                                 printf("ioctl 0x%x OK : %d bytes\n", (int)code,
5060                                        (int)blob.length);
5061                                 data_blob_free(&blob);
5062                         }
5063                 }
5064         }
5065
5066         if (!torture_close_connection(cli)) {
5067                 return False;
5068         }
5069
5070         return True;
5071 }
5072
5073
5074 /*
5075   tries varients of chkpath
5076  */
5077 bool torture_chkpath_test(int dummy)
5078 {
5079         static struct cli_state *cli;
5080         uint16_t fnum;
5081         bool ret;
5082
5083         if (!torture_open_connection(&cli, 0)) {
5084                 return False;
5085         }
5086
5087         printf("starting chkpath test\n");
5088
5089         /* cleanup from an old run */
5090         cli_rmdir(cli, "\\chkpath.dir\\dir2");
5091         cli_unlink(cli, "\\chkpath.dir\\*", aSYSTEM | aHIDDEN);
5092         cli_rmdir(cli, "\\chkpath.dir");
5093
5094         if (!NT_STATUS_IS_OK(cli_mkdir(cli, "\\chkpath.dir"))) {
5095                 printf("mkdir1 failed : %s\n", cli_errstr(cli));
5096                 return False;
5097         }
5098
5099         if (!NT_STATUS_IS_OK(cli_mkdir(cli, "\\chkpath.dir\\dir2"))) {
5100                 printf("mkdir2 failed : %s\n", cli_errstr(cli));
5101                 return False;
5102         }
5103
5104         if (!NT_STATUS_IS_OK(cli_open(cli, "\\chkpath.dir\\foo.txt", O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum))) {
5105                 printf("open1 failed (%s)\n", cli_errstr(cli));
5106                 return False;
5107         }
5108         cli_close(cli, fnum);
5109
5110         if (!NT_STATUS_IS_OK(cli_chkpath(cli, "\\chkpath.dir"))) {
5111                 printf("chkpath1 failed: %s\n", cli_errstr(cli));
5112                 ret = False;
5113         }
5114
5115         if (!NT_STATUS_IS_OK(cli_chkpath(cli, "\\chkpath.dir\\dir2"))) {
5116                 printf("chkpath2 failed: %s\n", cli_errstr(cli));
5117                 ret = False;
5118         }
5119
5120         if (!NT_STATUS_IS_OK(cli_chkpath(cli, "\\chkpath.dir\\foo.txt"))) {
5121                 ret = check_error(__LINE__, cli, ERRDOS, ERRbadpath, 
5122                                   NT_STATUS_NOT_A_DIRECTORY);
5123         } else {
5124                 printf("* chkpath on a file should fail\n");
5125                 ret = False;
5126         }
5127
5128         if (!NT_STATUS_IS_OK(cli_chkpath(cli, "\\chkpath.dir\\bar.txt"))) {
5129                 ret = check_error(__LINE__, cli, ERRDOS, ERRbadfile, 
5130                                   NT_STATUS_OBJECT_NAME_NOT_FOUND);
5131         } else {
5132                 printf("* chkpath on a non existant file should fail\n");
5133                 ret = False;
5134         }
5135
5136         if (!NT_STATUS_IS_OK(cli_chkpath(cli, "\\chkpath.dir\\dirxx\\bar.txt"))) {
5137                 ret = check_error(__LINE__, cli, ERRDOS, ERRbadpath, 
5138                                   NT_STATUS_OBJECT_PATH_NOT_FOUND);
5139         } else {
5140                 printf("* chkpath on a non existent component should fail\n");
5141                 ret = False;
5142         }
5143
5144         cli_rmdir(cli, "\\chkpath.dir\\dir2");
5145         cli_unlink(cli, "\\chkpath.dir\\*", aSYSTEM | aHIDDEN);
5146         cli_rmdir(cli, "\\chkpath.dir");
5147
5148         if (!torture_close_connection(cli)) {
5149                 return False;
5150         }
5151
5152         return ret;
5153 }
5154
5155 static bool run_eatest(int dummy)
5156 {
5157         static struct cli_state *cli;
5158         const char *fname = "\\eatest.txt";
5159         bool correct = True;
5160         uint16_t fnum;
5161         int i;
5162         size_t num_eas;
5163         struct ea_struct *ea_list = NULL;
5164         TALLOC_CTX *mem_ctx = talloc_init("eatest");
5165         NTSTATUS status;
5166
5167         printf("starting eatest\n");
5168
5169         if (!torture_open_connection(&cli, 0)) {
5170                 talloc_destroy(mem_ctx);
5171                 return False;
5172         }
5173
5174         cli_unlink(cli, fname, aSYSTEM | aHIDDEN);
5175         if (!NT_STATUS_IS_OK(cli_ntcreate(cli, fname, 0,
5176                                    FIRST_DESIRED_ACCESS, FILE_ATTRIBUTE_ARCHIVE,
5177                                    FILE_SHARE_NONE, FILE_OVERWRITE_IF, 
5178                                    0x4044, 0, &fnum))) {
5179                 printf("open failed - %s\n", cli_errstr(cli));
5180                 talloc_destroy(mem_ctx);
5181                 return False;
5182         }
5183
5184         for (i = 0; i < 10; i++) {
5185                 fstring ea_name, ea_val;
5186
5187                 slprintf(ea_name, sizeof(ea_name), "EA_%d", i);
5188                 memset(ea_val, (char)i+1, i+1);
5189                 if (!cli_set_ea_fnum(cli, fnum, ea_name, ea_val, i+1)) {
5190                         printf("ea_set of name %s failed - %s\n", ea_name, cli_errstr(cli));
5191                         talloc_destroy(mem_ctx);
5192                         return False;
5193                 }
5194         }
5195
5196         cli_close(cli, fnum);
5197         for (i = 0; i < 10; i++) {
5198                 fstring ea_name, ea_val;
5199
5200                 slprintf(ea_name, sizeof(ea_name), "EA_%d", i+10);
5201                 memset(ea_val, (char)i+1, i+1);
5202                 if (!cli_set_ea_path(cli, fname, ea_name, ea_val, i+1)) {
5203                         printf("ea_set of name %s failed - %s\n", ea_name, cli_errstr(cli));
5204                         talloc_destroy(mem_ctx);
5205                         return False;
5206                 }
5207         }
5208
5209         status = cli_get_ea_list_path(cli, fname, mem_ctx, &num_eas, &ea_list);
5210         if (!NT_STATUS_IS_OK(status)) {
5211                 printf("ea_get list failed - %s\n", nt_errstr(status));
5212                 correct = False;
5213         }
5214
5215         printf("num_eas = %d\n", (int)num_eas);
5216
5217         if (num_eas != 20) {
5218                 printf("Should be 20 EA's stored... failing.\n");
5219                 correct = False;
5220         }
5221
5222         for (i = 0; i < num_eas; i++) {
5223                 printf("%d: ea_name = %s. Val = ", i, ea_list[i].name);
5224                 dump_data(0, ea_list[i].value.data,
5225                           ea_list[i].value.length);
5226         }
5227
5228         /* Setting EA's to zero length deletes them. Test this */
5229         printf("Now deleting all EA's - case indepenent....\n");
5230
5231 #if 1
5232         cli_set_ea_path(cli, fname, "", "", 0);
5233 #else
5234         for (i = 0; i < 20; i++) {
5235                 fstring ea_name;
5236                 slprintf(ea_name, sizeof(ea_name), "ea_%d", i);
5237                 if (!cli_set_ea_path(cli, fname, ea_name, "", 0)) {
5238                         printf("ea_set of name %s failed - %s\n", ea_name, cli_errstr(cli));
5239                         talloc_destroy(mem_ctx);
5240                         return False;
5241                 }
5242         }
5243 #endif
5244
5245         status = cli_get_ea_list_path(cli, fname, mem_ctx, &num_eas, &ea_list);
5246         if (!NT_STATUS_IS_OK(status)) {
5247                 printf("ea_get list failed - %s\n", nt_errstr(status));
5248                 correct = False;
5249         }
5250
5251         printf("num_eas = %d\n", (int)num_eas);
5252         for (i = 0; i < num_eas; i++) {
5253                 printf("%d: ea_name = %s. Val = ", i, ea_list[i].name);
5254                 dump_data(0, ea_list[i].value.data,
5255                           ea_list[i].value.length);
5256         }
5257
5258         if (num_eas != 0) {
5259                 printf("deleting EA's failed.\n");
5260                 correct = False;
5261         }
5262
5263         /* Try and delete a non existant EA. */
5264         if (!cli_set_ea_path(cli, fname, "foo", "", 0)) {
5265                 printf("deleting non-existant EA 'foo' should succeed. %s\n", cli_errstr(cli));
5266                 correct = False;
5267         }
5268
5269         talloc_destroy(mem_ctx);
5270         if (!torture_close_connection(cli)) {
5271                 correct = False;
5272         }
5273
5274         return correct;
5275 }
5276
5277 static bool run_dirtest1(int dummy)
5278 {
5279         int i;
5280         static struct cli_state *cli;
5281         uint16_t fnum;
5282         int num_seen;
5283         bool correct = True;
5284
5285         printf("starting directory test\n");
5286
5287         if (!torture_open_connection(&cli, 0)) {
5288                 return False;
5289         }
5290
5291         cli_sockopt(cli, sockops);
5292
5293         cli_list(cli, "\\LISTDIR\\*", 0, del_fn, cli);
5294         cli_list(cli, "\\LISTDIR\\*", aDIR, del_fn, cli);
5295         cli_rmdir(cli, "\\LISTDIR");
5296         cli_mkdir(cli, "\\LISTDIR");
5297
5298         /* Create 1000 files and 1000 directories. */
5299         for (i=0;i<1000;i++) {
5300                 fstring fname;
5301                 slprintf(fname, sizeof(fname), "\\LISTDIR\\f%d", i);
5302                 if (!NT_STATUS_IS_OK(cli_ntcreate(cli, fname, 0, GENERIC_ALL_ACCESS, FILE_ATTRIBUTE_ARCHIVE,
5303                                    FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OVERWRITE_IF, 0, 0, &fnum))) {
5304                         fprintf(stderr,"Failed to open %s\n", fname);
5305                         return False;
5306                 }
5307                 cli_close(cli, fnum);
5308         }
5309         for (i=0;i<1000;i++) {
5310                 fstring fname;
5311                 slprintf(fname, sizeof(fname), "\\LISTDIR\\d%d", i);
5312                 if (!NT_STATUS_IS_OK(cli_mkdir(cli, fname))) {
5313                         fprintf(stderr,"Failed to open %s\n", fname);
5314                         return False;
5315                 }
5316         }
5317
5318         /* Now ensure that doing an old list sees both files and directories. */
5319         num_seen = 0;
5320         cli_list_old(cli, "\\LISTDIR\\*", aDIR, list_fn, &num_seen);
5321         printf("num_seen = %d\n", num_seen );
5322         /* We should see 100 files + 1000 directories + . and .. */
5323         if (num_seen != 2002)
5324                 correct = False;
5325
5326         /* Ensure if we have the "must have" bits we only see the
5327          * relevent entries.
5328          */
5329         num_seen = 0;
5330         cli_list_old(cli, "\\LISTDIR\\*", (aDIR<<8)|aDIR, list_fn, &num_seen);
5331         printf("num_seen = %d\n", num_seen );
5332         if (num_seen != 1002)
5333                 correct = False;
5334
5335         num_seen = 0;
5336         cli_list_old(cli, "\\LISTDIR\\*", (aARCH<<8)|aDIR, list_fn, &num_seen);
5337         printf("num_seen = %d\n", num_seen );
5338         if (num_seen != 1000)
5339                 correct = False;
5340
5341         /* Delete everything. */
5342         cli_list(cli, "\\LISTDIR\\*", 0, del_fn, cli);
5343         cli_list(cli, "\\LISTDIR\\*", aDIR, del_fn, cli);
5344         cli_rmdir(cli, "\\LISTDIR");
5345
5346 #if 0
5347         printf("Matched %d\n", cli_list(cli, "a*.*", 0, list_fn, NULL));
5348         printf("Matched %d\n", cli_list(cli, "b*.*", 0, list_fn, NULL));
5349         printf("Matched %d\n", cli_list(cli, "xyzabc", 0, list_fn, NULL));
5350 #endif
5351
5352         if (!torture_close_connection(cli)) {
5353                 correct = False;
5354         }
5355
5356         printf("finished dirtest1\n");
5357
5358         return correct;
5359 }
5360
5361 static bool run_error_map_extract(int dummy) {
5362
5363         static struct cli_state *c_dos;
5364         static struct cli_state *c_nt;
5365         NTSTATUS status;
5366
5367         uint32 error;
5368
5369         uint32 flgs2, errnum;
5370         uint8 errclass;
5371
5372         NTSTATUS nt_status;
5373
5374         fstring user;
5375
5376         /* NT-Error connection */
5377
5378         if (!(c_nt = open_nbt_connection())) {
5379                 return False;
5380         }
5381
5382         c_nt->use_spnego = False;
5383
5384         status = cli_negprot(c_nt);
5385
5386         if (!NT_STATUS_IS_OK(status)) {
5387                 printf("%s rejected the NT-error negprot (%s)\n", host,
5388                        nt_errstr(status));
5389                 cli_shutdown(c_nt);
5390                 return False;
5391         }
5392
5393         if (!NT_STATUS_IS_OK(cli_session_setup(c_nt, "", "", 0, "", 0,
5394                                                workgroup))) {
5395                 printf("%s rejected the NT-error initial session setup (%s)\n",host, cli_errstr(c_nt));
5396                 return False;
5397         }
5398
5399         /* DOS-Error connection */
5400
5401         if (!(c_dos = open_nbt_connection())) {
5402                 return False;
5403         }
5404
5405         c_dos->use_spnego = False;
5406         c_dos->force_dos_errors = True;
5407
5408         status = cli_negprot(c_dos);
5409         if (!NT_STATUS_IS_OK(status)) {
5410                 printf("%s rejected the DOS-error negprot (%s)\n", host,
5411                        nt_errstr(status));
5412                 cli_shutdown(c_dos);
5413                 return False;
5414         }
5415
5416         if (!NT_STATUS_IS_OK(cli_session_setup(c_dos, "", "", 0, "", 0,
5417                                                workgroup))) {
5418                 printf("%s rejected the DOS-error initial session setup (%s)\n",host, cli_errstr(c_dos));
5419                 return False;
5420         }
5421
5422         for (error=(0xc0000000 | 0x1); error < (0xc0000000| 0xFFF); error++) {
5423                 fstr_sprintf(user, "%X", error);
5424
5425                 if (NT_STATUS_IS_OK(cli_session_setup(c_nt, user, 
5426                                                       password, strlen(password),
5427                                                       password, strlen(password),
5428                                                       workgroup))) {
5429                         printf("/** Session setup succeeded.  This shouldn't happen...*/\n");
5430                 }
5431
5432                 flgs2 = SVAL(c_nt->inbuf,smb_flg2);
5433
5434                 /* Case #1: 32-bit NT errors */
5435                 if (flgs2 & FLAGS2_32_BIT_ERROR_CODES) {
5436                         nt_status = NT_STATUS(IVAL(c_nt->inbuf,smb_rcls));
5437                 } else {
5438                         printf("/** Dos error on NT connection! (%s) */\n", 
5439                                cli_errstr(c_nt));
5440                         nt_status = NT_STATUS(0xc0000000);
5441                 }
5442
5443                 if (NT_STATUS_IS_OK(cli_session_setup(c_dos, user, 
5444                                                       password, strlen(password),
5445                                                       password, strlen(password),
5446                                                       workgroup))) {
5447                         printf("/** Session setup succeeded.  This shouldn't happen...*/\n");
5448                 }
5449                 flgs2 = SVAL(c_dos->inbuf,smb_flg2), errnum;
5450
5451                 /* Case #1: 32-bit NT errors */
5452                 if (flgs2 & FLAGS2_32_BIT_ERROR_CODES) {
5453                         printf("/** NT error on DOS connection! (%s) */\n", 
5454                                cli_errstr(c_nt));
5455                         errnum = errclass = 0;
5456                 } else {
5457                         cli_dos_error(c_dos, &errclass, &errnum);
5458                 }
5459
5460                 if (NT_STATUS_V(nt_status) != error) { 
5461                         printf("/*\t{ This NT error code was 'sqashed'\n\t from %s to %s \n\t during the session setup }\n*/\n", 
5462                                get_nt_error_c_code(NT_STATUS(error)), 
5463                                get_nt_error_c_code(nt_status));
5464                 }
5465
5466                 printf("\t{%s,\t%s,\t%s},\n", 
5467                        smb_dos_err_class(errclass), 
5468                        smb_dos_err_name(errclass, errnum), 
5469                        get_nt_error_c_code(NT_STATUS(error)));
5470         }
5471         return True;
5472 }
5473
5474 static bool run_sesssetup_bench(int dummy)
5475 {
5476         static struct cli_state *c;
5477         const char *fname = "\\file.dat";
5478         uint16_t fnum;
5479         NTSTATUS status;
5480         int i;
5481
5482         if (!torture_open_connection(&c, 0)) {
5483                 return false;
5484         }
5485
5486         if (!NT_STATUS_IS_OK(cli_ntcreate(
5487                         c, fname, 0, GENERIC_ALL_ACCESS|DELETE_ACCESS,
5488                         FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
5489                         FILE_DELETE_ON_CLOSE, 0, &fnum))) {
5490                 d_printf("open %s failed: %s\n", fname, cli_errstr(c));
5491                 return false;
5492         }
5493
5494         for (i=0; i<torture_numops; i++) {
5495                 status = cli_session_setup(
5496                         c, username,
5497                         password, strlen(password),
5498                         password, strlen(password),
5499                         workgroup);
5500                 if (!NT_STATUS_IS_OK(status)) {
5501                         d_printf("(%s) cli_session_setup failed: %s\n",
5502                                  __location__, nt_errstr(status));
5503                         return false;
5504                 }
5505
5506                 d_printf("\r%d   ", (int)c->vuid);
5507
5508                 status = cli_ulogoff(c);
5509                 if (!NT_STATUS_IS_OK(status)) {
5510                         d_printf("(%s) cli_ulogoff failed: %s\n",
5511                                  __location__, nt_errstr(status));
5512                         return false;
5513                 }
5514                 c->vuid = 0;
5515         }
5516
5517         return true;
5518 }
5519
5520 static bool subst_test(const char *str, const char *user, const char *domain,
5521                        uid_t uid, gid_t gid, const char *expected)
5522 {
5523         char *subst;
5524         bool result = true;
5525
5526         subst = talloc_sub_specified(talloc_tos(), str, user, domain, uid, gid);
5527
5528         if (strcmp(subst, expected) != 0) {
5529                 printf("sub_specified(%s, %s, %s, %d, %d) returned [%s], expected "
5530                        "[%s]\n", str, user, domain, (int)uid, (int)gid, subst,
5531                        expected);
5532                 result = false;
5533         }
5534
5535         TALLOC_FREE(subst);
5536         return result;
5537 }
5538
5539 static void chain1_open_completion(struct tevent_req *req)
5540 {
5541         uint16_t fnum;
5542         NTSTATUS status;
5543         status = cli_open_recv(req, &fnum);
5544         TALLOC_FREE(req);
5545
5546         d_printf("cli_open_recv returned %s: %d\n",
5547                  nt_errstr(status),
5548                  NT_STATUS_IS_OK(status) ? fnum : -1);
5549 }
5550
5551 static void chain1_write_completion(struct tevent_req *req)
5552 {
5553         size_t written;
5554         NTSTATUS status;
5555         status = cli_write_andx_recv(req, &written);
5556         TALLOC_FREE(req);
5557
5558         d_printf("cli_write_andx_recv returned %s: %d\n",
5559                  nt_errstr(status),
5560                  NT_STATUS_IS_OK(status) ? (int)written : -1);
5561 }
5562
5563 static void chain1_close_completion(struct tevent_req *req)
5564 {
5565         NTSTATUS status;
5566         bool *done = (bool *)tevent_req_callback_data_void(req);
5567
5568         status = cli_close_recv(req);
5569         *done = true;
5570
5571         TALLOC_FREE(req);
5572
5573         d_printf("cli_close returned %s\n", nt_errstr(status));
5574 }
5575
5576 static bool run_chain1(int dummy)
5577 {
5578         struct cli_state *cli1;
5579         struct event_context *evt = event_context_init(NULL);
5580         struct tevent_req *reqs[3], *smbreqs[3];
5581         bool done = false;
5582         const char *str = "foobar";
5583         NTSTATUS status;
5584
5585         printf("starting chain1 test\n");
5586         if (!torture_open_connection(&cli1, 0)) {
5587                 return False;
5588         }
5589
5590         cli_sockopt(cli1, sockops);
5591
5592         reqs[0] = cli_open_create(talloc_tos(), evt, cli1, "\\test",
5593                                   O_CREAT|O_RDWR, 0, &smbreqs[0]);
5594         if (reqs[0] == NULL) return false;
5595         tevent_req_set_callback(reqs[0], chain1_open_completion, NULL);
5596
5597
5598         reqs[1] = cli_write_andx_create(talloc_tos(), evt, cli1, 0, 0,
5599                                         (uint8_t *)str, 0, strlen(str)+1,
5600                                         smbreqs, 1, &smbreqs[1]);
5601         if (reqs[1] == NULL) return false;
5602         tevent_req_set_callback(reqs[1], chain1_write_completion, NULL);
5603
5604         reqs[2] = cli_close_create(talloc_tos(), evt, cli1, 0, &smbreqs[2]);
5605         if (reqs[2] == NULL) return false;
5606         tevent_req_set_callback(reqs[2], chain1_close_completion, &done);
5607
5608         status = cli_smb_chain_send(smbreqs, ARRAY_SIZE(smbreqs));
5609         if (!NT_STATUS_IS_OK(status)) {
5610                 return false;
5611         }
5612
5613         while (!done) {
5614                 event_loop_once(evt);
5615         }
5616
5617         torture_close_connection(cli1);
5618         return True;
5619 }
5620
5621 static void chain2_sesssetup_completion(struct tevent_req *req)
5622 {
5623         NTSTATUS status;
5624         status = cli_session_setup_guest_recv(req);
5625         d_printf("sesssetup returned %s\n", nt_errstr(status));
5626 }
5627
5628 static void chain2_tcon_completion(struct tevent_req *req)
5629 {
5630         bool *done = (bool *)tevent_req_callback_data_void(req);
5631         NTSTATUS status;
5632         status = cli_tcon_andx_recv(req);
5633         d_printf("tcon_and_x returned %s\n", nt_errstr(status));
5634         *done = true;
5635 }
5636
5637 static bool run_chain2(int dummy)
5638 {
5639         struct cli_state *cli1;
5640         struct event_context *evt = event_context_init(NULL);
5641         struct tevent_req *reqs[2], *smbreqs[2];
5642         bool done = false;
5643         NTSTATUS status;
5644
5645         printf("starting chain2 test\n");
5646         status = cli_start_connection(&cli1, global_myname(), host, NULL,
5647                                       port_to_use, Undefined, 0, NULL);
5648         if (!NT_STATUS_IS_OK(status)) {
5649                 return False;
5650         }
5651
5652         cli_sockopt(cli1, sockops);
5653
5654         reqs[0] = cli_session_setup_guest_create(talloc_tos(), evt, cli1,
5655                                                  &smbreqs[0]);
5656         if (reqs[0] == NULL) return false;
5657         tevent_req_set_callback(reqs[0], chain2_sesssetup_completion, NULL);
5658
5659         reqs[1] = cli_tcon_andx_create(talloc_tos(), evt, cli1, "IPC$",
5660                                        "?????", NULL, 0, &smbreqs[1]);
5661         if (reqs[1] == NULL) return false;
5662         tevent_req_set_callback(reqs[1], chain2_tcon_completion, &done);
5663
5664         status = cli_smb_chain_send(smbreqs, ARRAY_SIZE(smbreqs));
5665         if (!NT_STATUS_IS_OK(status)) {
5666                 return false;
5667         }
5668
5669         while (!done) {
5670                 event_loop_once(evt);
5671         }
5672
5673         torture_close_connection(cli1);
5674         return True;
5675 }
5676
5677
5678 struct torture_createdel_state {
5679         struct tevent_context *ev;
5680         struct cli_state *cli;
5681 };
5682
5683 static void torture_createdel_created(struct tevent_req *subreq);
5684 static void torture_createdel_closed(struct tevent_req *subreq);
5685
5686 static struct tevent_req *torture_createdel_send(TALLOC_CTX *mem_ctx,
5687                                                  struct tevent_context *ev,
5688                                                  struct cli_state *cli,
5689                                                  const char *name)
5690 {
5691         struct tevent_req *req, *subreq;
5692         struct torture_createdel_state *state;
5693
5694         req = tevent_req_create(mem_ctx, &state,
5695                                 struct torture_createdel_state);
5696         if (req == NULL) {
5697                 return NULL;
5698         }
5699         state->ev = ev;
5700         state->cli = cli;
5701
5702         subreq = cli_ntcreate_send(
5703                 state, ev, cli, name, 0,
5704                 FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
5705                 FILE_ATTRIBUTE_NORMAL,
5706                 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5707                 FILE_OPEN_IF, FILE_DELETE_ON_CLOSE, 0);
5708
5709         if (tevent_req_nomem(subreq, req)) {
5710                 return tevent_req_post(req, ev);
5711         }
5712         tevent_req_set_callback(subreq, torture_createdel_created, req);
5713         return req;
5714 }
5715
5716 static void torture_createdel_created(struct tevent_req *subreq)
5717 {
5718         struct tevent_req *req = tevent_req_callback_data(
5719                 subreq, struct tevent_req);
5720         struct torture_createdel_state *state = tevent_req_data(
5721                 req, struct torture_createdel_state);
5722         NTSTATUS status;
5723         uint16_t fnum;
5724
5725         status = cli_ntcreate_recv(subreq, &fnum);
5726         TALLOC_FREE(subreq);
5727         if (!NT_STATUS_IS_OK(status)) {
5728                 DEBUG(10, ("cli_ntcreate_recv returned %s\n",
5729                            nt_errstr(status)));
5730                 tevent_req_nterror(req, status);
5731                 return;
5732         }
5733
5734         subreq = cli_close_send(state, state->ev, state->cli, fnum);
5735         if (tevent_req_nomem(subreq, req)) {
5736                 return;
5737         }
5738         tevent_req_set_callback(subreq, torture_createdel_closed, req);
5739 }
5740
5741 static void torture_createdel_closed(struct tevent_req *subreq)
5742 {
5743         struct tevent_req *req = tevent_req_callback_data(
5744                 subreq, struct tevent_req);
5745         NTSTATUS status;
5746
5747         status = cli_close_recv(subreq);
5748         if (!NT_STATUS_IS_OK(status)) {
5749                 DEBUG(10, ("cli_close_recv returned %s\n", nt_errstr(status)));
5750                 tevent_req_nterror(req, status);
5751                 return;
5752         }
5753         tevent_req_done(req);
5754 }
5755
5756 static NTSTATUS torture_createdel_recv(struct tevent_req *req)
5757 {
5758         return tevent_req_simple_recv_ntstatus(req);
5759 }
5760
5761 struct torture_createdels_state {
5762         struct tevent_context *ev;
5763         struct cli_state *cli;
5764         const char *base_name;
5765         int sent;
5766         int received;
5767         int num_files;
5768         struct tevent_req **reqs;
5769 };
5770
5771 static void torture_createdels_done(struct tevent_req *subreq);
5772
5773 static struct tevent_req *torture_createdels_send(TALLOC_CTX *mem_ctx,
5774                                                   struct tevent_context *ev,
5775                                                   struct cli_state *cli,
5776                                                   const char *base_name,
5777                                                   int num_parallel,
5778                                                   int num_files)
5779 {
5780         struct tevent_req *req;
5781         struct torture_createdels_state *state;
5782         int i;
5783
5784         req = tevent_req_create(mem_ctx, &state,
5785                                 struct torture_createdels_state);
5786         if (req == NULL) {
5787                 return NULL;
5788         }
5789         state->ev = ev;
5790         state->cli = cli;
5791         state->base_name = talloc_strdup(state, base_name);
5792         if (tevent_req_nomem(state->base_name, req)) {
5793                 return tevent_req_post(req, ev);
5794         }
5795         state->num_files = MAX(num_parallel, num_files);
5796         state->sent = 0;
5797         state->received = 0;
5798
5799         state->reqs = talloc_array(state, struct tevent_req *, num_parallel);
5800         if (tevent_req_nomem(state->reqs, req)) {
5801                 return tevent_req_post(req, ev);
5802         }
5803
5804         for (i=0; i<num_parallel; i++) {
5805                 char *name;
5806
5807                 name = talloc_asprintf(state, "%s%8.8d", state->base_name,
5808                                        state->sent);
5809                 if (tevent_req_nomem(name, req)) {
5810                         return tevent_req_post(req, ev);
5811                 }
5812                 state->reqs[i] = torture_createdel_send(
5813                         state->reqs, state->ev, state->cli, name);
5814                 if (tevent_req_nomem(state->reqs[i], req)) {
5815                         return tevent_req_post(req, ev);
5816                 }
5817                 name = talloc_move(state->reqs[i], &name);
5818                 tevent_req_set_callback(state->reqs[i],
5819                                         torture_createdels_done, req);
5820                 state->sent += 1;
5821         }
5822         return req;
5823 }
5824
5825 static void torture_createdels_done(struct tevent_req *subreq)
5826 {
5827         struct tevent_req *req = tevent_req_callback_data(
5828                 subreq, struct tevent_req);
5829         struct torture_createdels_state *state = tevent_req_data(
5830                 req, struct torture_createdels_state);
5831         size_t num_parallel = talloc_array_length(state->reqs);
5832         NTSTATUS status;
5833         char *name;
5834         int i;
5835
5836         status = torture_createdel_recv(subreq);
5837         if (!NT_STATUS_IS_OK(status)){
5838                 DEBUG(10, ("torture_createdel_recv returned %s\n",
5839                            nt_errstr(status)));
5840                 TALLOC_FREE(subreq);
5841                 tevent_req_nterror(req, status);
5842                 return;
5843         }
5844
5845         for (i=0; i<num_parallel; i++) {
5846                 if (subreq == state->reqs[i]) {
5847                         break;
5848                 }
5849         }
5850         if (i == num_parallel) {
5851                 DEBUG(10, ("received something we did not send\n"));
5852                 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
5853                 return;
5854         }
5855         TALLOC_FREE(state->reqs[i]);
5856
5857         if (state->sent >= state->num_files) {
5858                 tevent_req_done(req);
5859                 return;
5860         }
5861
5862         name = talloc_asprintf(state, "%s%8.8d", state->base_name,
5863                                state->sent);
5864         if (tevent_req_nomem(name, req)) {
5865                 return;
5866         }
5867         state->reqs[i] = torture_createdel_send(state->reqs, state->ev,
5868                                                 state->cli, name);
5869         if (tevent_req_nomem(state->reqs[i], req)) {
5870                 return;
5871         }
5872         name = talloc_move(state->reqs[i], &name);
5873         tevent_req_set_callback(state->reqs[i], torture_createdels_done, req);
5874         state->sent += 1;
5875 }
5876
5877 static NTSTATUS torture_createdels_recv(struct tevent_req *req)
5878 {
5879         return tevent_req_simple_recv_ntstatus(req);
5880 }
5881
5882 struct swallow_notify_state {
5883         struct tevent_context *ev;
5884         struct cli_state *cli;
5885         uint16_t fnum;
5886         uint32_t completion_filter;
5887         bool recursive;
5888         bool (*fn)(uint32_t action, const char *name, void *priv);
5889         void *priv;
5890 };
5891
5892 static void swallow_notify_done(struct tevent_req *subreq);
5893
5894 static struct tevent_req *swallow_notify_send(TALLOC_CTX *mem_ctx,
5895                                               struct tevent_context *ev,
5896                                               struct cli_state *cli,
5897                                               uint16_t fnum,
5898                                               uint32_t completion_filter,
5899                                               bool recursive,
5900                                               bool (*fn)(uint32_t action,
5901                                                          const char *name,
5902                                                          void *priv),
5903                                               void *priv)
5904 {
5905         struct tevent_req *req, *subreq;
5906         struct swallow_notify_state *state;
5907
5908         req = tevent_req_create(mem_ctx, &state,
5909                                 struct swallow_notify_state);
5910         if (req == NULL) {
5911                 return NULL;
5912         }
5913         state->ev = ev;
5914         state->cli = cli;
5915         state->fnum = fnum;
5916         state->completion_filter = completion_filter;
5917         state->recursive = recursive;
5918         state->fn = fn;
5919         state->priv = priv;
5920
5921         subreq = cli_notify_send(state, state->ev, state->cli, state->fnum,
5922                                  0xffff, state->completion_filter,
5923                                  state->recursive);
5924         if (tevent_req_nomem(subreq, req)) {
5925                 return tevent_req_post(req, ev);
5926         }
5927         tevent_req_set_callback(subreq, swallow_notify_done, req);
5928         return req;
5929 }
5930
5931 static void swallow_notify_done(struct tevent_req *subreq)
5932 {
5933         struct tevent_req *req = tevent_req_callback_data(
5934                 subreq, struct tevent_req);
5935         struct swallow_notify_state *state = tevent_req_data(
5936                 req, struct swallow_notify_state);
5937         NTSTATUS status;
5938         uint32_t i, num_changes;
5939         struct notify_change *changes;
5940
5941         status = cli_notify_recv(subreq, state, &num_changes, &changes);
5942         TALLOC_FREE(subreq);
5943         if (!NT_STATUS_IS_OK(status)) {
5944                 DEBUG(10, ("cli_notify_recv returned %s\n",
5945                            nt_errstr(status)));
5946                 tevent_req_nterror(req, status);
5947                 return;
5948         }
5949
5950         for (i=0; i<num_changes; i++) {
5951                 state->fn(changes[i].action, changes[i].name, state->priv);
5952         }
5953         TALLOC_FREE(changes);
5954
5955         subreq = cli_notify_send(state, state->ev, state->cli, state->fnum,
5956                                  0xffff, state->completion_filter,
5957                                  state->recursive);
5958         if (tevent_req_nomem(subreq, req)) {
5959                 return;
5960         }
5961         tevent_req_set_callback(subreq, swallow_notify_done, req);
5962 }
5963
5964 static bool print_notifies(uint32_t action, const char *name, void *priv)
5965 {
5966         if (DEBUGLEVEL > 5) {
5967                 d_printf("%d %s\n", (int)action, name);
5968         }
5969         return true;
5970 }
5971
5972 static void notify_bench_done(struct tevent_req *req)
5973 {
5974         int *num_finished = (int *)tevent_req_callback_data_void(req);
5975         *num_finished += 1;
5976 }
5977
5978 static bool run_notify_bench(int dummy)
5979 {
5980         const char *dname = "\\notify-bench";
5981         struct tevent_context *ev;
5982         NTSTATUS status;
5983         uint16_t dnum;
5984         struct tevent_req *req1;
5985         struct tevent_req *req2 = NULL;
5986         int i, num_unc_names;
5987         int num_finished = 0;
5988
5989         printf("starting notify-bench test\n");
5990
5991         if (use_multishare_conn) {
5992                 char **unc_list;
5993                 unc_list = file_lines_load(multishare_conn_fname,
5994                                            &num_unc_names, 0, NULL);
5995                 if (!unc_list || num_unc_names <= 0) {
5996                         d_printf("Failed to load unc names list from '%s'\n",
5997                                  multishare_conn_fname);
5998                         return false;
5999                 }
6000                 TALLOC_FREE(unc_list);
6001         } else {
6002                 num_unc_names = 1;
6003         }
6004
6005         ev = tevent_context_init(talloc_tos());
6006         if (ev == NULL) {
6007                 d_printf("tevent_context_init failed\n");
6008                 return false;
6009         }
6010
6011         for (i=0; i<num_unc_names; i++) {
6012                 struct cli_state *cli;
6013                 char *base_fname;
6014
6015                 base_fname = talloc_asprintf(talloc_tos(), "%s\\file%3.3d.",
6016                                              dname, i);
6017                 if (base_fname == NULL) {
6018                         return false;
6019                 }
6020
6021                 if (!torture_open_connection(&cli, i)) {
6022                         return false;
6023                 }
6024
6025                 status = cli_ntcreate(cli, dname, 0,
6026                                       MAXIMUM_ALLOWED_ACCESS,
6027                                       0, FILE_SHARE_READ|FILE_SHARE_WRITE|
6028                                       FILE_SHARE_DELETE,
6029                                       FILE_OPEN_IF, FILE_DIRECTORY_FILE, 0,
6030                                       &dnum);
6031
6032                 if (!NT_STATUS_IS_OK(status)) {
6033                         d_printf("Could not create %s: %s\n", dname,
6034                                  nt_errstr(status));
6035                         return false;
6036                 }
6037
6038                 req1 = swallow_notify_send(talloc_tos(), ev, cli, dnum,
6039                                            FILE_NOTIFY_CHANGE_FILE_NAME |
6040                                            FILE_NOTIFY_CHANGE_DIR_NAME |
6041                                            FILE_NOTIFY_CHANGE_ATTRIBUTES |
6042                                            FILE_NOTIFY_CHANGE_LAST_WRITE,
6043                                            false, print_notifies, NULL);
6044                 if (req1 == NULL) {
6045                         d_printf("Could not create notify request\n");
6046                         return false;
6047                 }
6048
6049                 req2 = torture_createdels_send(talloc_tos(), ev, cli,
6050                                                base_fname, 10, torture_numops);
6051                 if (req2 == NULL) {
6052                         d_printf("Could not create createdels request\n");
6053                         return false;
6054                 }
6055                 TALLOC_FREE(base_fname);
6056
6057                 tevent_req_set_callback(req2, notify_bench_done,
6058                                         &num_finished);
6059         }
6060
6061         while (num_finished < num_unc_names) {
6062                 int ret;
6063                 ret = tevent_loop_once(ev);
6064                 if (ret != 0) {
6065                         d_printf("tevent_loop_once failed\n");
6066                         return false;
6067                 }
6068         }
6069
6070         if (!tevent_req_poll(req2, ev)) {
6071                 d_printf("tevent_req_poll failed\n");
6072         }
6073
6074         status = torture_createdels_recv(req2);
6075         d_printf("torture_createdels_recv returned %s\n", nt_errstr(status));
6076
6077         return true;
6078 }
6079
6080 static bool run_mangle1(int dummy)
6081 {
6082         struct cli_state *cli;
6083         const char *fname = "this_is_a_long_fname_to_be_mangled.txt";
6084         uint16_t fnum;
6085         fstring alt_name;
6086         NTSTATUS status;
6087         time_t change_time, access_time, write_time;
6088         SMB_OFF_T size;
6089         uint16_t mode;
6090
6091         printf("starting mangle1 test\n");
6092         if (!torture_open_connection(&cli, 0)) {
6093                 return False;
6094         }
6095
6096         cli_sockopt(cli, sockops);
6097
6098         if (!NT_STATUS_IS_OK(cli_ntcreate(
6099                         cli, fname, 0, GENERIC_ALL_ACCESS|DELETE_ACCESS,
6100                         FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF, 0, 0, &fnum))) {
6101                 d_printf("open %s failed: %s\n", fname, cli_errstr(cli));
6102                 return false;
6103         }
6104         cli_close(cli, fnum);
6105
6106         status = cli_qpathinfo_alt_name(cli, fname, alt_name);
6107         if (!NT_STATUS_IS_OK(status)) {
6108                 d_printf("cli_qpathinfo_alt_name failed: %s\n",
6109                          nt_errstr(status));
6110                 return false;
6111         }
6112         d_printf("alt_name: %s\n", alt_name);
6113
6114         if (!NT_STATUS_IS_OK(cli_open(cli, alt_name, O_RDONLY, DENY_NONE, &fnum))) {
6115                 d_printf("cli_open(%s) failed: %s\n", alt_name,
6116                          cli_errstr(cli));
6117                 return false;
6118         }
6119         cli_close(cli, fnum);
6120
6121         status = cli_qpathinfo1(cli, alt_name, &change_time, &access_time,
6122                                 &write_time, &size, &mode);
6123         if (!NT_STATUS_IS_OK(status)) {
6124                 d_printf("cli_qpathinfo1(%s) failed: %s\n", alt_name,
6125                          nt_errstr(status));
6126                 return false;
6127         }
6128
6129         return true;
6130 }
6131
6132 static size_t null_source(uint8_t *buf, size_t n, void *priv)
6133 {
6134         size_t *to_pull = (size_t *)priv;
6135         size_t thistime = *to_pull;
6136
6137         thistime = MIN(thistime, n);
6138         if (thistime == 0) {
6139                 return 0;
6140         }
6141
6142         memset(buf, 0, thistime);
6143         *to_pull -= thistime;
6144         return thistime;
6145 }
6146
6147 static bool run_windows_write(int dummy)
6148 {
6149         struct cli_state *cli1;
6150         uint16_t fnum;
6151         int i;
6152         bool ret = false;
6153         const char *fname = "\\writetest.txt";
6154         struct timeval start_time;
6155         double seconds;
6156         double kbytes;
6157
6158         printf("starting windows_write test\n");
6159         if (!torture_open_connection(&cli1, 0)) {
6160                 return False;
6161         }
6162
6163         if (!NT_STATUS_IS_OK(cli_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum))) {
6164                 printf("open failed (%s)\n", cli_errstr(cli1));
6165                 return False;
6166         }
6167
6168         cli_sockopt(cli1, sockops);
6169
6170         start_time = timeval_current();
6171
6172         for (i=0; i<torture_numops; i++) {
6173                 char c = 0;
6174                 off_t start = i * torture_blocksize;
6175                 NTSTATUS status;
6176                 size_t to_pull = torture_blocksize - 1;
6177
6178                 if (cli_write(cli1, fnum, 0, &c,
6179                               start + torture_blocksize - 1, 1) != 1) {
6180                         printf("cli_write failed: %s\n", cli_errstr(cli1));
6181                         goto fail;
6182                 }
6183
6184                 status = cli_push(cli1, fnum, 0, i * torture_blocksize, torture_blocksize,
6185                                   null_source, &to_pull);
6186                 if (!NT_STATUS_IS_OK(status)) {
6187                         printf("cli_push returned: %s\n", nt_errstr(status));
6188                         goto fail;
6189                 }
6190         }
6191
6192         seconds = timeval_elapsed(&start_time);
6193         kbytes = (double)torture_blocksize * torture_numops;
6194         kbytes /= 1024;
6195
6196         printf("Wrote %d kbytes in %.2f seconds: %d kb/sec\n", (int)kbytes,
6197                (double)seconds, (int)(kbytes/seconds));
6198
6199         ret = true;
6200  fail:
6201         cli_close(cli1, fnum);
6202         cli_unlink(cli1, fname, aSYSTEM | aHIDDEN);
6203         torture_close_connection(cli1);
6204         return ret;
6205 }
6206
6207 static bool run_cli_echo(int dummy)
6208 {
6209         struct cli_state *cli;
6210         NTSTATUS status;
6211
6212         printf("starting cli_echo test\n");
6213         if (!torture_open_connection(&cli, 0)) {
6214                 return false;
6215         }
6216         cli_sockopt(cli, sockops);
6217
6218         status = cli_echo(cli, 5, data_blob_const("hello", 5));
6219
6220         d_printf("cli_echo returned %s\n", nt_errstr(status));
6221
6222         torture_close_connection(cli);
6223         return NT_STATUS_IS_OK(status);
6224 }
6225
6226 static bool run_uid_regression_test(int dummy)
6227 {
6228         static struct cli_state *cli;
6229         int16_t old_vuid;
6230         int16_t old_cnum;
6231         bool correct = True;
6232         NTSTATUS status;
6233
6234         printf("starting uid regression test\n");
6235
6236         if (!torture_open_connection(&cli, 0)) {
6237                 return False;
6238         }
6239
6240         cli_sockopt(cli, sockops);
6241
6242         /* Ok - now save then logoff our current user. */
6243         old_vuid = cli->vuid;
6244
6245         status = cli_ulogoff(cli);
6246         if (!NT_STATUS_IS_OK(status)) {
6247                 d_printf("(%s) cli_ulogoff failed: %s\n",
6248                          __location__, nt_errstr(status));
6249                 correct = false;
6250                 goto out;
6251         }
6252
6253         cli->vuid = old_vuid;
6254
6255         /* Try an operation. */
6256         status = cli_mkdir(cli, "\\uid_reg_test");
6257         if (NT_STATUS_IS_OK(status)) {
6258                 d_printf("(%s) cli_mkdir succeeded\n",
6259                          __location__);
6260                 correct = false;
6261                 goto out;
6262         } else {
6263                 /* Should be bad uid. */
6264                 if (!check_error(__LINE__, cli, ERRSRV, ERRbaduid,
6265                                 NT_STATUS_USER_SESSION_DELETED)) {
6266                         correct = false;
6267                         goto out;
6268                 }
6269         }
6270
6271         old_cnum = cli->cnum;
6272
6273         /* Now try a SMBtdis with the invald vuid set to zero. */
6274         cli->vuid = 0;
6275
6276         /* This should succeed. */
6277         status = cli_tdis(cli);
6278
6279         if (NT_STATUS_IS_OK(status)) {
6280                 d_printf("First tdis with invalid vuid should succeed.\n");
6281         } else {
6282                 d_printf("First tdis failed (%s)\n", nt_errstr(status));
6283                 correct = false;
6284                 goto out;
6285         }
6286
6287         cli->vuid = old_vuid;
6288         cli->cnum = old_cnum;
6289
6290         /* This should fail. */
6291         status = cli_tdis(cli);
6292         if (NT_STATUS_IS_OK(status)) {
6293                 d_printf("Second tdis with invalid vuid should fail - succeeded instead !.\n");
6294                 correct = false;
6295                 goto out;
6296         } else {
6297                 /* Should be bad tid. */
6298                 if (!check_error(__LINE__, cli, ERRSRV, ERRinvnid,
6299                                 NT_STATUS_NETWORK_NAME_DELETED)) {
6300                         correct = false;
6301                         goto out;
6302                 }
6303         }
6304
6305         cli_rmdir(cli, "\\uid_reg_test");
6306
6307   out:
6308
6309         cli_shutdown(cli);
6310         return correct;
6311 }
6312
6313
6314 static const char *illegal_chars = "*\\/?<>|\":";
6315 static char force_shortname_chars[] = " +,.[];=\177";
6316
6317 static NTSTATUS shortname_del_fn(const char *mnt, struct file_info *finfo,
6318                              const char *mask, void *state)
6319 {
6320         struct cli_state *pcli = (struct cli_state *)state;
6321         fstring fname;
6322         NTSTATUS status = NT_STATUS_OK;
6323
6324         slprintf(fname, sizeof(fname), "\\shortname\\%s", finfo->name);
6325
6326         if (strcmp(finfo->name, ".") == 0 || strcmp(finfo->name, "..") == 0)
6327                 return NT_STATUS_OK;
6328
6329         if (finfo->mode & aDIR) {
6330                 status = cli_rmdir(pcli, fname);
6331                 if (!NT_STATUS_IS_OK(status)) {
6332                         printf("del_fn: failed to rmdir %s\n,", fname );
6333                 }
6334         } else {
6335                 status = cli_unlink(pcli, fname, aSYSTEM | aHIDDEN);
6336                 if (!NT_STATUS_IS_OK(status)) {
6337                         printf("del_fn: failed to unlink %s\n,", fname );
6338                 }
6339         }
6340         return status;
6341 }
6342
6343 struct sn_state {
6344         int matched;
6345         int i;
6346         bool val;
6347 };
6348
6349 static NTSTATUS shortname_list_fn(const char *mnt, struct file_info *finfo,
6350                               const char *name, void *state)
6351 {
6352         struct sn_state *s = (struct sn_state  *)state;
6353         int i = s->i;
6354
6355 #if 0
6356         printf("shortname list: i = %d, name = |%s|, shortname = |%s|\n",
6357                 i, finfo->name, finfo->short_name);
6358 #endif
6359
6360         if (strchr(force_shortname_chars, i)) {
6361                 if (!finfo->short_name[0]) {
6362                         /* Shortname not created when it should be. */
6363                         d_printf("(%s) ERROR: Shortname was not created for file %s containing %d\n",
6364                                 __location__, finfo->name, i);
6365                         s->val = true;
6366                 }
6367         } else if (finfo->short_name[0]){
6368                 /* Shortname created when it should not be. */
6369                 d_printf("(%s) ERROR: Shortname %s was created for file %s\n",
6370                         __location__, finfo->short_name, finfo->name);
6371                 s->val = true;
6372         }
6373         s->matched += 1;
6374         return NT_STATUS_OK;
6375 }
6376
6377 static bool run_shortname_test(int dummy)
6378 {
6379         static struct cli_state *cli;
6380         bool correct = True;
6381         int i;
6382         struct sn_state s;
6383         char fname[20];
6384
6385         printf("starting shortname test\n");
6386
6387         if (!torture_open_connection(&cli, 0)) {
6388                 return False;
6389         }
6390
6391         cli_sockopt(cli, sockops);
6392
6393         cli_list(cli, "\\shortname\\*", 0, shortname_del_fn, cli);
6394         cli_list(cli, "\\shortname\\*", aDIR, shortname_del_fn, cli);
6395         cli_rmdir(cli, "\\shortname");
6396
6397         if (!NT_STATUS_IS_OK(cli_mkdir(cli, "\\shortname"))) {
6398                 d_printf("(%s) cli_mkdir of \\shortname failed: %s\n",
6399                         __location__, cli_errstr(cli));
6400                 correct = false;
6401                 goto out;
6402         }
6403
6404         strlcpy(fname, "\\shortname\\", sizeof(fname));
6405         strlcat(fname, "test .txt", sizeof(fname));
6406
6407         s.val = false;
6408
6409         for (i = 32; i < 128; i++) {
6410                 NTSTATUS status;
6411                 uint16_t fnum = (uint16_t)-1;
6412
6413                 s.i = i;
6414
6415                 if (strchr(illegal_chars, i)) {
6416                         continue;
6417                 }
6418                 fname[15] = i;
6419
6420                 status = cli_ntcreate(cli, fname, 0, GENERIC_ALL_ACCESS, FILE_ATTRIBUTE_NORMAL,
6421                                    FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OVERWRITE_IF, 0, 0, &fnum);
6422                 if (!NT_STATUS_IS_OK(status)) {
6423                         d_printf("(%s) cli_nt_create of %s failed: %s\n",
6424                                 __location__, fname, cli_errstr(cli));
6425                         correct = false;
6426                         goto out;
6427                 }
6428                 cli_close(cli, fnum);
6429
6430                 s.matched = 0;
6431                 cli_list(cli, "\\shortname\\test*.*", 0, shortname_list_fn,
6432                          &s);
6433                 if (s.matched != 1) {
6434                         d_printf("(%s) failed to list %s: %s\n",
6435                                 __location__, fname, cli_errstr(cli));
6436                         correct = false;
6437                         goto out;
6438                 }
6439                 if (!NT_STATUS_IS_OK(cli_unlink(cli, fname, aSYSTEM | aHIDDEN))) {
6440                         d_printf("(%s) failed to delete %s: %s\n",
6441                                 __location__, fname, cli_errstr(cli));
6442                         correct = false;
6443                         goto out;
6444                 }
6445
6446                 if (s.val) {
6447                         correct = false;
6448                         goto out;
6449                 }
6450         }
6451
6452   out:
6453
6454         cli_list(cli, "\\shortname\\*", 0, shortname_del_fn, cli);
6455         cli_list(cli, "\\shortname\\*", aDIR, shortname_del_fn, cli);
6456         cli_rmdir(cli, "\\shortname");
6457         torture_close_connection(cli);
6458         return correct;
6459 }
6460
6461 static void pagedsearch_cb(struct tevent_req *req)
6462 {
6463         int rc;
6464         struct tldap_message *msg;
6465         char *dn;
6466
6467         rc = tldap_search_paged_recv(req, talloc_tos(), &msg);
6468         if (rc != TLDAP_SUCCESS) {
6469                 d_printf("tldap_search_paged_recv failed: %s\n",
6470                          tldap_err2string(rc));
6471                 return;
6472         }
6473         if (tldap_msg_type(msg) != TLDAP_RES_SEARCH_ENTRY) {
6474                 TALLOC_FREE(msg);
6475                 return;
6476         }
6477         if (!tldap_entry_dn(msg, &dn)) {
6478                 d_printf("tldap_entry_dn failed\n");
6479                 return;
6480         }
6481         d_printf("%s\n", dn);
6482         TALLOC_FREE(msg);
6483 }
6484
6485 static bool run_tldap(int dummy)
6486 {
6487         struct tldap_context *ld;
6488         int fd, rc;
6489         NTSTATUS status;
6490         struct sockaddr_storage addr;
6491         struct tevent_context *ev;
6492         struct tevent_req *req;
6493         char *basedn;
6494         const char *filter;
6495
6496         if (!resolve_name(host, &addr, 0, false)) {
6497                 d_printf("could not find host %s\n", host);
6498                 return false;
6499         }
6500         status = open_socket_out(&addr, 389, 9999, &fd);
6501         if (!NT_STATUS_IS_OK(status)) {
6502                 d_printf("open_socket_out failed: %s\n", nt_errstr(status));
6503                 return false;
6504         }
6505
6506         ld = tldap_context_create(talloc_tos(), fd);
6507         if (ld == NULL) {
6508                 close(fd);
6509                 d_printf("tldap_context_create failed\n");
6510                 return false;
6511         }
6512
6513         rc = tldap_fetch_rootdse(ld);
6514         if (rc != TLDAP_SUCCESS) {
6515                 d_printf("tldap_fetch_rootdse failed: %s\n",
6516                          tldap_errstr(talloc_tos(), ld, rc));
6517                 return false;
6518         }
6519
6520         basedn = tldap_talloc_single_attribute(
6521                 tldap_rootdse(ld), "defaultNamingContext", talloc_tos());
6522         if (basedn == NULL) {
6523                 d_printf("no defaultNamingContext\n");
6524                 return false;
6525         }
6526         d_printf("defaultNamingContext: %s\n", basedn);
6527
6528         ev = tevent_context_init(talloc_tos());
6529         if (ev == NULL) {
6530                 d_printf("tevent_context_init failed\n");
6531                 return false;
6532         }
6533
6534         req = tldap_search_paged_send(talloc_tos(), ev, ld, basedn,
6535                                       TLDAP_SCOPE_SUB, "(objectclass=*)",
6536                                       NULL, 0, 0,
6537                                       NULL, 0, NULL, 0, 0, 0, 0, 5);
6538         if (req == NULL) {
6539                 d_printf("tldap_search_paged_send failed\n");
6540                 return false;
6541         }
6542         tevent_req_set_callback(req, pagedsearch_cb, NULL);
6543
6544         tevent_req_poll(req, ev);
6545
6546         TALLOC_FREE(req);
6547
6548         /* test search filters against rootDSE */
6549         filter = "(&(|(name=samba)(nextRid<=10000000)(usnChanged>=10)(samba~=ambas)(!(name=s*m*a)))"
6550                    "(|(name:=samba)(name:dn:2.5.13.5:=samba)(:dn:2.5.13.5:=samba)(!(name=*samba))))";
6551
6552         rc = tldap_search(ld, "", TLDAP_SCOPE_BASE, filter,
6553                           NULL, 0, 0, NULL, 0, NULL, 0, 0, 0, 0,
6554                           talloc_tos(), NULL, NULL);
6555         if (rc != TLDAP_SUCCESS) {
6556                 d_printf("tldap_search with complex filter failed: %s\n",
6557                          tldap_errstr(talloc_tos(), ld, rc));
6558                 return false;
6559         }
6560
6561         TALLOC_FREE(ld);
6562         return true;
6563 }
6564
6565 /* Torture test to ensure no regression of :
6566 https://bugzilla.samba.org/show_bug.cgi?id=7084
6567 */
6568
6569 static bool run_dir_createtime(int dummy)
6570 {
6571         struct cli_state *cli;
6572         const char *dname = "\\testdir";
6573         const char *fname = "\\testdir\\testfile";
6574         NTSTATUS status;
6575         struct timespec create_time;
6576         struct timespec create_time1;
6577         uint16_t fnum;
6578         bool ret = false;
6579
6580         if (!torture_open_connection(&cli, 0)) {
6581                 return false;
6582         }
6583
6584         cli_unlink(cli, fname, aSYSTEM | aHIDDEN);
6585         cli_rmdir(cli, dname);
6586
6587         status = cli_mkdir(cli, dname);
6588         if (!NT_STATUS_IS_OK(status)) {
6589                 printf("mkdir failed: %s\n", nt_errstr(status));
6590                 goto out;
6591         }
6592
6593         status = cli_qpathinfo2(cli, dname, &create_time, NULL, NULL, NULL,
6594                                 NULL, NULL, NULL);
6595         if (!NT_STATUS_IS_OK(status)) {
6596                 printf("cli_qpathinfo2 returned %s\n",
6597                        nt_errstr(status));
6598                 goto out;
6599         }
6600
6601         /* Sleep 3 seconds, then create a file. */
6602         sleep(3);
6603
6604         status = cli_open(cli, fname, O_RDWR | O_CREAT | O_EXCL,
6605                          DENY_NONE, &fnum);
6606         if (!NT_STATUS_IS_OK(status)) {
6607                 printf("cli_open failed: %s\n", nt_errstr(status));
6608                 goto out;
6609         }
6610
6611         status = cli_qpathinfo2(cli, dname, &create_time1, NULL, NULL, NULL,
6612                                 NULL, NULL, NULL);
6613         if (!NT_STATUS_IS_OK(status)) {
6614                 printf("cli_qpathinfo2 (2) returned %s\n",
6615                        nt_errstr(status));
6616                 goto out;
6617         }
6618
6619         if (timespec_compare(&create_time1, &create_time)) {
6620                 printf("run_dir_createtime: create time was updated (error)\n");
6621         } else {
6622                 printf("run_dir_createtime: create time was not updated (correct)\n");
6623                 ret = true;
6624         }
6625
6626   out:
6627
6628         cli_unlink(cli, fname, aSYSTEM | aHIDDEN);
6629         cli_rmdir(cli, dname);
6630         if (!torture_close_connection(cli)) {
6631                 ret = false;
6632         }
6633         return ret;
6634 }
6635
6636
6637 static bool run_streamerror(int dummy)
6638 {
6639         struct cli_state *cli;
6640         const char *dname = "\\testdir";
6641         const char *streamname =
6642                 "testdir:{4c8cc155-6c1e-11d1-8e41-00c04fb9386d}:$DATA";
6643         NTSTATUS status;
6644         time_t change_time, access_time, write_time;
6645         SMB_OFF_T size;
6646         uint16_t mode, fnum;
6647         bool ret = true;
6648
6649         if (!torture_open_connection(&cli, 0)) {
6650                 return false;
6651         }
6652
6653         cli_unlink(cli, "\\testdir\\*", aSYSTEM | aHIDDEN);
6654         cli_rmdir(cli, dname);
6655
6656         status = cli_mkdir(cli, dname);
6657         if (!NT_STATUS_IS_OK(status)) {
6658                 printf("mkdir failed: %s\n", nt_errstr(status));
6659                 return false;
6660         }
6661
6662         cli_qpathinfo1(cli, streamname, &change_time, &access_time, &write_time,
6663                       &size, &mode);
6664         status = cli_nt_error(cli);
6665
6666         if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
6667                 printf("pathinfo returned %s, expected "
6668                        "NT_STATUS_OBJECT_NAME_NOT_FOUND\n",
6669                        nt_errstr(status));
6670                 ret = false;
6671         }
6672
6673         status = cli_ntcreate(cli, streamname, 0x16,
6674                               FILE_READ_DATA|FILE_READ_EA|
6675                               FILE_READ_ATTRIBUTES|READ_CONTROL_ACCESS,
6676                               FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ,
6677                               FILE_OPEN, 0, 0, &fnum);
6678
6679         if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
6680                 printf("ntcreate returned %s, expected "
6681                        "NT_STATUS_OBJECT_NAME_NOT_FOUND\n",
6682                        nt_errstr(status));
6683                 ret = false;
6684         }
6685
6686
6687         cli_rmdir(cli, dname);
6688         return ret;
6689 }
6690
6691 static bool run_local_substitute(int dummy)
6692 {
6693         bool ok = true;
6694
6695         ok &= subst_test("%U", "bla", "", -1, -1, "bla");
6696         ok &= subst_test("%u%U", "bla", "", -1, -1, "blabla");
6697         ok &= subst_test("%g", "", "", -1, -1, "NO_GROUP");
6698         ok &= subst_test("%G", "", "", -1, -1, "NO_GROUP");
6699         ok &= subst_test("%g", "", "", -1, 0, gidtoname(0));
6700         ok &= subst_test("%G", "", "", -1, 0, gidtoname(0));
6701         ok &= subst_test("%D%u", "u", "dom", -1, 0, "domu");
6702         ok &= subst_test("%i %I", "", "", -1, -1, "0.0.0.0 0.0.0.0");
6703
6704         /* Different captialization rules in sub_basic... */
6705
6706         ok &=  (strcmp(talloc_sub_basic(talloc_tos(), "BLA", "dom", "%U%D"),
6707                        "blaDOM") == 0);
6708
6709         return ok;
6710 }
6711
6712 static bool run_local_base64(int dummy)
6713 {
6714         int i;
6715         bool ret = true;
6716
6717         for (i=1; i<2000; i++) {
6718                 DATA_BLOB blob1, blob2;
6719                 char *b64;
6720
6721                 blob1.data = talloc_array(talloc_tos(), uint8_t, i);
6722                 blob1.length = i;
6723                 generate_random_buffer(blob1.data, blob1.length);
6724
6725                 b64 = base64_encode_data_blob(talloc_tos(), blob1);
6726                 if (b64 == NULL) {
6727                         d_fprintf(stderr, "base64_encode_data_blob failed "
6728                                   "for %d bytes\n", i);
6729                         ret = false;
6730                 }
6731                 blob2 = base64_decode_data_blob(b64);
6732                 TALLOC_FREE(b64);
6733
6734                 if (data_blob_cmp(&blob1, &blob2)) {
6735                         d_fprintf(stderr, "data_blob_cmp failed for %d "
6736                                   "bytes\n", i);
6737                         ret = false;
6738                 }
6739                 TALLOC_FREE(blob1.data);
6740                 data_blob_free(&blob2);
6741         }
6742         return ret;
6743 }
6744
6745 static bool run_local_gencache(int dummy)
6746 {
6747         char *val;
6748         time_t tm;
6749         DATA_BLOB blob;
6750
6751         if (!gencache_set("foo", "bar", time(NULL) + 1000)) {
6752                 d_printf("%s: gencache_set() failed\n", __location__);
6753                 return False;
6754         }
6755
6756         if (!gencache_get("foo", NULL, NULL)) {
6757                 d_printf("%s: gencache_get() failed\n", __location__);
6758                 return False;
6759         }
6760
6761         if (!gencache_get("foo", &val, &tm)) {
6762                 d_printf("%s: gencache_get() failed\n", __location__);
6763                 return False;
6764         }
6765
6766         if (strcmp(val, "bar") != 0) {
6767                 d_printf("%s: gencache_get() returned %s, expected %s\n",
6768                          __location__, val, "bar");
6769                 SAFE_FREE(val);
6770                 return False;
6771         }
6772
6773         SAFE_FREE(val);
6774
6775         if (!gencache_del("foo")) {
6776                 d_printf("%s: gencache_del() failed\n", __location__);
6777                 return False;
6778         }
6779         if (gencache_del("foo")) {
6780                 d_printf("%s: second gencache_del() succeeded\n",
6781                          __location__);
6782                 return False;
6783         }
6784
6785         if (gencache_get("foo", &val, &tm)) {
6786                 d_printf("%s: gencache_get() on deleted entry "
6787                          "succeeded\n", __location__);
6788                 return False;
6789         }
6790
6791         blob = data_blob_string_const_null("bar");
6792         tm = time(NULL) + 60;
6793
6794         if (!gencache_set_data_blob("foo", &blob, tm)) {
6795                 d_printf("%s: gencache_set_data_blob() failed\n", __location__);
6796                 return False;
6797         }
6798
6799         if (!gencache_get_data_blob("foo", &blob, NULL, NULL)) {
6800                 d_printf("%s: gencache_get_data_blob() failed\n", __location__);
6801                 return False;
6802         }
6803
6804         if (strcmp((const char *)blob.data, "bar") != 0) {
6805                 d_printf("%s: gencache_get_data_blob() returned %s, expected %s\n",
6806                          __location__, (const char *)blob.data, "bar");
6807                 data_blob_free(&blob);
6808                 return False;
6809         }
6810
6811         data_blob_free(&blob);
6812
6813         if (!gencache_del("foo")) {
6814                 d_printf("%s: gencache_del() failed\n", __location__);
6815                 return False;
6816         }
6817         if (gencache_del("foo")) {
6818                 d_printf("%s: second gencache_del() succeeded\n",
6819                          __location__);
6820                 return False;
6821         }
6822
6823         if (gencache_get_data_blob("foo", &blob, NULL, NULL)) {
6824                 d_printf("%s: gencache_get_data_blob() on deleted entry "
6825                          "succeeded\n", __location__);
6826                 return False;
6827         }
6828
6829         return True;
6830 }
6831
6832 static bool rbt_testval(struct db_context *db, const char *key,
6833                         const char *value)
6834 {
6835         struct db_record *rec;
6836         TDB_DATA data = string_tdb_data(value);
6837         bool ret = false;
6838         NTSTATUS status;
6839
6840         rec = db->fetch_locked(db, db, string_tdb_data(key));
6841         if (rec == NULL) {
6842                 d_fprintf(stderr, "fetch_locked failed\n");
6843                 goto done;
6844         }
6845         status = rec->store(rec, data, 0);
6846         if (!NT_STATUS_IS_OK(status)) {
6847                 d_fprintf(stderr, "store failed: %s\n", nt_errstr(status));
6848                 goto done;
6849         }
6850         TALLOC_FREE(rec);
6851
6852         rec = db->fetch_locked(db, db, string_tdb_data(key));
6853         if (rec == NULL) {
6854                 d_fprintf(stderr, "second fetch_locked failed\n");
6855                 goto done;
6856         }
6857         if ((rec->value.dsize != data.dsize)
6858             || (memcmp(rec->value.dptr, data.dptr, data.dsize) != 0)) {
6859                 d_fprintf(stderr, "Got wrong data back\n");
6860                 goto done;
6861         }
6862
6863         ret = true;
6864  done:
6865         TALLOC_FREE(rec);
6866         return ret;
6867 }
6868
6869 static bool run_local_rbtree(int dummy)
6870 {
6871         struct db_context *db;
6872         bool ret = false;
6873         int i;
6874
6875         db = db_open_rbt(NULL);
6876
6877         if (db == NULL) {
6878                 d_fprintf(stderr, "db_open_rbt failed\n");
6879                 return false;
6880         }
6881
6882         for (i=0; i<1000; i++) {
6883                 char *key, *value;
6884
6885                 if (asprintf(&key, "key%ld", random()) == -1) {
6886                         goto done;
6887                 }
6888                 if (asprintf(&value, "value%ld", random()) == -1) {
6889                         SAFE_FREE(key);
6890                         goto done;
6891                 }
6892
6893                 if (!rbt_testval(db, key, value)) {
6894                         SAFE_FREE(key);
6895                         SAFE_FREE(value);
6896                         goto done;
6897                 }
6898
6899                 SAFE_FREE(value);
6900                 if (asprintf(&value, "value%ld", random()) == -1) {
6901                         SAFE_FREE(key);
6902                         goto done;
6903                 }
6904
6905                 if (!rbt_testval(db, key, value)) {
6906                         SAFE_FREE(key);
6907                         SAFE_FREE(value);
6908                         goto done;
6909                 }
6910
6911                 SAFE_FREE(key);
6912                 SAFE_FREE(value);
6913         }
6914
6915         ret = true;
6916
6917  done:
6918         TALLOC_FREE(db);
6919         return ret;
6920 }
6921
6922 struct talloc_dict_test {
6923         int content;
6924 };
6925
6926 static int talloc_dict_traverse_fn(DATA_BLOB key, void *data, void *priv)
6927 {
6928         int *count = (int *)priv;
6929         *count += 1;
6930         return 0;
6931 }
6932
6933 static bool run_local_talloc_dict(int dummy)
6934 {
6935         struct talloc_dict *dict;
6936         struct talloc_dict_test *t;
6937         int key, count;
6938
6939         dict = talloc_dict_init(talloc_tos());
6940         if (dict == NULL) {
6941                 return false;
6942         }
6943
6944         t = talloc(talloc_tos(), struct talloc_dict_test);
6945         if (t == NULL) {
6946                 return false;
6947         }
6948
6949         key = 1;
6950         t->content = 1;
6951         if (!talloc_dict_set(dict, data_blob_const(&key, sizeof(key)), t)) {
6952                 return false;
6953         }
6954
6955         count = 0;
6956         if (talloc_dict_traverse(dict, talloc_dict_traverse_fn, &count) != 0) {
6957                 return false;
6958         }
6959
6960         if (count != 1) {
6961                 return false;
6962         }
6963
6964         TALLOC_FREE(dict);
6965
6966         return true;
6967 }
6968
6969 static bool run_local_string_to_sid(int dummy) {
6970         struct dom_sid sid;
6971
6972         if (string_to_sid(&sid, "S--1-5-32-545")) {
6973                 printf("allowing S--1-5-32-545\n");
6974                 return false;
6975         }
6976         if (string_to_sid(&sid, "S-1-5-32-+545")) {
6977                 printf("allowing S-1-5-32-+545\n");
6978                 return false;
6979         }
6980         if (string_to_sid(&sid, "S-1-2-3-4-5-6-7-8-9-0-1-2-3-4-5-6-7-8-9-0")) {
6981                 printf("allowing S-1-2-3-4-5-6-7-8-9-0-1-2-3-4-5-6-7-8-9-0\n");
6982                 return false;
6983         }
6984         if (string_to_sid(&sid, "S-1-5-32-545-abc")) {
6985                 printf("allowing S-1-5-32-545-abc\n");
6986                 return false;
6987         }
6988         if (!string_to_sid(&sid, "S-1-5-32-545")) {
6989                 printf("could not parse S-1-5-32-545\n");
6990                 return false;
6991         }
6992         if (!dom_sid_equal(&sid, &global_sid_Builtin_Users)) {
6993                 printf("mis-parsed S-1-5-32-545 as %s\n",
6994                        sid_string_tos(&sid));
6995                 return false;
6996         }
6997         return true;
6998 }
6999
7000 static bool run_local_binary_to_sid(int dummy) {
7001         struct dom_sid *sid = talloc(NULL, struct dom_sid);
7002         static const char good_binary_sid[] = {
7003                 0x1, /* revision number */
7004                 15, /* num auths */
7005                 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, /* id_auth */
7006                 0x1, 0x1, 0x1, 0x1, /* auth[0] */
7007                 0x1, 0x1, 0x1, 0x1, /* auth[1] */
7008                 0x1, 0x1, 0x1, 0x1, /* auth[2] */
7009                 0x1, 0x1, 0x1, 0x1, /* auth[3] */
7010                 0x1, 0x1, 0x1, 0x1, /* auth[4] */
7011                 0x1, 0x1, 0x1, 0x1, /* auth[5] */
7012                 0x1, 0x1, 0x1, 0x1, /* auth[6] */
7013                 0x1, 0x1, 0x1, 0x1, /* auth[7] */
7014                 0x1, 0x1, 0x1, 0x1, /* auth[8] */
7015                 0x1, 0x1, 0x1, 0x1, /* auth[9] */
7016                 0x1, 0x1, 0x1, 0x1, /* auth[10] */
7017                 0x1, 0x1, 0x1, 0x1, /* auth[11] */
7018                 0x1, 0x1, 0x1, 0x1, /* auth[12] */
7019                 0x1, 0x1, 0x1, 0x1, /* auth[13] */
7020                 0x1, 0x1, 0x1, 0x1, /* auth[14] */
7021         };
7022
7023         static const char long_binary_sid[] = {
7024                 0x1, /* revision number */
7025                 15, /* num auths */
7026                 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, /* id_auth */
7027                 0x1, 0x1, 0x1, 0x1, /* auth[0] */
7028                 0x1, 0x1, 0x1, 0x1, /* auth[1] */
7029                 0x1, 0x1, 0x1, 0x1, /* auth[2] */
7030                 0x1, 0x1, 0x1, 0x1, /* auth[3] */
7031                 0x1, 0x1, 0x1, 0x1, /* auth[4] */
7032                 0x1, 0x1, 0x1, 0x1, /* auth[5] */
7033                 0x1, 0x1, 0x1, 0x1, /* auth[6] */
7034                 0x1, 0x1, 0x1, 0x1, /* auth[7] */
7035                 0x1, 0x1, 0x1, 0x1, /* auth[8] */
7036                 0x1, 0x1, 0x1, 0x1, /* auth[9] */
7037                 0x1, 0x1, 0x1, 0x1, /* auth[10] */
7038                 0x1, 0x1, 0x1, 0x1, /* auth[11] */
7039                 0x1, 0x1, 0x1, 0x1, /* auth[12] */
7040                 0x1, 0x1, 0x1, 0x1, /* auth[13] */
7041                 0x1, 0x1, 0x1, 0x1, /* auth[14] */
7042                 0x1, 0x1, 0x1, 0x1, /* auth[15] */
7043                 0x1, 0x1, 0x1, 0x1, /* auth[16] */
7044                 0x1, 0x1, 0x1, 0x1, /* auth[17] */
7045         };
7046
7047         static const char long_binary_sid2[] = {
7048                 0x1, /* revision number */
7049                 32, /* num auths */
7050                 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, /* id_auth */
7051                 0x1, 0x1, 0x1, 0x1, /* auth[0] */
7052                 0x1, 0x1, 0x1, 0x1, /* auth[1] */
7053                 0x1, 0x1, 0x1, 0x1, /* auth[2] */
7054                 0x1, 0x1, 0x1, 0x1, /* auth[3] */
7055                 0x1, 0x1, 0x1, 0x1, /* auth[4] */
7056                 0x1, 0x1, 0x1, 0x1, /* auth[5] */
7057                 0x1, 0x1, 0x1, 0x1, /* auth[6] */
7058                 0x1, 0x1, 0x1, 0x1, /* auth[7] */
7059                 0x1, 0x1, 0x1, 0x1, /* auth[8] */
7060                 0x1, 0x1, 0x1, 0x1, /* auth[9] */
7061                 0x1, 0x1, 0x1, 0x1, /* auth[10] */
7062                 0x1, 0x1, 0x1, 0x1, /* auth[11] */
7063                 0x1, 0x1, 0x1, 0x1, /* auth[12] */
7064                 0x1, 0x1, 0x1, 0x1, /* auth[13] */
7065                 0x1, 0x1, 0x1, 0x1, /* auth[14] */
7066                 0x1, 0x1, 0x1, 0x1, /* auth[15] */
7067                 0x1, 0x1, 0x1, 0x1, /* auth[16] */
7068                 0x1, 0x1, 0x1, 0x1, /* auth[17] */
7069                 0x1, 0x1, 0x1, 0x1, /* auth[18] */
7070                 0x1, 0x1, 0x1, 0x1, /* auth[19] */
7071                 0x1, 0x1, 0x1, 0x1, /* auth[20] */
7072                 0x1, 0x1, 0x1, 0x1, /* auth[21] */
7073                 0x1, 0x1, 0x1, 0x1, /* auth[22] */
7074                 0x1, 0x1, 0x1, 0x1, /* auth[23] */
7075                 0x1, 0x1, 0x1, 0x1, /* auth[24] */
7076                 0x1, 0x1, 0x1, 0x1, /* auth[25] */
7077                 0x1, 0x1, 0x1, 0x1, /* auth[26] */
7078                 0x1, 0x1, 0x1, 0x1, /* auth[27] */
7079                 0x1, 0x1, 0x1, 0x1, /* auth[28] */
7080                 0x1, 0x1, 0x1, 0x1, /* auth[29] */
7081                 0x1, 0x1, 0x1, 0x1, /* auth[30] */
7082                 0x1, 0x1, 0x1, 0x1, /* auth[31] */
7083         };
7084
7085         if (!sid_parse(good_binary_sid, sizeof(good_binary_sid), sid)) {
7086                 return false;
7087         }
7088         if (sid_parse(long_binary_sid2, sizeof(long_binary_sid2), sid)) {
7089                 return false;
7090         }
7091         if (sid_parse(long_binary_sid, sizeof(long_binary_sid), sid)) {
7092                 return false;
7093         }
7094         return true;
7095 }
7096
7097 /* Split a path name into filename and stream name components. Canonicalise
7098  * such that an implicit $DATA token is always explicit.
7099  *
7100  * The "specification" of this function can be found in the
7101  * run_local_stream_name() function in torture.c, I've tried those
7102  * combinations against a W2k3 server.
7103  */
7104
7105 static NTSTATUS split_ntfs_stream_name(TALLOC_CTX *mem_ctx, const char *fname,
7106                                        char **pbase, char **pstream)
7107 {
7108         char *base = NULL;
7109         char *stream = NULL;
7110         char *sname; /* stream name */
7111         const char *stype; /* stream type */
7112
7113         DEBUG(10, ("split_ntfs_stream_name called for [%s]\n", fname));
7114
7115         sname = strchr_m(fname, ':');
7116
7117         if (lp_posix_pathnames() || (sname == NULL)) {
7118                 if (pbase != NULL) {
7119                         base = talloc_strdup(mem_ctx, fname);
7120                         NT_STATUS_HAVE_NO_MEMORY(base);
7121                 }
7122                 goto done;
7123         }
7124
7125         if (pbase != NULL) {
7126                 base = talloc_strndup(mem_ctx, fname, PTR_DIFF(sname, fname));
7127                 NT_STATUS_HAVE_NO_MEMORY(base);
7128         }
7129
7130         sname += 1;
7131
7132         stype = strchr_m(sname, ':');
7133
7134         if (stype == NULL) {
7135                 sname = talloc_strdup(mem_ctx, sname);
7136                 stype = "$DATA";
7137         }
7138         else {
7139                 if (StrCaseCmp(stype, ":$DATA") != 0) {
7140                         /*
7141                          * If there is an explicit stream type, so far we only
7142                          * allow $DATA. Is there anything else allowed? -- vl
7143                          */
7144                         DEBUG(10, ("[%s] is an invalid stream type\n", stype));
7145                         TALLOC_FREE(base);
7146                         return NT_STATUS_OBJECT_NAME_INVALID;
7147                 }
7148                 sname = talloc_strndup(mem_ctx, sname, PTR_DIFF(stype, sname));
7149                 stype += 1;
7150         }
7151
7152         if (sname == NULL) {
7153                 TALLOC_FREE(base);
7154                 return NT_STATUS_NO_MEMORY;
7155         }
7156
7157         if (sname[0] == '\0') {
7158                 /*
7159                  * no stream name, so no stream
7160                  */
7161                 goto done;
7162         }
7163
7164         if (pstream != NULL) {
7165                 stream = talloc_asprintf(mem_ctx, "%s:%s", sname, stype);
7166                 if (stream == NULL) {
7167                         TALLOC_FREE(sname);
7168                         TALLOC_FREE(base);
7169                         return NT_STATUS_NO_MEMORY;
7170                 }
7171                 /*
7172                  * upper-case the type field
7173                  */
7174                 strupper_m(strchr_m(stream, ':')+1);
7175         }
7176
7177  done:
7178         if (pbase != NULL) {
7179                 *pbase = base;
7180         }
7181         if (pstream != NULL) {
7182                 *pstream = stream;
7183         }
7184         return NT_STATUS_OK;
7185 }
7186
7187 static bool test_stream_name(const char *fname, const char *expected_base,
7188                              const char *expected_stream,
7189                              NTSTATUS expected_status)
7190 {
7191         NTSTATUS status;
7192         char *base = NULL;
7193         char *stream = NULL;
7194
7195         status = split_ntfs_stream_name(talloc_tos(), fname, &base, &stream);
7196         if (!NT_STATUS_EQUAL(status, expected_status)) {
7197                 goto error;
7198         }
7199
7200         if (!NT_STATUS_IS_OK(status)) {
7201                 return true;
7202         }
7203
7204         if (base == NULL) goto error;
7205
7206         if (strcmp(expected_base, base) != 0) goto error;
7207
7208         if ((expected_stream != NULL) && (stream == NULL)) goto error;
7209         if ((expected_stream == NULL) && (stream != NULL)) goto error;
7210
7211         if ((stream != NULL) && (strcmp(expected_stream, stream) != 0))
7212                 goto error;
7213
7214         TALLOC_FREE(base);
7215         TALLOC_FREE(stream);
7216         return true;
7217
7218  error:
7219         d_fprintf(stderr, "Do test_stream(%s, %s, %s, %s)\n",
7220                   fname, expected_base ? expected_base : "<NULL>",
7221                   expected_stream ? expected_stream : "<NULL>",
7222                   nt_errstr(expected_status));
7223         d_fprintf(stderr, "-> base=%s, stream=%s, status=%s\n",
7224                   base ? base : "<NULL>", stream ? stream : "<NULL>",
7225                   nt_errstr(status));
7226         TALLOC_FREE(base);
7227         TALLOC_FREE(stream);
7228         return false;
7229 }
7230
7231 static bool run_local_stream_name(int dummy)
7232 {
7233         bool ret = true;
7234
7235         ret &= test_stream_name(
7236                 "bla", "bla", NULL, NT_STATUS_OK);
7237         ret &= test_stream_name(
7238                 "bla::$DATA", "bla", NULL, NT_STATUS_OK);
7239         ret &= test_stream_name(
7240                 "bla:blub:", "bla", NULL, NT_STATUS_OBJECT_NAME_INVALID);
7241         ret &= test_stream_name(
7242                 "bla::", NULL, NULL, NT_STATUS_OBJECT_NAME_INVALID);
7243         ret &= test_stream_name(
7244                 "bla::123", "bla", NULL, NT_STATUS_OBJECT_NAME_INVALID);
7245         ret &= test_stream_name(
7246                 "bla:$DATA", "bla", "$DATA:$DATA", NT_STATUS_OK);
7247         ret &= test_stream_name(
7248                 "bla:x:$DATA", "bla", "x:$DATA", NT_STATUS_OK);
7249         ret &= test_stream_name(
7250                 "bla:x", "bla", "x:$DATA", NT_STATUS_OK);
7251
7252         return ret;
7253 }
7254
7255 static bool data_blob_equal(DATA_BLOB a, DATA_BLOB b)
7256 {
7257         if (a.length != b.length) {
7258                 printf("a.length=%d != b.length=%d\n",
7259                        (int)a.length, (int)b.length);
7260                 return false;
7261         }
7262         if (memcmp(a.data, b.data, a.length) != 0) {
7263                 printf("a.data and b.data differ\n");
7264                 return false;
7265         }
7266         return true;
7267 }
7268
7269 static bool run_local_memcache(int dummy)
7270 {
7271         struct memcache *cache;
7272         DATA_BLOB k1, k2;
7273         DATA_BLOB d1, d2, d3;
7274         DATA_BLOB v1, v2, v3;
7275
7276         TALLOC_CTX *mem_ctx;
7277         char *str1, *str2;
7278         size_t size1, size2;
7279         bool ret = false;
7280
7281         cache = memcache_init(NULL, 100);
7282
7283         if (cache == NULL) {
7284                 printf("memcache_init failed\n");
7285                 return false;
7286         }
7287
7288         d1 = data_blob_const("d1", 2);
7289         d2 = data_blob_const("d2", 2);
7290         d3 = data_blob_const("d3", 2);
7291
7292         k1 = data_blob_const("d1", 2);
7293         k2 = data_blob_const("d2", 2);
7294
7295         memcache_add(cache, STAT_CACHE, k1, d1);
7296         memcache_add(cache, GETWD_CACHE, k2, d2);
7297
7298         if (!memcache_lookup(cache, STAT_CACHE, k1, &v1)) {
7299                 printf("could not find k1\n");
7300                 return false;
7301         }
7302         if (!data_blob_equal(d1, v1)) {
7303                 return false;
7304         }
7305
7306         if (!memcache_lookup(cache, GETWD_CACHE, k2, &v2)) {
7307                 printf("could not find k2\n");
7308                 return false;
7309         }
7310         if (!data_blob_equal(d2, v2)) {
7311                 return false;
7312         }
7313
7314         memcache_add(cache, STAT_CACHE, k1, d3);
7315
7316         if (!memcache_lookup(cache, STAT_CACHE, k1, &v3)) {
7317                 printf("could not find replaced k1\n");
7318                 return false;
7319         }
7320         if (!data_blob_equal(d3, v3)) {
7321                 return false;
7322         }
7323
7324         memcache_add(cache, GETWD_CACHE, k1, d1);
7325
7326         if (memcache_lookup(cache, GETWD_CACHE, k2, &v2)) {
7327                 printf("Did find k2, should have been purged\n");
7328                 return false;
7329         }
7330
7331         TALLOC_FREE(cache);
7332
7333         cache = memcache_init(NULL, 0);
7334
7335         mem_ctx = talloc_init("foo");
7336
7337         str1 = talloc_strdup(mem_ctx, "string1");
7338         str2 = talloc_strdup(mem_ctx, "string2");
7339
7340         memcache_add_talloc(cache, SINGLETON_CACHE_TALLOC,
7341                             data_blob_string_const("torture"), &str1);
7342         size1 = talloc_total_size(cache);
7343
7344         memcache_add_talloc(cache, SINGLETON_CACHE_TALLOC,
7345                             data_blob_string_const("torture"), &str2);
7346         size2 = talloc_total_size(cache);
7347
7348         printf("size1=%d, size2=%d\n", (int)size1, (int)size2);
7349
7350         if (size2 > size1) {
7351                 printf("memcache leaks memory!\n");
7352                 goto fail;
7353         }
7354
7355         ret = true;
7356  fail:
7357         TALLOC_FREE(cache);
7358         return ret;
7359 }
7360
7361 static void wbclient_done(struct tevent_req *req)
7362 {
7363         wbcErr wbc_err;
7364         struct winbindd_response *wb_resp;
7365         int *i = (int *)tevent_req_callback_data_void(req);
7366
7367         wbc_err = wb_trans_recv(req, req, &wb_resp);
7368         TALLOC_FREE(req);
7369         *i += 1;
7370         d_printf("wb_trans_recv %d returned %s\n", *i, wbcErrorString(wbc_err));
7371 }
7372
7373 static bool run_local_wbclient(int dummy)
7374 {
7375         struct event_context *ev;
7376         struct wb_context **wb_ctx;
7377         struct winbindd_request wb_req;
7378         bool result = false;
7379         int i, j;
7380
7381         BlockSignals(True, SIGPIPE);
7382
7383         ev = tevent_context_init_byname(talloc_tos(), "epoll");
7384         if (ev == NULL) {
7385                 goto fail;
7386         }
7387
7388         wb_ctx = TALLOC_ARRAY(ev, struct wb_context *, nprocs);
7389         if (wb_ctx == NULL) {
7390                 goto fail;
7391         }
7392
7393         ZERO_STRUCT(wb_req);
7394         wb_req.cmd = WINBINDD_PING;
7395
7396         d_printf("nprocs=%d, numops=%d\n", (int)nprocs, (int)torture_numops);
7397
7398         for (i=0; i<nprocs; i++) {
7399                 wb_ctx[i] = wb_context_init(ev, NULL);
7400                 if (wb_ctx[i] == NULL) {
7401                         goto fail;
7402                 }
7403                 for (j=0; j<torture_numops; j++) {
7404                         struct tevent_req *req;
7405                         req = wb_trans_send(ev, ev, wb_ctx[i],
7406                                             (j % 2) == 0, &wb_req);
7407                         if (req == NULL) {
7408                                 goto fail;
7409                         }
7410                         tevent_req_set_callback(req, wbclient_done, &i);
7411                 }
7412         }
7413
7414         i = 0;
7415
7416         while (i < nprocs * torture_numops) {
7417                 event_loop_once(ev);
7418         }
7419
7420         result = true;
7421  fail:
7422         TALLOC_FREE(ev);
7423         return result;
7424 }
7425
7426 static void getaddrinfo_finished(struct tevent_req *req)
7427 {
7428         char *name = (char *)tevent_req_callback_data_void(req);
7429         struct addrinfo *ainfo;
7430         int res;
7431
7432         res = getaddrinfo_recv(req, &ainfo);
7433         if (res != 0) {
7434                 d_printf("gai(%s) returned %s\n", name, gai_strerror(res));
7435                 return;
7436         }
7437         d_printf("gai(%s) succeeded\n", name);
7438         freeaddrinfo(ainfo);
7439 }
7440
7441 static bool run_getaddrinfo_send(int dummy)
7442 {
7443         TALLOC_CTX *frame = talloc_stackframe();
7444         struct fncall_context *ctx;
7445         struct tevent_context *ev;
7446         bool result = false;
7447         const char *names[4] = { "www.samba.org", "notfound.samba.org",
7448                                  "www.slashdot.org", "heise.de" };
7449         struct tevent_req *reqs[4];
7450         int i;
7451
7452         ev = event_context_init(frame);
7453         if (ev == NULL) {
7454                 goto fail;
7455         }
7456
7457         ctx = fncall_context_init(frame, 4);
7458
7459         for (i=0; i<ARRAY_SIZE(names); i++) {
7460                 reqs[i] = getaddrinfo_send(frame, ev, ctx, names[i], NULL,
7461                                            NULL);
7462                 if (reqs[i] == NULL) {
7463                         goto fail;
7464                 }
7465                 tevent_req_set_callback(reqs[i], getaddrinfo_finished,
7466                                         (void *)names[i]);
7467         }
7468
7469         for (i=0; i<ARRAY_SIZE(reqs); i++) {
7470                 tevent_loop_once(ev);
7471         }
7472
7473         result = true;
7474 fail:
7475         TALLOC_FREE(frame);
7476         return result;
7477 }
7478
7479 static bool dbtrans_inc(struct db_context *db)
7480 {
7481         struct db_record *rec;
7482         uint32_t *val;
7483         bool ret = false;
7484         NTSTATUS status;
7485
7486         rec = db->fetch_locked(db, db, string_term_tdb_data("transtest"));
7487         if (rec == NULL) {
7488                 printf(__location__ "fetch_lock failed\n");
7489                 return false;
7490         }
7491
7492         if (rec->value.dsize != sizeof(uint32_t)) {
7493                 printf(__location__ "value.dsize = %d\n",
7494                        (int)rec->value.dsize);
7495                 goto fail;
7496         }
7497
7498         val = (uint32_t *)rec->value.dptr;
7499         *val += 1;
7500
7501         status = rec->store(rec, make_tdb_data((uint8_t *)val,
7502                                                sizeof(uint32_t)),
7503                             0);
7504         if (!NT_STATUS_IS_OK(status)) {
7505                 printf(__location__ "store failed: %s\n",
7506                        nt_errstr(status));
7507                 goto fail;
7508         }
7509
7510         ret = true;
7511 fail:
7512         TALLOC_FREE(rec);
7513         return ret;
7514 }
7515
7516 static bool run_local_dbtrans(int dummy)
7517 {
7518         struct db_context *db;
7519         struct db_record *rec;
7520         NTSTATUS status;
7521         uint32_t initial;
7522         int res;
7523
7524         db = db_open(talloc_tos(), "transtest.tdb", 0, TDB_DEFAULT,
7525                      O_RDWR|O_CREAT, 0600);
7526         if (db == NULL) {
7527                 printf("Could not open transtest.db\n");
7528                 return false;
7529         }
7530
7531         res = db->transaction_start(db);
7532         if (res == -1) {
7533                 printf(__location__ "transaction_start failed\n");
7534                 return false;
7535         }
7536
7537         rec = db->fetch_locked(db, db, string_term_tdb_data("transtest"));
7538         if (rec == NULL) {
7539                 printf(__location__ "fetch_lock failed\n");
7540                 return false;
7541         }
7542
7543         if (rec->value.dptr == NULL) {
7544                 initial = 0;
7545                 status = rec->store(
7546                         rec, make_tdb_data((uint8_t *)&initial,
7547                                            sizeof(initial)),
7548                         0);
7549                 if (!NT_STATUS_IS_OK(status)) {
7550                         printf(__location__ "store returned %s\n",
7551                                nt_errstr(status));
7552                         return false;
7553                 }
7554         }
7555
7556         TALLOC_FREE(rec);
7557
7558         res = db->transaction_commit(db);
7559         if (res == -1) {
7560                 printf(__location__ "transaction_commit failed\n");
7561                 return false;
7562         }
7563
7564         while (true) {
7565                 uint32_t val, val2;
7566                 int i;
7567
7568                 res = db->transaction_start(db);
7569                 if (res == -1) {
7570                         printf(__location__ "transaction_start failed\n");
7571                         break;
7572                 }
7573
7574                 if (!dbwrap_fetch_uint32(db, "transtest", &val)) {
7575                         printf(__location__ "dbwrap_fetch_uint32 failed\n");
7576                         break;
7577                 }
7578
7579                 for (i=0; i<10; i++) {
7580                         if (!dbtrans_inc(db)) {
7581                                 return false;
7582                         }
7583                 }
7584
7585                 if (!dbwrap_fetch_uint32(db, "transtest", &val2)) {
7586                         printf(__location__ "dbwrap_fetch_uint32 failed\n");
7587                         break;
7588                 }
7589
7590                 if (val2 != val + 10) {
7591                         printf(__location__ "val=%d, val2=%d\n",
7592                                (int)val, (int)val2);
7593                         break;
7594                 }
7595
7596                 printf("val2=%d\r", val2);
7597
7598                 res = db->transaction_commit(db);
7599                 if (res == -1) {
7600                         printf(__location__ "transaction_commit failed\n");
7601                         break;
7602                 }
7603         }
7604
7605         TALLOC_FREE(db);
7606         return true;
7607 }
7608
7609 /*
7610  * Just a dummy test to be run under a debugger. There's no real way
7611  * to inspect the tevent_select specific function from outside of
7612  * tevent_select.c.
7613  */
7614
7615 static bool run_local_tevent_select(int dummy)
7616 {
7617         struct tevent_context *ev;
7618         struct tevent_fd *fd1, *fd2;
7619         bool result = false;
7620
7621         ev = tevent_context_init_byname(NULL, "select");
7622         if (ev == NULL) {
7623                 d_fprintf(stderr, "tevent_context_init_byname failed\n");
7624                 goto fail;
7625         }
7626
7627         fd1 = tevent_add_fd(ev, ev, 2, 0, NULL, NULL);
7628         if (fd1 == NULL) {
7629                 d_fprintf(stderr, "tevent_add_fd failed\n");
7630                 goto fail;
7631         }
7632         fd2 = tevent_add_fd(ev, ev, 3, 0, NULL, NULL);
7633         if (fd2 == NULL) {
7634                 d_fprintf(stderr, "tevent_add_fd failed\n");
7635                 goto fail;
7636         }
7637         TALLOC_FREE(fd2);
7638
7639         fd2 = tevent_add_fd(ev, ev, 1, 0, NULL, NULL);
7640         if (fd2 == NULL) {
7641                 d_fprintf(stderr, "tevent_add_fd failed\n");
7642                 goto fail;
7643         }
7644
7645         result = true;
7646 fail:
7647         TALLOC_FREE(ev);
7648         return result;
7649 }
7650
7651 static double create_procs(bool (*fn)(int), bool *result)
7652 {
7653         int i, status;
7654         volatile pid_t *child_status;
7655         volatile bool *child_status_out;
7656         int synccount;
7657         int tries = 8;
7658         struct timeval start;
7659
7660         synccount = 0;
7661
7662         child_status = (volatile pid_t *)shm_setup(sizeof(pid_t)*nprocs);
7663         if (!child_status) {
7664                 printf("Failed to setup shared memory\n");
7665                 return -1;
7666         }
7667
7668         child_status_out = (volatile bool *)shm_setup(sizeof(bool)*nprocs);
7669         if (!child_status_out) {
7670                 printf("Failed to setup result status shared memory\n");
7671                 return -1;
7672         }
7673
7674         for (i = 0; i < nprocs; i++) {
7675                 child_status[i] = 0;
7676                 child_status_out[i] = True;
7677         }
7678
7679         start = timeval_current();
7680
7681         for (i=0;i<nprocs;i++) {
7682                 procnum = i;
7683                 if (fork() == 0) {
7684                         pid_t mypid = getpid();
7685                         sys_srandom(((int)mypid) ^ ((int)time(NULL)));
7686
7687                         slprintf(myname,sizeof(myname),"CLIENT%d", i);
7688
7689                         while (1) {
7690                                 if (torture_open_connection(&current_cli, i)) break;
7691                                 if (tries-- == 0) {
7692                                         printf("pid %d failed to start\n", (int)getpid());
7693                                         _exit(1);
7694                                 }
7695                                 smb_msleep(10); 
7696                         }
7697
7698                         child_status[i] = getpid();
7699
7700                         while (child_status[i] && timeval_elapsed(&start) < 5) smb_msleep(2);
7701
7702                         child_status_out[i] = fn(i);
7703                         _exit(0);
7704                 }
7705         }
7706
7707         do {
7708                 synccount = 0;
7709                 for (i=0;i<nprocs;i++) {
7710                         if (child_status[i]) synccount++;
7711                 }
7712                 if (synccount == nprocs) break;
7713                 smb_msleep(10);
7714         } while (timeval_elapsed(&start) < 30);
7715
7716         if (synccount != nprocs) {
7717                 printf("FAILED TO START %d CLIENTS (started %d)\n", nprocs, synccount);
7718                 *result = False;
7719                 return timeval_elapsed(&start);
7720         }
7721
7722         /* start the client load */
7723         start = timeval_current();
7724
7725         for (i=0;i<nprocs;i++) {
7726                 child_status[i] = 0;
7727         }
7728
7729         printf("%d clients started\n", nprocs);
7730
7731         for (i=0;i<nprocs;i++) {
7732                 while (waitpid(0, &status, 0) == -1 && errno == EINTR) /* noop */ ;
7733         }
7734
7735         printf("\n");
7736
7737         for (i=0;i<nprocs;i++) {
7738                 if (!child_status_out[i]) {
7739                         *result = False;
7740                 }
7741         }
7742         return timeval_elapsed(&start);
7743 }
7744
7745 #define FLAG_MULTIPROC 1
7746
7747 static struct {
7748         const char *name;
7749         bool (*fn)(int);
7750         unsigned flags;
7751 } torture_ops[] = {
7752         {"FDPASS", run_fdpasstest, 0},
7753         {"LOCK1",  run_locktest1,  0},
7754         {"LOCK2",  run_locktest2,  0},
7755         {"LOCK3",  run_locktest3,  0},
7756         {"LOCK4",  run_locktest4,  0},
7757         {"LOCK5",  run_locktest5,  0},
7758         {"LOCK6",  run_locktest6,  0},
7759         {"LOCK7",  run_locktest7,  0},
7760         {"LOCK8",  run_locktest8,  0},
7761         {"LOCK9",  run_locktest9,  0},
7762         {"UNLINK", run_unlinktest, 0},
7763         {"BROWSE", run_browsetest, 0},
7764         {"ATTR",   run_attrtest,   0},
7765         {"TRANS2", run_trans2test, 0},
7766         {"MAXFID", run_maxfidtest, FLAG_MULTIPROC},
7767         {"TORTURE",run_torture,    FLAG_MULTIPROC},
7768         {"RANDOMIPC", run_randomipc, 0},
7769         {"NEGNOWAIT", run_negprot_nowait, 0},
7770         {"NBENCH",  run_nbench, 0},
7771         {"NBENCH2", run_nbench2, 0},
7772         {"OPLOCK1",  run_oplock1, 0},
7773         {"OPLOCK2",  run_oplock2, 0},
7774         {"OPLOCK3",  run_oplock3, 0},
7775         {"DIR",  run_dirtest, 0},
7776         {"DIR1",  run_dirtest1, 0},
7777         {"DIR-CREATETIME",  run_dir_createtime, 0},
7778         {"DENY1",  torture_denytest1, 0},
7779         {"DENY2",  torture_denytest2, 0},
7780         {"TCON",  run_tcon_test, 0},
7781         {"TCONDEV",  run_tcon_devtype_test, 0},
7782         {"RW1",  run_readwritetest, 0},
7783         {"RW2",  run_readwritemulti, FLAG_MULTIPROC},
7784         {"RW3",  run_readwritelarge, 0},
7785         {"OPEN", run_opentest, 0},
7786         {"POSIX", run_simple_posix_open_test, 0},
7787         {"POSIX-APPEND", run_posix_append, 0},
7788         {"ASYNC-ECHO", run_async_echo, 0},
7789         { "UID-REGRESSION-TEST", run_uid_regression_test, 0},
7790         { "SHORTNAME-TEST", run_shortname_test, 0},
7791 #if 1
7792         {"OPENATTR", run_openattrtest, 0},
7793 #endif
7794         {"XCOPY", run_xcopy, 0},
7795         {"RENAME", run_rename, 0},
7796         {"DELETE", run_deletetest, 0},
7797         {"PROPERTIES", run_properties, 0},
7798         {"MANGLE", torture_mangle, 0},
7799         {"MANGLE1", run_mangle1, 0},
7800         {"W2K", run_w2ktest, 0},
7801         {"TRANS2SCAN", torture_trans2_scan, 0},
7802         {"NTTRANSSCAN", torture_nttrans_scan, 0},
7803         {"UTABLE", torture_utable, 0},
7804         {"CASETABLE", torture_casetable, 0},
7805         {"ERRMAPEXTRACT", run_error_map_extract, 0},
7806         {"PIPE_NUMBER", run_pipe_number, 0},
7807         {"TCON2",  run_tcon2_test, 0},
7808         {"IOCTL",  torture_ioctl_test, 0},
7809         {"CHKPATH",  torture_chkpath_test, 0},
7810         {"FDSESS", run_fdsesstest, 0},
7811         { "EATEST", run_eatest, 0},
7812         { "SESSSETUP_BENCH", run_sesssetup_bench, 0},
7813         { "CHAIN1", run_chain1, 0},
7814         { "CHAIN2", run_chain2, 0},
7815         { "WINDOWS-WRITE", run_windows_write, 0},
7816         { "CLI_ECHO", run_cli_echo, 0},
7817         { "GETADDRINFO", run_getaddrinfo_send, 0},
7818         { "TLDAP", run_tldap },
7819         { "STREAMERROR", run_streamerror },
7820         { "NOTIFY-BENCH", run_notify_bench },
7821         { "BAD-NBT-SESSION", run_bad_nbt_session },
7822         { "LOCAL-SUBSTITUTE", run_local_substitute, 0},
7823         { "LOCAL-GENCACHE", run_local_gencache, 0},
7824         { "LOCAL-TALLOC-DICT", run_local_talloc_dict, 0},
7825         { "LOCAL-BASE64", run_local_base64, 0},
7826         { "LOCAL-RBTREE", run_local_rbtree, 0},
7827         { "LOCAL-MEMCACHE", run_local_memcache, 0},
7828         { "LOCAL-STREAM-NAME", run_local_stream_name, 0},
7829         { "LOCAL-WBCLIENT", run_local_wbclient, 0},
7830         { "LOCAL-string_to_sid", run_local_string_to_sid, 0},
7831         { "LOCAL-binary_to_sid", run_local_binary_to_sid, 0},
7832         { "LOCAL-DBTRANS", run_local_dbtrans, 0},
7833         { "LOCAL-TEVENT-SELECT", run_local_tevent_select, 0},
7834         {NULL, NULL, 0}};
7835
7836
7837
7838 /****************************************************************************
7839 run a specified test or "ALL"
7840 ****************************************************************************/
7841 static bool run_test(const char *name)
7842 {
7843         bool ret = True;
7844         bool result = True;
7845         bool found = False;
7846         int i;
7847         double t;
7848         if (strequal(name,"ALL")) {
7849                 for (i=0;torture_ops[i].name;i++) {
7850                         run_test(torture_ops[i].name);
7851                 }
7852                 found = True;
7853         }
7854
7855         for (i=0;torture_ops[i].name;i++) {
7856                 fstr_sprintf(randomfname, "\\XX%x", 
7857                          (unsigned)random());
7858
7859                 if (strequal(name, torture_ops[i].name)) {
7860                         found = True;
7861                         printf("Running %s\n", name);
7862                         if (torture_ops[i].flags & FLAG_MULTIPROC) {
7863                                 t = create_procs(torture_ops[i].fn, &result);
7864                                 if (!result) { 
7865                                         ret = False;
7866                                         printf("TEST %s FAILED!\n", name);
7867                                 }
7868                         } else {
7869                                 struct timeval start;
7870                                 start = timeval_current();
7871                                 if (!torture_ops[i].fn(0)) {
7872                                         ret = False;
7873                                         printf("TEST %s FAILED!\n", name);
7874                                 }
7875                                 t = timeval_elapsed(&start);
7876                         }
7877                         printf("%s took %g secs\n\n", name, t);
7878                 }
7879         }
7880
7881         if (!found) {
7882                 printf("Did not find a test named %s\n", name);
7883                 ret = False;
7884         }
7885
7886         return ret;
7887 }
7888
7889
7890 static void usage(void)
7891 {
7892         int i;
7893
7894         printf("WARNING samba4 test suite is much more complete nowadays.\n");
7895         printf("Please use samba4 torture.\n\n");
7896
7897         printf("Usage: smbtorture //server/share <options> TEST1 TEST2 ...\n");
7898
7899         printf("\t-d debuglevel\n");
7900         printf("\t-U user%%pass\n");
7901         printf("\t-k               use kerberos\n");
7902         printf("\t-N numprocs\n");
7903         printf("\t-n my_netbios_name\n");
7904         printf("\t-W workgroup\n");
7905         printf("\t-o num_operations\n");
7906         printf("\t-O socket_options\n");
7907         printf("\t-m maximum protocol\n");
7908         printf("\t-L use oplocks\n");
7909         printf("\t-c CLIENT.TXT   specify client load file for NBENCH\n");
7910         printf("\t-A showall\n");
7911         printf("\t-p port\n");
7912         printf("\t-s seed\n");
7913         printf("\t-b unclist_filename   specify multiple shares for multiple connections\n");
7914         printf("\n\n");
7915
7916         printf("tests are:");
7917         for (i=0;torture_ops[i].name;i++) {
7918                 printf(" %s", torture_ops[i].name);
7919         }
7920         printf("\n");
7921
7922         printf("default test is ALL\n");
7923
7924         exit(1);
7925 }
7926
7927 /****************************************************************************
7928   main program
7929 ****************************************************************************/
7930  int main(int argc,char *argv[])
7931 {
7932         int opt, i;
7933         char *p;
7934         int gotuser = 0;
7935         int gotpass = 0;
7936         bool correct = True;
7937         TALLOC_CTX *frame = talloc_stackframe();
7938         int seed = time(NULL);
7939
7940 #ifdef HAVE_SETBUFFER
7941         setbuffer(stdout, NULL, 0);
7942 #endif
7943
7944         setup_logging("smbtorture", DEBUG_STDOUT);
7945
7946         load_case_tables();
7947
7948         if (is_default_dyn_CONFIGFILE()) {
7949                 if(getenv("SMB_CONF_PATH")) {
7950                         set_dyn_CONFIGFILE(getenv("SMB_CONF_PATH"));
7951                 }
7952         }
7953         lp_load(get_dyn_CONFIGFILE(),True,False,False,True);
7954         load_interfaces();
7955
7956         if (argc < 2) {
7957                 usage();
7958         }
7959
7960         for(p = argv[1]; *p; p++)
7961           if(*p == '\\')
7962             *p = '/';
7963
7964         if (strncmp(argv[1], "//", 2)) {
7965                 usage();
7966         }
7967
7968         fstrcpy(host, &argv[1][2]);
7969         p = strchr_m(&host[2],'/');
7970         if (!p) {
7971                 usage();
7972         }
7973         *p = 0;
7974         fstrcpy(share, p+1);
7975
7976         fstrcpy(myname, get_myname(talloc_tos()));
7977         if (!*myname) {
7978                 fprintf(stderr, "Failed to get my hostname.\n");
7979                 return 1;
7980         }
7981
7982         if (*username == 0 && getenv("LOGNAME")) {
7983           fstrcpy(username,getenv("LOGNAME"));
7984         }
7985
7986         argc--;
7987         argv++;
7988
7989         fstrcpy(workgroup, lp_workgroup());
7990
7991         while ((opt = getopt(argc, argv, "p:hW:U:n:N:O:o:m:Ll:d:Aec:ks:b:B:")) != EOF) {
7992                 switch (opt) {
7993                 case 'p':
7994                         port_to_use = atoi(optarg);
7995                         break;
7996                 case 's':
7997                         seed = atoi(optarg);
7998                         break;
7999                 case 'W':
8000                         fstrcpy(workgroup,optarg);
8001                         break;
8002                 case 'm':
8003                         max_protocol = interpret_protocol(optarg, max_protocol);
8004                         break;
8005                 case 'N':
8006                         nprocs = atoi(optarg);
8007                         break;
8008                 case 'o':
8009                         torture_numops = atoi(optarg);
8010                         break;
8011                 case 'd':
8012                         DEBUGLEVEL = atoi(optarg);
8013                         break;
8014                 case 'O':
8015                         sockops = optarg;
8016                         break;
8017                 case 'L':
8018                         use_oplocks = True;
8019                         break;
8020                 case 'l':
8021                         local_path = optarg;
8022                         break;
8023                 case 'A':
8024                         torture_showall = True;
8025                         break;
8026                 case 'n':
8027                         fstrcpy(myname, optarg);
8028                         break;
8029                 case 'c':
8030                         client_txt = optarg;
8031                         break;
8032                 case 'e':
8033                         do_encrypt = true;
8034                         break;
8035                 case 'k':
8036 #ifdef HAVE_KRB5
8037                         use_kerberos = True;
8038 #else
8039                         d_printf("No kerberos support compiled in\n");
8040                         exit(1);
8041 #endif
8042                         break;
8043                 case 'U':
8044                         gotuser = 1;
8045                         fstrcpy(username,optarg);
8046                         p = strchr_m(username,'%');
8047                         if (p) {
8048                                 *p = 0;
8049                                 fstrcpy(password, p+1);
8050                                 gotpass = 1;
8051                         }
8052                         break;
8053                 case 'b':
8054                         fstrcpy(multishare_conn_fname, optarg);
8055                         use_multishare_conn = True;
8056                         break;
8057                 case 'B':
8058                         torture_blocksize = atoi(optarg);
8059                         break;
8060                 default:
8061                         printf("Unknown option %c (%d)\n", (char)opt, opt);
8062                         usage();
8063                 }
8064         }
8065
8066         d_printf("using seed %d\n", seed);
8067
8068         srandom(seed);
8069
8070         if(use_kerberos && !gotuser) gotpass = True;
8071
8072         while (!gotpass) {
8073                 p = getpass("Password:");
8074                 if (p) {
8075                         fstrcpy(password, p);
8076                         gotpass = 1;
8077                 }
8078         }
8079
8080         printf("host=%s share=%s user=%s myname=%s\n", 
8081                host, share, username, myname);
8082
8083         if (argc == optind) {
8084                 correct = run_test("ALL");
8085         } else {
8086                 for (i=optind;i<argc;i++) {
8087                         if (!run_test(argv[i])) {
8088                                 correct = False;
8089                         }
8090                 }
8091         }
8092
8093         TALLOC_FREE(frame);
8094
8095         if (correct) {
8096                 return(0);
8097         } else {
8098                 return(1);
8099         }
8100 }