6317d0eae6a5a155d6317a0286d9c659a293754a
[kai/samba.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 "system/shmem.h"
23 #include "wbc_async.h"
24 #include "torture/proto.h"
25 #include "libcli/security/security.h"
26 #include "tldap.h"
27 #include "tldap_util.h"
28 #include "../librpc/gen_ndr/svcctl.h"
29 #include "memcache.h"
30 #include "nsswitch/winbind_client.h"
31 #include "dbwrap.h"
32 #include "talloc_dict.h"
33 #include "async_smb.h"
34 #include "libsmb/libsmb.h"
35 #include "libsmb/clirap.h"
36 #include "trans2.h"
37 #include "libsmb/nmblib.h"
38 #include "../lib/util/tevent_ntstatus.h"
39 #include "util_tdb.h"
40 #include "libsmb/read_smb.h"
41
42 extern char *optarg;
43 extern int optind;
44
45 fstring host, workgroup, share, password, username, myname;
46 static int max_protocol = PROTOCOL_NT1;
47 static const char *sockops="TCP_NODELAY";
48 static int nprocs=1;
49 static int port_to_use=0;
50 int torture_numops=100;
51 int torture_blocksize=1024*1024;
52 static int procnum; /* records process count number when forking */
53 static struct cli_state *current_cli;
54 static fstring randomfname;
55 static bool use_oplocks;
56 static bool use_level_II_oplocks;
57 static const char *client_txt = "client_oplocks.txt";
58 static bool use_kerberos;
59 static fstring multishare_conn_fname;
60 static bool use_multishare_conn = False;
61 static bool do_encrypt;
62 static const char *local_path = NULL;
63 static int signing_state = Undefined;
64 char *test_filename;
65
66 bool torture_showall = False;
67
68 static double create_procs(bool (*fn)(int), bool *result);
69
70
71 /* return a pointer to a anonymous shared memory segment of size "size"
72    which will persist across fork() but will disappear when all processes
73    exit 
74
75    The memory is not zeroed 
76
77    This function uses system5 shared memory. It takes advantage of a property
78    that the memory is not destroyed if it is attached when the id is removed
79    */
80 void *shm_setup(int size)
81 {
82         int shmid;
83         void *ret;
84
85 #ifdef __QNXNTO__
86         shmid = shm_open("private", O_RDWR | O_CREAT | O_EXCL, S_IRUSR | S_IWUSR);
87         if (shmid == -1) {
88                 printf("can't get shared memory\n");
89                 exit(1);
90         }
91         shm_unlink("private");
92         if (ftruncate(shmid, size) == -1) {
93                 printf("can't set shared memory size\n");
94                 exit(1);
95         }
96         ret = mmap(0, size, PROT_READ | PROT_WRITE, MAP_SHARED, shmid, 0);
97         if (ret == MAP_FAILED) {
98                 printf("can't map shared memory\n");
99                 exit(1);
100         }
101 #else
102         shmid = shmget(IPC_PRIVATE, size, S_IRUSR | S_IWUSR);
103         if (shmid == -1) {
104                 printf("can't get shared memory\n");
105                 exit(1);
106         }
107         ret = (void *)shmat(shmid, 0, 0);
108         if (!ret || ret == (void *)-1) {
109                 printf("can't attach to shared memory\n");
110                 return NULL;
111         }
112         /* the following releases the ipc, but note that this process
113            and all its children will still have access to the memory, its
114            just that the shmid is no longer valid for other shm calls. This
115            means we don't leave behind lots of shm segments after we exit 
116
117            See Stevens "advanced programming in unix env" for details
118            */
119         shmctl(shmid, IPC_RMID, 0);
120 #endif
121
122         return ret;
123 }
124
125 /********************************************************************
126  Ensure a connection is encrypted.
127 ********************************************************************/
128
129 static bool force_cli_encryption(struct cli_state *c,
130                         const char *sharename)
131 {
132         uint16 major, minor;
133         uint32 caplow, caphigh;
134         NTSTATUS status;
135
136         if (!SERVER_HAS_UNIX_CIFS(c)) {
137                 d_printf("Encryption required and "
138                         "server that doesn't support "
139                         "UNIX extensions - failing connect\n");
140                         return false;
141         }
142
143         status = cli_unix_extensions_version(c, &major, &minor, &caplow,
144                                              &caphigh);
145         if (!NT_STATUS_IS_OK(status)) {
146                 d_printf("Encryption required and "
147                         "can't get UNIX CIFS extensions "
148                         "version from server: %s\n", nt_errstr(status));
149                 return false;
150         }
151
152         if (!(caplow & CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP)) {
153                 d_printf("Encryption required and "
154                         "share %s doesn't support "
155                         "encryption.\n", sharename);
156                 return false;
157         }
158
159         if (c->use_kerberos) {
160                 status = cli_gss_smb_encryption_start(c);
161         } else {
162                 status = cli_raw_ntlm_smb_encryption_start(c,
163                                                 username,
164                                                 password,
165                                                 workgroup);
166         }
167
168         if (!NT_STATUS_IS_OK(status)) {
169                 d_printf("Encryption required and "
170                         "setup failed with error %s.\n",
171                         nt_errstr(status));
172                 return false;
173         }
174
175         return true;
176 }
177
178
179 static struct cli_state *open_nbt_connection(void)
180 {
181         struct cli_state *c;
182         NTSTATUS status;
183
184         status = cli_connect_nb(host, NULL, port_to_use, 0x20, myname,
185                                 signing_state, &c);
186         if (!NT_STATUS_IS_OK(status)) {
187                 printf("Failed to connect with %s. Error %s\n", host, nt_errstr(status) );
188                 return NULL;
189         }
190
191         c->use_kerberos = use_kerberos;
192
193         c->timeout = 120000; /* set a really long timeout (2 minutes) */
194         if (use_oplocks) c->use_oplocks = True;
195         if (use_level_II_oplocks) c->use_level_II_oplocks = True;
196
197         return c;
198 }
199
200 /****************************************************************************
201  Send a corrupt session request. See rfc1002.txt 4.3 and 4.3.2.
202 ****************************************************************************/
203
204 static bool cli_bad_session_request(int fd,
205                          struct nmb_name *calling, struct nmb_name *called)
206 {
207         TALLOC_CTX *frame;
208         uint8_t len_buf[4];
209         struct iovec iov[3];
210         ssize_t len;
211         uint8_t *inbuf;
212         int err;
213         bool ret = false;
214         uint8_t message_type;
215         uint8_t error;
216
217         frame = talloc_stackframe();
218
219         iov[0].iov_base = len_buf;
220         iov[0].iov_len  = sizeof(len_buf);
221
222         /* put in the destination name */
223
224         iov[1].iov_base = name_mangle(talloc_tos(), called->name,
225                                       called->name_type);
226         if (iov[1].iov_base == NULL) {
227                 goto fail;
228         }
229         iov[1].iov_len = name_len((unsigned char *)iov[1].iov_base,
230                                   talloc_get_size(iov[1].iov_base));
231
232         /* and my name */
233
234         iov[2].iov_base = name_mangle(talloc_tos(), calling->name,
235                                       calling->name_type);
236         if (iov[2].iov_base == NULL) {
237                 goto fail;
238         }
239         iov[2].iov_len = name_len((unsigned char *)iov[2].iov_base,
240                                   talloc_get_size(iov[2].iov_base));
241
242         /* Deliberately corrupt the name len (first byte) */
243         *((uint8_t *)iov[2].iov_base) = 100;
244
245         /* send a session request (RFC 1002) */
246         /* setup the packet length
247          * Remove four bytes from the length count, since the length
248          * field in the NBT Session Service header counts the number
249          * of bytes which follow.  The cli_send_smb() function knows
250          * about this and accounts for those four bytes.
251          * CRH.
252          */
253
254         _smb_setlen(len_buf, iov[1].iov_len + iov[2].iov_len);
255         SCVAL(len_buf,0,0x81);
256
257         len = write_data_iov(fd, iov, 3);
258         if (len == -1) {
259                 goto fail;
260         }
261         len = read_smb(fd, talloc_tos(), &inbuf, &err);
262         if (len == -1) {
263                 errno = err;
264                 goto fail;
265         }
266
267         message_type = CVAL(inbuf, 0);
268         if (message_type != 0x83) {
269                 d_fprintf(stderr, "Expected msg type 0x83, got 0x%2.2x\n",
270                           message_type);
271                 goto fail;
272         }
273
274         if (smb_len(inbuf) != 1) {
275                 d_fprintf(stderr, "Expected smb_len 1, got %d\n",
276                           (int)smb_len(inbuf));
277                 goto fail;
278         }
279
280         error = CVAL(inbuf, 4);
281         if (error !=  0x82) {
282                 d_fprintf(stderr, "Expected error 0x82, got %d\n",
283                           (int)error);
284                 goto fail;
285         }
286
287         ret = true;
288 fail:
289         TALLOC_FREE(frame);
290         return ret;
291 }
292
293 /* Insert a NULL at the first separator of the given path and return a pointer
294  * to the remainder of the string.
295  */
296 static char *
297 terminate_path_at_separator(char * path)
298 {
299         char * p;
300
301         if (!path) {
302                 return NULL;
303         }
304
305         if ((p = strchr_m(path, '/'))) {
306                 *p = '\0';
307                 return p + 1;
308         }
309
310         if ((p = strchr_m(path, '\\'))) {
311                 *p = '\0';
312                 return p + 1;
313         }
314
315         /* No separator. */
316         return NULL;
317 }
318
319 /*
320   parse a //server/share type UNC name
321 */
322 bool smbcli_parse_unc(const char *unc_name, TALLOC_CTX *mem_ctx,
323                       char **hostname, char **sharename)
324 {
325         char *p;
326
327         *hostname = *sharename = NULL;
328
329         if (strncmp(unc_name, "\\\\", 2) &&
330             strncmp(unc_name, "//", 2)) {
331                 return False;
332         }
333
334         *hostname = talloc_strdup(mem_ctx, &unc_name[2]);
335         p = terminate_path_at_separator(*hostname);
336
337         if (p && *p) {
338                 *sharename = talloc_strdup(mem_ctx, p);
339                 terminate_path_at_separator(*sharename);
340         }
341
342         if (*hostname && *sharename) {
343                 return True;
344         }
345
346         TALLOC_FREE(*hostname);
347         TALLOC_FREE(*sharename);
348         return False;
349 }
350
351 static bool torture_open_connection_share(struct cli_state **c,
352                                    const char *hostname, 
353                                    const char *sharename)
354 {
355         int flags = 0;
356         NTSTATUS status;
357
358         if (use_kerberos)
359                 flags |= CLI_FULL_CONNECTION_USE_KERBEROS;
360         if (use_oplocks)
361                 flags |= CLI_FULL_CONNECTION_OPLOCKS;
362         if (use_level_II_oplocks)
363                 flags |= CLI_FULL_CONNECTION_LEVEL_II_OPLOCKS;
364
365         status = cli_full_connection(c, myname,
366                                      hostname, NULL, port_to_use, 
367                                      sharename, "?????", 
368                                      username, workgroup, 
369                                      password, flags, signing_state);
370         if (!NT_STATUS_IS_OK(status)) {
371                 printf("failed to open share connection: //%s/%s port:%d - %s\n",
372                         hostname, sharename, port_to_use, nt_errstr(status));
373                 return False;
374         }
375
376         (*c)->timeout = 120000; /* set a really long timeout (2 minutes) */
377
378         if (do_encrypt) {
379                 return force_cli_encryption(*c,
380                                         sharename);
381         }
382         return True;
383 }
384
385 bool torture_open_connection(struct cli_state **c, int conn_index)
386 {
387         char **unc_list = NULL;
388         int num_unc_names = 0;
389         bool result;
390
391         if (use_multishare_conn==True) {
392                 char *h, *s;
393                 unc_list = file_lines_load(multishare_conn_fname, &num_unc_names, 0, NULL);
394                 if (!unc_list || num_unc_names <= 0) {
395                         printf("Failed to load unc names list from '%s'\n", multishare_conn_fname);
396                         exit(1);
397                 }
398
399                 if (!smbcli_parse_unc(unc_list[conn_index % num_unc_names],
400                                       NULL, &h, &s)) {
401                         printf("Failed to parse UNC name %s\n",
402                                unc_list[conn_index % num_unc_names]);
403                         TALLOC_FREE(unc_list);
404                         exit(1);
405                 }
406
407                 result = torture_open_connection_share(c, h, s);
408
409                 /* h, s were copied earlier */
410                 TALLOC_FREE(unc_list);
411                 return result;
412         }
413
414         return torture_open_connection_share(c, host, share);
415 }
416
417 bool torture_init_connection(struct cli_state **pcli)
418 {
419         struct cli_state *cli;
420
421         cli = open_nbt_connection();
422         if (cli == NULL) {
423                 return false;
424         }
425
426         *pcli = cli;
427         return true;
428 }
429
430 bool torture_cli_session_setup2(struct cli_state *cli, uint16 *new_vuid)
431 {
432         uint16 old_vuid = cli->vuid;
433         fstring old_user_name;
434         size_t passlen = strlen(password);
435         NTSTATUS status;
436         bool ret;
437
438         fstrcpy(old_user_name, cli->user_name);
439         cli->vuid = 0;
440         ret = NT_STATUS_IS_OK(cli_session_setup(cli, username,
441                                                 password, passlen,
442                                                 password, passlen,
443                                                 workgroup));
444         *new_vuid = cli->vuid;
445         cli->vuid = old_vuid;
446         status = cli_set_username(cli, old_user_name);
447         if (!NT_STATUS_IS_OK(status)) {
448                 return false;
449         }
450         return ret;
451 }
452
453
454 bool torture_close_connection(struct cli_state *c)
455 {
456         bool ret = True;
457         NTSTATUS status;
458
459         status = cli_tdis(c);
460         if (!NT_STATUS_IS_OK(status)) {
461                 printf("tdis failed (%s)\n", nt_errstr(status));
462                 ret = False;
463         }
464
465         cli_shutdown(c);
466
467         return ret;
468 }
469
470
471 /* check if the server produced the expected dos or nt error code */
472 static bool check_both_error(int line, NTSTATUS status,
473                              uint8 eclass, uint32 ecode, NTSTATUS nterr)
474 {
475         if (NT_STATUS_IS_DOS(status)) {
476                 uint8 cclass;
477                 uint32 num;
478
479                 /* Check DOS error */
480                 cclass = NT_STATUS_DOS_CLASS(status);
481                 num = NT_STATUS_DOS_CODE(status);
482
483                 if (eclass != cclass || ecode != num) {
484                         printf("unexpected error code class=%d code=%d\n",
485                                (int)cclass, (int)num);
486                         printf(" expected %d/%d %s (line=%d)\n",
487                                (int)eclass, (int)ecode, nt_errstr(nterr), line);
488                         return false;
489                 }
490         } else {
491                 /* Check NT error */
492                 if (!NT_STATUS_EQUAL(nterr, status)) {
493                         printf("unexpected error code %s\n",
494                                 nt_errstr(status));
495                         printf(" expected %s (line=%d)\n",
496                                 nt_errstr(nterr), line);
497                         return false;
498                 }
499         }
500
501         return true;
502 }
503
504
505 /* check if the server produced the expected error code */
506 static bool check_error(int line, struct cli_state *c, 
507                         uint8 eclass, uint32 ecode, NTSTATUS nterr)
508 {
509         if (cli_is_dos_error(c)) {
510                 uint8 cclass;
511                 uint32 num;
512
513                 /* Check DOS error */
514
515                 cli_dos_error(c, &cclass, &num);
516
517                 if (eclass != cclass || ecode != num) {
518                         printf("unexpected error code class=%d code=%d\n", 
519                                (int)cclass, (int)num);
520                         printf(" expected %d/%d %s (line=%d)\n", 
521                                (int)eclass, (int)ecode, nt_errstr(nterr), line);
522                         return False;
523                 }
524
525         } else {
526                 NTSTATUS status;
527
528                 /* Check NT error */
529
530                 status = cli_nt_error(c);
531
532                 if (NT_STATUS_V(nterr) != NT_STATUS_V(status)) {
533                         printf("unexpected error code %s\n", nt_errstr(status));
534                         printf(" expected %s (line=%d)\n", nt_errstr(nterr), line);
535                         return False;
536                 }
537         }
538
539         return True;
540 }
541
542
543 static bool wait_lock(struct cli_state *c, int fnum, uint32 offset, uint32 len)
544 {
545         NTSTATUS status;
546
547         status = cli_lock32(c, fnum, offset, len, -1, WRITE_LOCK);
548
549         while (!NT_STATUS_IS_OK(status)) {
550                 if (!check_both_error(__LINE__, status, ERRDOS,
551                                       ERRlock, NT_STATUS_LOCK_NOT_GRANTED)) {
552                         return false;
553                 }
554
555                 status = cli_lock32(c, fnum, offset, len, -1, WRITE_LOCK);
556         }
557
558         return true;
559 }
560
561
562 static bool rw_torture(struct cli_state *c)
563 {
564         const char *lockfname = "\\torture.lck";
565         fstring fname;
566         uint16_t fnum;
567         uint16_t fnum2;
568         pid_t pid2, pid = getpid();
569         int i, j;
570         char buf[1024];
571         bool correct = True;
572         size_t nread = 0;
573         NTSTATUS status;
574
575         memset(buf, '\0', sizeof(buf));
576
577         status = cli_open(c, lockfname, O_RDWR | O_CREAT | O_EXCL, 
578                          DENY_NONE, &fnum2);
579         if (!NT_STATUS_IS_OK(status)) {
580                 status = cli_open(c, lockfname, O_RDWR, DENY_NONE, &fnum2);
581         }
582         if (!NT_STATUS_IS_OK(status)) {
583                 printf("open of %s failed (%s)\n",
584                        lockfname, nt_errstr(status));
585                 return False;
586         }
587
588         for (i=0;i<torture_numops;i++) {
589                 unsigned n = (unsigned)sys_random()%10;
590
591                 if (i % 10 == 0) {
592                         printf("%d\r", i); fflush(stdout);
593                 }
594                 slprintf(fname, sizeof(fstring) - 1, "\\torture.%u", n);
595
596                 if (!wait_lock(c, fnum2, n*sizeof(int), sizeof(int))) {
597                         return False;
598                 }
599
600                 status = cli_open(c, fname, O_RDWR | O_CREAT | O_TRUNC,
601                                   DENY_ALL, &fnum);
602                 if (!NT_STATUS_IS_OK(status)) {
603                         printf("open failed (%s)\n", nt_errstr(status));
604                         correct = False;
605                         break;
606                 }
607
608                 status = cli_writeall(c, fnum, 0, (uint8_t *)&pid, 0,
609                                       sizeof(pid), NULL);
610                 if (!NT_STATUS_IS_OK(status)) {
611                         printf("write failed (%s)\n", nt_errstr(status));
612                         correct = False;
613                 }
614
615                 for (j=0;j<50;j++) {
616                         status = cli_writeall(c, fnum, 0, (uint8_t *)buf,
617                                               sizeof(pid)+(j*sizeof(buf)),
618                                               sizeof(buf), NULL);
619                         if (!NT_STATUS_IS_OK(status)) {
620                                 printf("write failed (%s)\n",
621                                        nt_errstr(status));
622                                 correct = False;
623                         }
624                 }
625
626                 pid2 = 0;
627
628                 status = cli_read(c, fnum, (char *)&pid2, 0, sizeof(pid),
629                                   &nread);
630                 if (!NT_STATUS_IS_OK(status)) {
631                         printf("read failed (%s)\n", nt_errstr(status));
632                         correct = false;
633                 } else if (nread != sizeof(pid)) {
634                         printf("read/write compare failed: "
635                                "recv %ld req %ld\n", (unsigned long)nread,
636                                (unsigned long)sizeof(pid));
637                         correct = false;
638                 }
639
640                 if (pid2 != pid) {
641                         printf("data corruption!\n");
642                         correct = False;
643                 }
644
645                 status = cli_close(c, fnum);
646                 if (!NT_STATUS_IS_OK(status)) {
647                         printf("close failed (%s)\n", nt_errstr(status));
648                         correct = False;
649                 }
650
651                 status = cli_unlink(c, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
652                 if (!NT_STATUS_IS_OK(status)) {
653                         printf("unlink failed (%s)\n", nt_errstr(status));
654                         correct = False;
655                 }
656
657                 status = cli_unlock(c, fnum2, n*sizeof(int), sizeof(int));
658                 if (!NT_STATUS_IS_OK(status)) {
659                         printf("unlock failed (%s)\n", nt_errstr(status));
660                         correct = False;
661                 }
662         }
663
664         cli_close(c, fnum2);
665         cli_unlink(c, lockfname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
666
667         printf("%d\n", i);
668
669         return correct;
670 }
671
672 static bool run_torture(int dummy)
673 {
674         struct cli_state *cli;
675         bool ret;
676
677         cli = current_cli;
678
679         cli_sockopt(cli, sockops);
680
681         ret = rw_torture(cli);
682
683         if (!torture_close_connection(cli)) {
684                 ret = False;
685         }
686
687         return ret;
688 }
689
690 static bool rw_torture3(struct cli_state *c, char *lockfname)
691 {
692         uint16_t fnum = (uint16_t)-1;
693         unsigned int i = 0;
694         char buf[131072];
695         char buf_rd[131072];
696         unsigned count;
697         unsigned countprev = 0;
698         size_t sent = 0;
699         bool correct = True;
700         NTSTATUS status = NT_STATUS_OK;
701
702         srandom(1);
703         for (i = 0; i < sizeof(buf); i += sizeof(uint32))
704         {
705                 SIVAL(buf, i, sys_random());
706         }
707
708         if (procnum == 0)
709         {
710                 status = cli_unlink(
711                         c, lockfname,
712                         FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
713                 if (!NT_STATUS_IS_OK(status)) {
714                         printf("unlink failed (%s) (normal, this file should "
715                                "not exist)\n", nt_errstr(status));
716                 }
717
718                 status = cli_open(c, lockfname, O_RDWR | O_CREAT | O_EXCL,
719                                   DENY_NONE, &fnum);
720                 if (!NT_STATUS_IS_OK(status)) {
721                         printf("first open read/write of %s failed (%s)\n",
722                                         lockfname, nt_errstr(status));
723                         return False;
724                 }
725         }
726         else
727         {
728                 for (i = 0; i < 500 && fnum == (uint16_t)-1; i++)
729                 {
730                         status = cli_open(c, lockfname, O_RDONLY, 
731                                          DENY_NONE, &fnum);
732                         if (!NT_STATUS_IS_OK(status)) {
733                                 break;
734                         }
735                         smb_msleep(10);
736                 }
737                 if (!NT_STATUS_IS_OK(status)) {
738                         printf("second open read-only of %s failed (%s)\n",
739                                         lockfname, nt_errstr(status));
740                         return False;
741                 }
742         }
743
744         i = 0;
745         for (count = 0; count < sizeof(buf); count += sent)
746         {
747                 if (count >= countprev) {
748                         printf("%d %8d\r", i, count);
749                         fflush(stdout);
750                         i++;
751                         countprev += (sizeof(buf) / 20);
752                 }
753
754                 if (procnum == 0)
755                 {
756                         sent = ((unsigned)sys_random()%(20))+ 1;
757                         if (sent > sizeof(buf) - count)
758                         {
759                                 sent = sizeof(buf) - count;
760                         }
761
762                         status = cli_writeall(c, fnum, 0, (uint8_t *)buf+count,
763                                               count, sent, NULL);
764                         if (!NT_STATUS_IS_OK(status)) {
765                                 printf("write failed (%s)\n",
766                                        nt_errstr(status));
767                                 correct = False;
768                         }
769                 }
770                 else
771                 {
772                         status = cli_read(c, fnum, buf_rd+count, count,
773                                           sizeof(buf)-count, &sent);
774                         if(!NT_STATUS_IS_OK(status)) {
775                                 printf("read failed offset:%d size:%ld (%s)\n",
776                                        count, (unsigned long)sizeof(buf)-count,
777                                        nt_errstr(status));
778                                 correct = False;
779                                 sent = 0;
780                         } else if (sent > 0) {
781                                 if (memcmp(buf_rd+count, buf+count, sent) != 0)
782                                 {
783                                         printf("read/write compare failed\n");
784                                         printf("offset: %d req %ld recvd %ld\n", count, (unsigned long)sizeof(buf)-count, (unsigned long)sent);
785                                         correct = False;
786                                         break;
787                                 }
788                         }
789                 }
790
791         }
792
793         status = cli_close(c, fnum);
794         if (!NT_STATUS_IS_OK(status)) {
795                 printf("close failed (%s)\n", nt_errstr(status));
796                 correct = False;
797         }
798
799         return correct;
800 }
801
802 static bool rw_torture2(struct cli_state *c1, struct cli_state *c2)
803 {
804         const char *lockfname = "\\torture2.lck";
805         uint16_t fnum1;
806         uint16_t fnum2;
807         int i;
808         char buf[131072];
809         char buf_rd[131072];
810         bool correct = True;
811         size_t bytes_read;
812         NTSTATUS status;
813
814         status = cli_unlink(c1, lockfname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
815         if (!NT_STATUS_IS_OK(status)) {
816                 printf("unlink failed (%s) (normal, this file should not exist)\n", nt_errstr(status));
817         }
818
819         status = cli_open(c1, lockfname, O_RDWR | O_CREAT | O_EXCL,
820                           DENY_NONE, &fnum1);
821         if (!NT_STATUS_IS_OK(status)) {
822                 printf("first open read/write of %s failed (%s)\n",
823                                 lockfname, nt_errstr(status));
824                 return False;
825         }
826
827         status = cli_open(c2, lockfname, O_RDONLY, DENY_NONE, &fnum2);
828         if (!NT_STATUS_IS_OK(status)) {
829                 printf("second open read-only of %s failed (%s)\n",
830                                 lockfname, nt_errstr(status));
831                 cli_close(c1, fnum1);
832                 return False;
833         }
834
835         for (i = 0; i < torture_numops; i++)
836         {
837                 size_t buf_size = ((unsigned)sys_random()%(sizeof(buf)-1))+ 1;
838                 if (i % 10 == 0) {
839                         printf("%d\r", i); fflush(stdout);
840                 }
841
842                 generate_random_buffer((unsigned char *)buf, buf_size);
843
844                 status = cli_writeall(c1, fnum1, 0, (uint8_t *)buf, 0,
845                                       buf_size, NULL);
846                 if (!NT_STATUS_IS_OK(status)) {
847                         printf("write failed (%s)\n", nt_errstr(status));
848                         correct = False;
849                         break;
850                 }
851
852                 status = cli_read(c2, fnum2, buf_rd, 0, buf_size, &bytes_read);
853                 if(!NT_STATUS_IS_OK(status)) {
854                         printf("read failed (%s)\n", nt_errstr(status));
855                         correct = false;
856                         break;
857                 } else if (bytes_read != buf_size) {
858                         printf("read failed\n");
859                         printf("read %ld, expected %ld\n",
860                                (unsigned long)bytes_read,
861                                (unsigned long)buf_size); 
862                         correct = False;
863                         break;
864                 }
865
866                 if (memcmp(buf_rd, buf, buf_size) != 0)
867                 {
868                         printf("read/write compare failed\n");
869                         correct = False;
870                         break;
871                 }
872         }
873
874         status = cli_close(c2, fnum2);
875         if (!NT_STATUS_IS_OK(status)) {
876                 printf("close failed (%s)\n", nt_errstr(status));
877                 correct = False;
878         }
879
880         status = cli_close(c1, fnum1);
881         if (!NT_STATUS_IS_OK(status)) {
882                 printf("close failed (%s)\n", nt_errstr(status));
883                 correct = False;
884         }
885
886         status = cli_unlink(c1, lockfname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
887         if (!NT_STATUS_IS_OK(status)) {
888                 printf("unlink failed (%s)\n", nt_errstr(status));
889                 correct = False;
890         }
891
892         return correct;
893 }
894
895 static bool run_readwritetest(int dummy)
896 {
897         struct cli_state *cli1, *cli2;
898         bool test1, test2 = False;
899
900         if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
901                 return False;
902         }
903         cli_sockopt(cli1, sockops);
904         cli_sockopt(cli2, sockops);
905
906         printf("starting readwritetest\n");
907
908         test1 = rw_torture2(cli1, cli2);
909         printf("Passed readwritetest v1: %s\n", BOOLSTR(test1));
910
911         if (test1) {
912                 test2 = rw_torture2(cli1, cli1);
913                 printf("Passed readwritetest v2: %s\n", BOOLSTR(test2));
914         }
915
916         if (!torture_close_connection(cli1)) {
917                 test1 = False;
918         }
919
920         if (!torture_close_connection(cli2)) {
921                 test2 = False;
922         }
923
924         return (test1 && test2);
925 }
926
927 static bool run_readwritemulti(int dummy)
928 {
929         struct cli_state *cli;
930         bool test;
931
932         cli = current_cli;
933
934         cli_sockopt(cli, sockops);
935
936         printf("run_readwritemulti: fname %s\n", randomfname);
937         test = rw_torture3(cli, randomfname);
938
939         if (!torture_close_connection(cli)) {
940                 test = False;
941         }
942
943         return test;
944 }
945
946 static bool run_readwritelarge_internal(int max_xmit_k)
947 {
948         static struct cli_state *cli1;
949         uint16_t fnum1;
950         const char *lockfname = "\\large.dat";
951         SMB_OFF_T fsize;
952         char buf[126*1024];
953         bool correct = True;
954         NTSTATUS status;
955
956         if (!torture_open_connection(&cli1, 0)) {
957                 return False;
958         }
959         cli_sockopt(cli1, sockops);
960         memset(buf,'\0',sizeof(buf));
961
962         cli1->max_xmit = max_xmit_k*1024;
963
964         if (signing_state == Required) {
965                 /* Horrible cheat to force
966                    multiple signed outstanding
967                    packets against a Samba server.
968                 */
969                 cli1->is_samba = false;
970         }
971
972         printf("starting readwritelarge_internal\n");
973
974         cli_unlink(cli1, lockfname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
975
976         status = cli_open(cli1, lockfname, O_RDWR | O_CREAT | O_EXCL,
977                           DENY_NONE, &fnum1);
978         if (!NT_STATUS_IS_OK(status)) {
979                 printf("open read/write of %s failed (%s)\n", lockfname, nt_errstr(status));
980                 return False;
981         }
982
983         cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 0, sizeof(buf), NULL);
984
985         status = cli_qfileinfo_basic(cli1, fnum1, NULL, &fsize, NULL, NULL,
986                                      NULL, NULL, NULL);
987         if (!NT_STATUS_IS_OK(status)) {
988                 printf("qfileinfo failed (%s)\n", nt_errstr(status));
989                 correct = False;
990         }
991
992         if (fsize == sizeof(buf))
993                 printf("readwritelarge_internal test 1 succeeded (size = %lx)\n",
994                        (unsigned long)fsize);
995         else {
996                 printf("readwritelarge_internal test 1 failed (size = %lx)\n",
997                        (unsigned long)fsize);
998                 correct = False;
999         }
1000
1001         status = cli_close(cli1, fnum1);
1002         if (!NT_STATUS_IS_OK(status)) {
1003                 printf("close failed (%s)\n", nt_errstr(status));
1004                 correct = False;
1005         }
1006
1007         status = cli_unlink(cli1, lockfname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1008         if (!NT_STATUS_IS_OK(status)) {
1009                 printf("unlink failed (%s)\n", nt_errstr(status));
1010                 correct = False;
1011         }
1012
1013         status = cli_open(cli1, lockfname, O_RDWR | O_CREAT | O_EXCL,
1014                           DENY_NONE, &fnum1);
1015         if (!NT_STATUS_IS_OK(status)) {
1016                 printf("open read/write of %s failed (%s)\n", lockfname, nt_errstr(status));
1017                 return False;
1018         }
1019
1020         cli1->max_xmit = 4*1024;
1021
1022         cli_smbwrite(cli1, fnum1, buf, 0, sizeof(buf), NULL);
1023
1024         status = cli_qfileinfo_basic(cli1, fnum1, NULL, &fsize, NULL, NULL,
1025                                      NULL, NULL, NULL);
1026         if (!NT_STATUS_IS_OK(status)) {
1027                 printf("qfileinfo failed (%s)\n", nt_errstr(status));
1028                 correct = False;
1029         }
1030
1031         if (fsize == sizeof(buf))
1032                 printf("readwritelarge_internal test 2 succeeded (size = %lx)\n",
1033                        (unsigned long)fsize);
1034         else {
1035                 printf("readwritelarge_internal test 2 failed (size = %lx)\n",
1036                        (unsigned long)fsize);
1037                 correct = False;
1038         }
1039
1040 #if 0
1041         /* ToDo - set allocation. JRA */
1042         if(!cli_set_allocation_size(cli1, fnum1, 0)) {
1043                 printf("set allocation size to zero failed (%s)\n", cli_errstr(&cli1));
1044                 return False;
1045         }
1046         if (!cli_qfileinfo_basic(cli1, fnum1, NULL, &fsize, NULL, NULL, NULL,
1047                                  NULL, NULL)) {
1048                 printf("qfileinfo failed (%s)\n", cli_errstr(cli1));
1049                 correct = False;
1050         }
1051         if (fsize != 0)
1052                 printf("readwritelarge test 3 (truncate test) succeeded (size = %x)\n", fsize);
1053 #endif
1054
1055         status = cli_close(cli1, fnum1);
1056         if (!NT_STATUS_IS_OK(status)) {
1057                 printf("close failed (%s)\n", nt_errstr(status));
1058                 correct = False;
1059         }
1060
1061         if (!torture_close_connection(cli1)) {
1062                 correct = False;
1063         }
1064         return correct;
1065 }
1066
1067 static bool run_readwritelarge(int dummy)
1068 {
1069         return run_readwritelarge_internal(128);
1070 }
1071
1072 static bool run_readwritelarge_signtest(int dummy)
1073 {
1074         bool ret;
1075         signing_state = Required;
1076         ret = run_readwritelarge_internal(2);
1077         signing_state = Undefined;
1078         return ret;
1079 }
1080
1081 int line_count = 0;
1082 int nbio_id;
1083
1084 #define ival(s) strtol(s, NULL, 0)
1085
1086 /* run a test that simulates an approximate netbench client load */
1087 static bool run_netbench(int client)
1088 {
1089         struct cli_state *cli;
1090         int i;
1091         char line[1024];
1092         char cname[20];
1093         FILE *f;
1094         const char *params[20];
1095         bool correct = True;
1096
1097         cli = current_cli;
1098
1099         nbio_id = client;
1100
1101         cli_sockopt(cli, sockops);
1102
1103         nb_setup(cli);
1104
1105         slprintf(cname,sizeof(cname)-1, "client%d", client);
1106
1107         f = fopen(client_txt, "r");
1108
1109         if (!f) {
1110                 perror(client_txt);
1111                 return False;
1112         }
1113
1114         while (fgets(line, sizeof(line)-1, f)) {
1115                 char *saveptr;
1116                 line_count++;
1117
1118                 line[strlen(line)-1] = 0;
1119
1120                 /* printf("[%d] %s\n", line_count, line); */
1121
1122                 all_string_sub(line,"client1", cname, sizeof(line));
1123
1124                 /* parse the command parameters */
1125                 params[0] = strtok_r(line, " ", &saveptr);
1126                 i = 0;
1127                 while (params[i]) params[++i] = strtok_r(NULL, " ", &saveptr);
1128
1129                 params[i] = "";
1130
1131                 if (i < 2) continue;
1132
1133                 if (!strncmp(params[0],"SMB", 3)) {
1134                         printf("ERROR: You are using a dbench 1 load file\n");
1135                         exit(1);
1136                 }
1137
1138                 if (!strcmp(params[0],"NTCreateX")) {
1139                         nb_createx(params[1], ival(params[2]), ival(params[3]), 
1140                                    ival(params[4]));
1141                 } else if (!strcmp(params[0],"Close")) {
1142                         nb_close(ival(params[1]));
1143                 } else if (!strcmp(params[0],"Rename")) {
1144                         nb_rename(params[1], params[2]);
1145                 } else if (!strcmp(params[0],"Unlink")) {
1146                         nb_unlink(params[1]);
1147                 } else if (!strcmp(params[0],"Deltree")) {
1148                         nb_deltree(params[1]);
1149                 } else if (!strcmp(params[0],"Rmdir")) {
1150                         nb_rmdir(params[1]);
1151                 } else if (!strcmp(params[0],"QUERY_PATH_INFORMATION")) {
1152                         nb_qpathinfo(params[1]);
1153                 } else if (!strcmp(params[0],"QUERY_FILE_INFORMATION")) {
1154                         nb_qfileinfo(ival(params[1]));
1155                 } else if (!strcmp(params[0],"QUERY_FS_INFORMATION")) {
1156                         nb_qfsinfo(ival(params[1]));
1157                 } else if (!strcmp(params[0],"FIND_FIRST")) {
1158                         nb_findfirst(params[1]);
1159                 } else if (!strcmp(params[0],"WriteX")) {
1160                         nb_writex(ival(params[1]), 
1161                                   ival(params[2]), ival(params[3]), ival(params[4]));
1162                 } else if (!strcmp(params[0],"ReadX")) {
1163                         nb_readx(ival(params[1]), 
1164                                   ival(params[2]), ival(params[3]), ival(params[4]));
1165                 } else if (!strcmp(params[0],"Flush")) {
1166                         nb_flush(ival(params[1]));
1167                 } else {
1168                         printf("Unknown operation %s\n", params[0]);
1169                         exit(1);
1170                 }
1171         }
1172         fclose(f);
1173
1174         nb_cleanup();
1175
1176         if (!torture_close_connection(cli)) {
1177                 correct = False;
1178         }
1179
1180         return correct;
1181 }
1182
1183
1184 /* run a test that simulates an approximate netbench client load */
1185 static bool run_nbench(int dummy)
1186 {
1187         double t;
1188         bool correct = True;
1189
1190         nbio_shmem(nprocs);
1191
1192         nbio_id = -1;
1193
1194         signal(SIGALRM, nb_alarm);
1195         alarm(1);
1196         t = create_procs(run_netbench, &correct);
1197         alarm(0);
1198
1199         printf("\nThroughput %g MB/sec\n", 
1200                1.0e-6 * nbio_total() / t);
1201         return correct;
1202 }
1203
1204
1205 /*
1206   This test checks for two things:
1207
1208   1) correct support for retaining locks over a close (ie. the server
1209      must not use posix semantics)
1210   2) support for lock timeouts
1211  */
1212 static bool run_locktest1(int dummy)
1213 {
1214         struct cli_state *cli1, *cli2;
1215         const char *fname = "\\lockt1.lck";
1216         uint16_t fnum1, fnum2, fnum3;
1217         time_t t1, t2;
1218         unsigned lock_timeout;
1219         NTSTATUS status;
1220
1221         if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
1222                 return False;
1223         }
1224         cli_sockopt(cli1, sockops);
1225         cli_sockopt(cli2, sockops);
1226
1227         printf("starting locktest1\n");
1228
1229         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1230
1231         status = cli_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
1232                           &fnum1);
1233         if (!NT_STATUS_IS_OK(status)) {
1234                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
1235                 return False;
1236         }
1237
1238         status = cli_open(cli1, fname, O_RDWR, DENY_NONE, &fnum2);
1239         if (!NT_STATUS_IS_OK(status)) {
1240                 printf("open2 of %s failed (%s)\n", fname, nt_errstr(status));
1241                 return False;
1242         }
1243
1244         status = cli_open(cli2, fname, O_RDWR, DENY_NONE, &fnum3);
1245         if (!NT_STATUS_IS_OK(status)) {
1246                 printf("open3 of %s failed (%s)\n", fname, nt_errstr(status));
1247                 return False;
1248         }
1249
1250         status = cli_lock32(cli1, fnum1, 0, 4, 0, WRITE_LOCK);
1251         if (!NT_STATUS_IS_OK(status)) {
1252                 printf("lock1 failed (%s)\n", nt_errstr(status));
1253                 return false;
1254         }
1255
1256         status = cli_lock32(cli2, fnum3, 0, 4, 0, WRITE_LOCK);
1257         if (NT_STATUS_IS_OK(status)) {
1258                 printf("lock2 succeeded! This is a locking bug\n");
1259                 return false;
1260         } else {
1261                 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1262                                       NT_STATUS_LOCK_NOT_GRANTED)) {
1263                         return false;
1264                 }
1265         }
1266
1267         lock_timeout = (1 + (random() % 20));
1268         printf("Testing lock timeout with timeout=%u\n", lock_timeout);
1269         t1 = time(NULL);
1270         status = cli_lock32(cli2, fnum3, 0, 4, lock_timeout * 1000, WRITE_LOCK);
1271         if (NT_STATUS_IS_OK(status)) {
1272                 printf("lock3 succeeded! This is a locking bug\n");
1273                 return false;
1274         } else {
1275                 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1276                                       NT_STATUS_FILE_LOCK_CONFLICT)) {
1277                         return false;
1278                 }
1279         }
1280         t2 = time(NULL);
1281
1282         if (ABS(t2 - t1) < lock_timeout-1) {
1283                 printf("error: This server appears not to support timed lock requests\n");
1284         }
1285
1286         printf("server slept for %u seconds for a %u second timeout\n",
1287                (unsigned int)(t2-t1), lock_timeout);
1288
1289         status = cli_close(cli1, fnum2);
1290         if (!NT_STATUS_IS_OK(status)) {
1291                 printf("close1 failed (%s)\n", nt_errstr(status));
1292                 return False;
1293         }
1294
1295         status = cli_lock32(cli2, fnum3, 0, 4, 0, WRITE_LOCK);
1296         if (NT_STATUS_IS_OK(status)) {
1297                 printf("lock4 succeeded! This is a locking bug\n");
1298                 return false;
1299         } else {
1300                 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1301                                       NT_STATUS_FILE_LOCK_CONFLICT)) {
1302                         return false;
1303                 }
1304         }
1305
1306         status = cli_close(cli1, fnum1);
1307         if (!NT_STATUS_IS_OK(status)) {
1308                 printf("close2 failed (%s)\n", nt_errstr(status));
1309                 return False;
1310         }
1311
1312         status = cli_close(cli2, fnum3);
1313         if (!NT_STATUS_IS_OK(status)) {
1314                 printf("close3 failed (%s)\n", nt_errstr(status));
1315                 return False;
1316         }
1317
1318         status = cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1319         if (!NT_STATUS_IS_OK(status)) {
1320                 printf("unlink failed (%s)\n", nt_errstr(status));
1321                 return False;
1322         }
1323
1324
1325         if (!torture_close_connection(cli1)) {
1326                 return False;
1327         }
1328
1329         if (!torture_close_connection(cli2)) {
1330                 return False;
1331         }
1332
1333         printf("Passed locktest1\n");
1334         return True;
1335 }
1336
1337 /*
1338   this checks to see if a secondary tconx can use open files from an
1339   earlier tconx
1340  */
1341 static bool run_tcon_test(int dummy)
1342 {
1343         static struct cli_state *cli;
1344         const char *fname = "\\tcontest.tmp";
1345         uint16 fnum1;
1346         uint16 cnum1, cnum2, cnum3;
1347         uint16 vuid1, vuid2;
1348         char buf[4];
1349         bool ret = True;
1350         NTSTATUS status;
1351
1352         memset(buf, '\0', sizeof(buf));
1353
1354         if (!torture_open_connection(&cli, 0)) {
1355                 return False;
1356         }
1357         cli_sockopt(cli, sockops);
1358
1359         printf("starting tcontest\n");
1360
1361         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1362
1363         status = cli_open(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
1364         if (!NT_STATUS_IS_OK(status)) {
1365                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
1366                 return False;
1367         }
1368
1369         cnum1 = cli_state_get_tid(cli);
1370         vuid1 = cli->vuid;
1371
1372         status = cli_writeall(cli, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
1373         if (!NT_STATUS_IS_OK(status)) {
1374                 printf("initial write failed (%s)", nt_errstr(status));
1375                 return False;
1376         }
1377
1378         status = cli_tcon_andx(cli, share, "?????",
1379                                password, strlen(password)+1);
1380         if (!NT_STATUS_IS_OK(status)) {
1381                 printf("%s refused 2nd tree connect (%s)\n", host,
1382                        nt_errstr(status));
1383                 cli_shutdown(cli);
1384                 return False;
1385         }
1386
1387         cnum2 = cli_state_get_tid(cli);
1388         cnum3 = MAX(cnum1, cnum2) + 1; /* any invalid number */
1389         vuid2 = cli->vuid + 1;
1390
1391         /* try a write with the wrong tid */
1392         cli_state_set_tid(cli, cnum2);
1393
1394         status = cli_writeall(cli, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
1395         if (NT_STATUS_IS_OK(status)) {
1396                 printf("* server allows write with wrong TID\n");
1397                 ret = False;
1398         } else {
1399                 printf("server fails write with wrong TID : %s\n",
1400                        nt_errstr(status));
1401         }
1402
1403
1404         /* try a write with an invalid tid */
1405         cli_state_set_tid(cli, cnum3);
1406
1407         status = cli_writeall(cli, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
1408         if (NT_STATUS_IS_OK(status)) {
1409                 printf("* server allows write with invalid TID\n");
1410                 ret = False;
1411         } else {
1412                 printf("server fails write with invalid TID : %s\n",
1413                        nt_errstr(status));
1414         }
1415
1416         /* try a write with an invalid vuid */
1417         cli->vuid = vuid2;
1418         cli_state_set_tid(cli, cnum1);
1419
1420         status = cli_writeall(cli, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
1421         if (NT_STATUS_IS_OK(status)) {
1422                 printf("* server allows write with invalid VUID\n");
1423                 ret = False;
1424         } else {
1425                 printf("server fails write with invalid VUID : %s\n",
1426                        nt_errstr(status));
1427         }
1428
1429         cli_state_set_tid(cli, cnum1);
1430         cli->vuid = vuid1;
1431
1432         status = cli_close(cli, fnum1);
1433         if (!NT_STATUS_IS_OK(status)) {
1434                 printf("close failed (%s)\n", nt_errstr(status));
1435                 return False;
1436         }
1437
1438         cli_state_set_tid(cli, cnum2);
1439
1440         status = cli_tdis(cli);
1441         if (!NT_STATUS_IS_OK(status)) {
1442                 printf("secondary tdis failed (%s)\n", nt_errstr(status));
1443                 return False;
1444         }
1445
1446         cli_state_set_tid(cli, cnum1);
1447
1448         if (!torture_close_connection(cli)) {
1449                 return False;
1450         }
1451
1452         return ret;
1453 }
1454
1455
1456 /*
1457  checks for old style tcon support
1458  */
1459 static bool run_tcon2_test(int dummy)
1460 {
1461         static struct cli_state *cli;
1462         uint16 cnum, max_xmit;
1463         char *service;
1464         NTSTATUS status;
1465
1466         if (!torture_open_connection(&cli, 0)) {
1467                 return False;
1468         }
1469         cli_sockopt(cli, sockops);
1470
1471         printf("starting tcon2 test\n");
1472
1473         if (asprintf(&service, "\\\\%s\\%s", host, share) == -1) {
1474                 return false;
1475         }
1476
1477         status = cli_raw_tcon(cli, service, password, "?????", &max_xmit, &cnum);
1478
1479         SAFE_FREE(service);
1480
1481         if (!NT_STATUS_IS_OK(status)) {
1482                 printf("tcon2 failed : %s\n", nt_errstr(status));
1483         } else {
1484                 printf("tcon OK : max_xmit=%d cnum=%d\n",
1485                        (int)max_xmit, (int)cnum);
1486         }
1487
1488         if (!torture_close_connection(cli)) {
1489                 return False;
1490         }
1491
1492         printf("Passed tcon2 test\n");
1493         return True;
1494 }
1495
1496 static bool tcon_devtest(struct cli_state *cli,
1497                          const char *myshare, const char *devtype,
1498                          const char *return_devtype,
1499                          NTSTATUS expected_error)
1500 {
1501         NTSTATUS status;
1502         bool ret;
1503
1504         status = cli_tcon_andx(cli, myshare, devtype,
1505                                password, strlen(password)+1);
1506
1507         if (NT_STATUS_IS_OK(expected_error)) {
1508                 if (NT_STATUS_IS_OK(status)) {
1509                         if (strcmp(cli->dev, return_devtype) == 0) {
1510                                 ret = True;
1511                         } else { 
1512                                 printf("tconX to share %s with type %s "
1513                                        "succeeded but returned the wrong "
1514                                        "device type (got [%s] but should have got [%s])\n",
1515                                        myshare, devtype, cli->dev, return_devtype);
1516                                 ret = False;
1517                         }
1518                 } else {
1519                         printf("tconX to share %s with type %s "
1520                                "should have succeeded but failed\n",
1521                                myshare, devtype);
1522                         ret = False;
1523                 }
1524                 cli_tdis(cli);
1525         } else {
1526                 if (NT_STATUS_IS_OK(status)) {
1527                         printf("tconx to share %s with type %s "
1528                                "should have failed but succeeded\n",
1529                                myshare, devtype);
1530                         ret = False;
1531                 } else {
1532                         if (NT_STATUS_EQUAL(cli_nt_error(cli),
1533                                             expected_error)) {
1534                                 ret = True;
1535                         } else {
1536                                 printf("Returned unexpected error\n");
1537                                 ret = False;
1538                         }
1539                 }
1540         }
1541         return ret;
1542 }
1543
1544 /*
1545  checks for correct tconX support
1546  */
1547 static bool run_tcon_devtype_test(int dummy)
1548 {
1549         static struct cli_state *cli1 = NULL;
1550         int flags = 0;
1551         NTSTATUS status;
1552         bool ret = True;
1553
1554         status = cli_full_connection(&cli1, myname,
1555                                      host, NULL, port_to_use,
1556                                      NULL, NULL,
1557                                      username, workgroup,
1558                                      password, flags, signing_state);
1559
1560         if (!NT_STATUS_IS_OK(status)) {
1561                 printf("could not open connection\n");
1562                 return False;
1563         }
1564
1565         if (!tcon_devtest(cli1, "IPC$", "A:", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1566                 ret = False;
1567
1568         if (!tcon_devtest(cli1, "IPC$", "?????", "IPC", NT_STATUS_OK))
1569                 ret = False;
1570
1571         if (!tcon_devtest(cli1, "IPC$", "LPT:", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1572                 ret = False;
1573
1574         if (!tcon_devtest(cli1, "IPC$", "IPC", "IPC", NT_STATUS_OK))
1575                 ret = False;
1576
1577         if (!tcon_devtest(cli1, "IPC$", "FOOBA", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1578                 ret = False;
1579
1580         if (!tcon_devtest(cli1, share, "A:", "A:", NT_STATUS_OK))
1581                 ret = False;
1582
1583         if (!tcon_devtest(cli1, share, "?????", "A:", NT_STATUS_OK))
1584                 ret = False;
1585
1586         if (!tcon_devtest(cli1, share, "LPT:", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1587                 ret = False;
1588
1589         if (!tcon_devtest(cli1, share, "IPC", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1590                 ret = False;
1591
1592         if (!tcon_devtest(cli1, share, "FOOBA", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1593                 ret = False;
1594
1595         cli_shutdown(cli1);
1596
1597         if (ret)
1598                 printf("Passed tcondevtest\n");
1599
1600         return ret;
1601 }
1602
1603
1604 /*
1605   This test checks that 
1606
1607   1) the server supports multiple locking contexts on the one SMB
1608   connection, distinguished by PID.  
1609
1610   2) the server correctly fails overlapping locks made by the same PID (this
1611      goes against POSIX behaviour, which is why it is tricky to implement)
1612
1613   3) the server denies unlock requests by an incorrect client PID
1614 */
1615 static bool run_locktest2(int dummy)
1616 {
1617         static struct cli_state *cli;
1618         const char *fname = "\\lockt2.lck";
1619         uint16_t fnum1, fnum2, fnum3;
1620         bool correct = True;
1621         NTSTATUS status;
1622
1623         if (!torture_open_connection(&cli, 0)) {
1624                 return False;
1625         }
1626
1627         cli_sockopt(cli, sockops);
1628
1629         printf("starting locktest2\n");
1630
1631         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1632
1633         cli_setpid(cli, 1);
1634
1635         status = cli_open(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
1636         if (!NT_STATUS_IS_OK(status)) {
1637                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
1638                 return False;
1639         }
1640
1641         status = cli_open(cli, fname, O_RDWR, DENY_NONE, &fnum2);
1642         if (!NT_STATUS_IS_OK(status)) {
1643                 printf("open2 of %s failed (%s)\n", fname, nt_errstr(status));
1644                 return False;
1645         }
1646
1647         cli_setpid(cli, 2);
1648
1649         status = cli_open(cli, fname, O_RDWR, DENY_NONE, &fnum3);
1650         if (!NT_STATUS_IS_OK(status)) {
1651                 printf("open3 of %s failed (%s)\n", fname, nt_errstr(status));
1652                 return False;
1653         }
1654
1655         cli_setpid(cli, 1);
1656
1657         status = cli_lock32(cli, fnum1, 0, 4, 0, WRITE_LOCK);
1658         if (!NT_STATUS_IS_OK(status)) {
1659                 printf("lock1 failed (%s)\n", nt_errstr(status));
1660                 return false;
1661         }
1662
1663         status = cli_lock32(cli, fnum1, 0, 4, 0, WRITE_LOCK);
1664         if (NT_STATUS_IS_OK(status)) {
1665                 printf("WRITE lock1 succeeded! This is a locking bug\n");
1666                 correct = false;
1667         } else {
1668                 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1669                                       NT_STATUS_LOCK_NOT_GRANTED)) {
1670                         return false;
1671                 }
1672         }
1673
1674         status = cli_lock32(cli, fnum2, 0, 4, 0, WRITE_LOCK);
1675         if (NT_STATUS_IS_OK(status)) {
1676                 printf("WRITE lock2 succeeded! This is a locking bug\n");
1677                 correct = false;
1678         } else {
1679                 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1680                                       NT_STATUS_LOCK_NOT_GRANTED)) {
1681                         return false;
1682                 }
1683         }
1684
1685         status = cli_lock32(cli, fnum2, 0, 4, 0, READ_LOCK);
1686         if (NT_STATUS_IS_OK(status)) {
1687                 printf("READ lock2 succeeded! This is a locking bug\n");
1688                 correct = false;
1689         } else {
1690                 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1691                                  NT_STATUS_FILE_LOCK_CONFLICT)) {
1692                         return false;
1693                 }
1694         }
1695
1696         status = cli_lock32(cli, fnum1, 100, 4, 0, WRITE_LOCK);
1697         if (!NT_STATUS_IS_OK(status)) {
1698                 printf("lock at 100 failed (%s)\n", nt_errstr(status));
1699         }
1700         cli_setpid(cli, 2);
1701         if (NT_STATUS_IS_OK(cli_unlock(cli, fnum1, 100, 4))) {
1702                 printf("unlock at 100 succeeded! This is a locking bug\n");
1703                 correct = False;
1704         }
1705
1706         status = cli_unlock(cli, fnum1, 0, 4);
1707         if (NT_STATUS_IS_OK(status)) {
1708                 printf("unlock1 succeeded! This is a locking bug\n");
1709                 correct = false;
1710         } else {
1711                 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1712                                       NT_STATUS_RANGE_NOT_LOCKED)) {
1713                         return false;
1714                 }
1715         }
1716
1717         status = cli_unlock(cli, fnum1, 0, 8);
1718         if (NT_STATUS_IS_OK(status)) {
1719                 printf("unlock2 succeeded! This is a locking bug\n");
1720                 correct = false;
1721         } else {
1722                 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1723                                       NT_STATUS_RANGE_NOT_LOCKED)) {
1724                         return false;
1725                 }
1726         }
1727
1728         status = cli_lock32(cli, fnum3, 0, 4, 0, WRITE_LOCK);
1729         if (NT_STATUS_IS_OK(status)) {
1730                 printf("lock3 succeeded! This is a locking bug\n");
1731                 correct = false;
1732         } else {
1733                 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1734                                       NT_STATUS_LOCK_NOT_GRANTED)) {
1735                         return false;
1736                 }
1737         }
1738
1739         cli_setpid(cli, 1);
1740
1741         status = cli_close(cli, fnum1);
1742         if (!NT_STATUS_IS_OK(status)) {
1743                 printf("close1 failed (%s)\n", nt_errstr(status));
1744                 return False;
1745         }
1746
1747         status = cli_close(cli, fnum2);
1748         if (!NT_STATUS_IS_OK(status)) {
1749                 printf("close2 failed (%s)\n", nt_errstr(status));
1750                 return False;
1751         }
1752
1753         status = cli_close(cli, fnum3);
1754         if (!NT_STATUS_IS_OK(status)) {
1755                 printf("close3 failed (%s)\n", nt_errstr(status));
1756                 return False;
1757         }
1758
1759         if (!torture_close_connection(cli)) {
1760                 correct = False;
1761         }
1762
1763         printf("locktest2 finished\n");
1764
1765         return correct;
1766 }
1767
1768
1769 /*
1770   This test checks that 
1771
1772   1) the server supports the full offset range in lock requests
1773 */
1774 static bool run_locktest3(int dummy)
1775 {
1776         static struct cli_state *cli1, *cli2;
1777         const char *fname = "\\lockt3.lck";
1778         uint16_t fnum1, fnum2;
1779         int i;
1780         uint32 offset;
1781         bool correct = True;
1782         NTSTATUS status;
1783
1784 #define NEXT_OFFSET offset += (~(uint32)0) / torture_numops
1785
1786         if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
1787                 return False;
1788         }
1789         cli_sockopt(cli1, sockops);
1790         cli_sockopt(cli2, sockops);
1791
1792         printf("starting locktest3\n");
1793
1794         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1795
1796         status = cli_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
1797                          &fnum1);
1798         if (!NT_STATUS_IS_OK(status)) {
1799                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
1800                 return False;
1801         }
1802
1803         status = cli_open(cli2, fname, O_RDWR, DENY_NONE, &fnum2);
1804         if (!NT_STATUS_IS_OK(status)) {
1805                 printf("open2 of %s failed (%s)\n", fname, nt_errstr(status));
1806                 return False;
1807         }
1808
1809         for (offset=i=0;i<torture_numops;i++) {
1810                 NEXT_OFFSET;
1811
1812                 status = cli_lock32(cli1, fnum1, offset-1, 1, 0, WRITE_LOCK);
1813                 if (!NT_STATUS_IS_OK(status)) {
1814                         printf("lock1 %d failed (%s)\n", 
1815                                i,
1816                                nt_errstr(status));
1817                         return False;
1818                 }
1819
1820                 status = cli_lock32(cli2, fnum2, offset-2, 1, 0, WRITE_LOCK);
1821                 if (!NT_STATUS_IS_OK(status)) {
1822                         printf("lock2 %d failed (%s)\n", 
1823                                i,
1824                                nt_errstr(status));
1825                         return False;
1826                 }
1827         }
1828
1829         for (offset=i=0;i<torture_numops;i++) {
1830                 NEXT_OFFSET;
1831
1832                 status = cli_lock32(cli1, fnum1, offset-2, 1, 0, WRITE_LOCK);
1833                 if (NT_STATUS_IS_OK(status)) {
1834                         printf("error: lock1 %d succeeded!\n", i);
1835                         return False;
1836                 }
1837
1838                 status = cli_lock32(cli2, fnum2, offset-1, 1, 0, WRITE_LOCK);
1839                 if (NT_STATUS_IS_OK(status)) {
1840                         printf("error: lock2 %d succeeded!\n", i);
1841                         return False;
1842                 }
1843
1844                 status = cli_lock32(cli1, fnum1, offset-1, 1, 0, WRITE_LOCK);
1845                 if (NT_STATUS_IS_OK(status)) {
1846                         printf("error: lock3 %d succeeded!\n", i);
1847                         return False;
1848                 }
1849
1850                 status = cli_lock32(cli2, fnum2, offset-2, 1, 0, WRITE_LOCK);
1851                 if (NT_STATUS_IS_OK(status)) {
1852                         printf("error: lock4 %d succeeded!\n", i);
1853                         return False;
1854                 }
1855         }
1856
1857         for (offset=i=0;i<torture_numops;i++) {
1858                 NEXT_OFFSET;
1859
1860                 status = cli_unlock(cli1, fnum1, offset-1, 1);
1861                 if (!NT_STATUS_IS_OK(status)) {
1862                         printf("unlock1 %d failed (%s)\n", 
1863                                i,
1864                                nt_errstr(status));
1865                         return False;
1866                 }
1867
1868                 status = cli_unlock(cli2, fnum2, offset-2, 1);
1869                 if (!NT_STATUS_IS_OK(status)) {
1870                         printf("unlock2 %d failed (%s)\n", 
1871                                i,
1872                                nt_errstr(status));
1873                         return False;
1874                 }
1875         }
1876
1877         status = cli_close(cli1, fnum1);
1878         if (!NT_STATUS_IS_OK(status)) {
1879                 printf("close1 failed (%s)\n", nt_errstr(status));
1880                 return False;
1881         }
1882
1883         status = cli_close(cli2, fnum2);
1884         if (!NT_STATUS_IS_OK(status)) {
1885                 printf("close2 failed (%s)\n", nt_errstr(status));
1886                 return False;
1887         }
1888
1889         status = cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1890         if (!NT_STATUS_IS_OK(status)) {
1891                 printf("unlink failed (%s)\n", nt_errstr(status));
1892                 return False;
1893         }
1894
1895         if (!torture_close_connection(cli1)) {
1896                 correct = False;
1897         }
1898
1899         if (!torture_close_connection(cli2)) {
1900                 correct = False;
1901         }
1902
1903         printf("finished locktest3\n");
1904
1905         return correct;
1906 }
1907
1908 #define EXPECTED(ret, v) if ((ret) != (v)) { \
1909         printf("** "); correct = False; \
1910         }
1911
1912 /*
1913   looks at overlapping locks
1914 */
1915 static bool run_locktest4(int dummy)
1916 {
1917         static struct cli_state *cli1, *cli2;
1918         const char *fname = "\\lockt4.lck";
1919         uint16_t fnum1, fnum2, f;
1920         bool ret;
1921         char buf[1000];
1922         bool correct = True;
1923         NTSTATUS status;
1924
1925         if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
1926                 return False;
1927         }
1928
1929         cli_sockopt(cli1, sockops);
1930         cli_sockopt(cli2, sockops);
1931
1932         printf("starting locktest4\n");
1933
1934         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1935
1936         cli_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
1937         cli_open(cli2, fname, O_RDWR, DENY_NONE, &fnum2);
1938
1939         memset(buf, 0, sizeof(buf));
1940
1941         status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 0, sizeof(buf),
1942                               NULL);
1943         if (!NT_STATUS_IS_OK(status)) {
1944                 printf("Failed to create file: %s\n", nt_errstr(status));
1945                 correct = False;
1946                 goto fail;
1947         }
1948
1949         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 4, 0, WRITE_LOCK)) &&
1950               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 2, 4, 0, WRITE_LOCK));
1951         EXPECTED(ret, False);
1952         printf("the same process %s set overlapping write locks\n", ret?"can":"cannot");
1953
1954         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 10, 4, 0, READ_LOCK)) &&
1955               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 12, 4, 0, READ_LOCK));
1956         EXPECTED(ret, True);
1957         printf("the same process %s set overlapping read locks\n", ret?"can":"cannot");
1958
1959         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 20, 4, 0, WRITE_LOCK)) &&
1960               NT_STATUS_IS_OK(cli_lock32(cli2, fnum2, 22, 4, 0, WRITE_LOCK));
1961         EXPECTED(ret, False);
1962         printf("a different connection %s set overlapping write locks\n", ret?"can":"cannot");
1963
1964         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 30, 4, 0, READ_LOCK)) &&
1965               NT_STATUS_IS_OK(cli_lock32(cli2, fnum2, 32, 4, 0, READ_LOCK));
1966         EXPECTED(ret, True);
1967         printf("a different connection %s set overlapping read locks\n", ret?"can":"cannot");
1968
1969         ret = (cli_setpid(cli1, 1),
1970               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 40, 4, 0, WRITE_LOCK))) &&
1971               (cli_setpid(cli1, 2),
1972               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 42, 4, 0, WRITE_LOCK)));
1973         EXPECTED(ret, False);
1974         printf("a different pid %s set overlapping write locks\n", ret?"can":"cannot");
1975
1976         ret = (cli_setpid(cli1, 1),
1977               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 50, 4, 0, READ_LOCK))) &&
1978               (cli_setpid(cli1, 2),
1979               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 52, 4, 0, READ_LOCK)));
1980         EXPECTED(ret, True);
1981         printf("a different pid %s set overlapping read locks\n", ret?"can":"cannot");
1982
1983         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 60, 4, 0, READ_LOCK)) &&
1984               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 60, 4, 0, READ_LOCK));
1985         EXPECTED(ret, True);
1986         printf("the same process %s set the same read lock twice\n", ret?"can":"cannot");
1987
1988         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 70, 4, 0, WRITE_LOCK)) &&
1989               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 70, 4, 0, WRITE_LOCK));
1990         EXPECTED(ret, False);
1991         printf("the same process %s set the same write lock twice\n", ret?"can":"cannot");
1992
1993         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 80, 4, 0, READ_LOCK)) &&
1994               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 80, 4, 0, WRITE_LOCK));
1995         EXPECTED(ret, False);
1996         printf("the same process %s overlay a read lock with a write lock\n", ret?"can":"cannot");
1997
1998         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 90, 4, 0, WRITE_LOCK)) &&
1999               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 90, 4, 0, READ_LOCK));
2000         EXPECTED(ret, True);
2001         printf("the same process %s overlay a write lock with a read lock\n", ret?"can":"cannot");
2002
2003         ret = (cli_setpid(cli1, 1),
2004              NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 100, 4, 0, WRITE_LOCK))) &&
2005              (cli_setpid(cli1, 2),
2006              NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 100, 4, 0, READ_LOCK)));
2007         EXPECTED(ret, False);
2008         printf("a different pid %s overlay a write lock with a read lock\n", ret?"can":"cannot");
2009
2010         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 110, 4, 0, READ_LOCK)) &&
2011               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 112, 4, 0, READ_LOCK)) &&
2012               NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 110, 6));
2013         EXPECTED(ret, False);
2014         printf("the same process %s coalesce read locks\n", ret?"can":"cannot");
2015
2016
2017         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 120, 4, 0, WRITE_LOCK)) &&
2018               (cli_read_old(cli2, fnum2, buf, 120, 4) == 4);
2019         EXPECTED(ret, False);
2020         printf("this server %s strict write locking\n", ret?"doesn't do":"does");
2021
2022         status = cli_lock32(cli1, fnum1, 130, 4, 0, READ_LOCK);
2023         ret = NT_STATUS_IS_OK(status);
2024         if (ret) {
2025                 status = cli_writeall(cli2, fnum2, 0, (uint8_t *)buf, 130, 4,
2026                                       NULL);
2027                 ret = NT_STATUS_IS_OK(status);
2028         }
2029         EXPECTED(ret, False);
2030         printf("this server %s strict read locking\n", ret?"doesn't do":"does");
2031
2032
2033         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 140, 4, 0, READ_LOCK)) &&
2034               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 140, 4, 0, READ_LOCK)) &&
2035               NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 140, 4)) &&
2036               NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 140, 4));
2037         EXPECTED(ret, True);
2038         printf("this server %s do recursive read locking\n", ret?"does":"doesn't");
2039
2040
2041         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 150, 4, 0, WRITE_LOCK)) &&
2042               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 150, 4, 0, READ_LOCK)) &&
2043               NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 150, 4)) &&
2044               (cli_read_old(cli2, fnum2, buf, 150, 4) == 4) &&
2045               !(NT_STATUS_IS_OK(cli_writeall(cli2, fnum2, 0, (uint8_t *)buf,
2046                                              150, 4, NULL))) &&
2047               NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 150, 4));
2048         EXPECTED(ret, True);
2049         printf("this server %s do recursive lock overlays\n", ret?"does":"doesn't");
2050
2051         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 160, 4, 0, READ_LOCK)) &&
2052               NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 160, 4)) &&
2053               NT_STATUS_IS_OK(cli_writeall(cli2, fnum2, 0, (uint8_t *)buf,
2054                                            160, 4, NULL)) &&
2055               (cli_read_old(cli2, fnum2, buf, 160, 4) == 4);            
2056         EXPECTED(ret, True);
2057         printf("the same process %s remove a read lock using write locking\n", ret?"can":"cannot");
2058
2059         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 170, 4, 0, WRITE_LOCK)) &&
2060               NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 170, 4)) &&
2061               NT_STATUS_IS_OK(cli_writeall(cli2, fnum2, 0, (uint8_t *)buf,
2062                                            170, 4, NULL)) &&
2063               (cli_read_old(cli2, fnum2, buf, 170, 4) == 4);            
2064         EXPECTED(ret, True);
2065         printf("the same process %s remove a write lock using read locking\n", ret?"can":"cannot");
2066
2067         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 190, 4, 0, WRITE_LOCK)) &&
2068               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 190, 4, 0, READ_LOCK)) &&
2069               NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 190, 4)) &&
2070               !NT_STATUS_IS_OK(cli_writeall(cli2, fnum2, 0, (uint8_t *)buf,
2071                                             190, 4, NULL)) &&
2072               (cli_read_old(cli2, fnum2, buf, 190, 4) == 4);            
2073         EXPECTED(ret, True);
2074         printf("the same process %s remove the first lock first\n", ret?"does":"doesn't");
2075
2076         cli_close(cli1, fnum1);
2077         cli_close(cli2, fnum2);
2078         cli_open(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
2079         cli_open(cli1, fname, O_RDWR, DENY_NONE, &f);
2080         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 8, 0, READ_LOCK)) &&
2081               NT_STATUS_IS_OK(cli_lock32(cli1, f, 0, 1, 0, READ_LOCK)) &&
2082               NT_STATUS_IS_OK(cli_close(cli1, fnum1)) &&
2083               NT_STATUS_IS_OK(cli_open(cli1, fname, O_RDWR, DENY_NONE, &fnum1)) &&
2084               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 7, 1, 0, WRITE_LOCK));
2085         cli_close(cli1, f);
2086         cli_close(cli1, fnum1);
2087         EXPECTED(ret, True);
2088         printf("the server %s have the NT byte range lock bug\n", !ret?"does":"doesn't");
2089
2090  fail:
2091         cli_close(cli1, fnum1);
2092         cli_close(cli2, fnum2);
2093         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2094         torture_close_connection(cli1);
2095         torture_close_connection(cli2);
2096
2097         printf("finished locktest4\n");
2098         return correct;
2099 }
2100
2101 /*
2102   looks at lock upgrade/downgrade.
2103 */
2104 static bool run_locktest5(int dummy)
2105 {
2106         static struct cli_state *cli1, *cli2;
2107         const char *fname = "\\lockt5.lck";
2108         uint16_t fnum1, fnum2, fnum3;
2109         bool ret;
2110         char buf[1000];
2111         bool correct = True;
2112         NTSTATUS status;
2113
2114         if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
2115                 return False;
2116         }
2117
2118         cli_sockopt(cli1, sockops);
2119         cli_sockopt(cli2, sockops);
2120
2121         printf("starting locktest5\n");
2122
2123         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2124
2125         cli_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
2126         cli_open(cli2, fname, O_RDWR, DENY_NONE, &fnum2);
2127         cli_open(cli1, fname, O_RDWR, DENY_NONE, &fnum3);
2128
2129         memset(buf, 0, sizeof(buf));
2130
2131         status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 0, sizeof(buf),
2132                               NULL);
2133         if (!NT_STATUS_IS_OK(status)) {
2134                 printf("Failed to create file: %s\n", nt_errstr(status));
2135                 correct = False;
2136                 goto fail;
2137         }
2138
2139         /* Check for NT bug... */
2140         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 8, 0, READ_LOCK)) &&
2141               NT_STATUS_IS_OK(cli_lock32(cli1, fnum3, 0, 1, 0, READ_LOCK));
2142         cli_close(cli1, fnum1);
2143         cli_open(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
2144         status = cli_lock32(cli1, fnum1, 7, 1, 0, WRITE_LOCK);
2145         ret = NT_STATUS_IS_OK(status);
2146         EXPECTED(ret, True);
2147         printf("this server %s the NT locking bug\n", ret ? "doesn't have" : "has");
2148         cli_close(cli1, fnum1);
2149         cli_open(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
2150         cli_unlock(cli1, fnum3, 0, 1);
2151
2152         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 4, 0, WRITE_LOCK)) &&
2153               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 1, 1, 0, READ_LOCK));
2154         EXPECTED(ret, True);
2155         printf("the same process %s overlay a write with a read lock\n", ret?"can":"cannot");
2156
2157         status = cli_lock32(cli2, fnum2, 0, 4, 0, READ_LOCK);
2158         ret = NT_STATUS_IS_OK(status);
2159         EXPECTED(ret, False);
2160
2161         printf("a different processs %s get a read lock on the first process lock stack\n", ret?"can":"cannot");
2162
2163         /* Unlock the process 2 lock. */
2164         cli_unlock(cli2, fnum2, 0, 4);
2165
2166         status = cli_lock32(cli1, fnum3, 0, 4, 0, READ_LOCK);
2167         ret = NT_STATUS_IS_OK(status);
2168         EXPECTED(ret, False);
2169
2170         printf("the same processs on a different fnum %s get a read lock\n", ret?"can":"cannot");
2171
2172         /* Unlock the process 1 fnum3 lock. */
2173         cli_unlock(cli1, fnum3, 0, 4);
2174
2175         /* Stack 2 more locks here. */
2176         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 4, 0, READ_LOCK)) &&
2177               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 4, 0, READ_LOCK));
2178
2179         EXPECTED(ret, True);
2180         printf("the same process %s stack read locks\n", ret?"can":"cannot");
2181
2182         /* Unlock the first process lock, then check this was the WRITE lock that was
2183                 removed. */
2184
2185         ret = NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 0, 4)) &&
2186               NT_STATUS_IS_OK(cli_lock32(cli2, fnum2, 0, 4, 0, READ_LOCK));
2187
2188         EXPECTED(ret, True);
2189         printf("the first unlock removes the %s lock\n", ret?"WRITE":"READ");
2190
2191         /* Unlock the process 2 lock. */
2192         cli_unlock(cli2, fnum2, 0, 4);
2193
2194         /* We should have 3 stacked locks here. Ensure we need to do 3 unlocks. */
2195
2196         ret = NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 1, 1)) &&
2197                   NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 0, 4)) &&
2198                   NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 0, 4));
2199
2200         EXPECTED(ret, True);
2201         printf("the same process %s unlock the stack of 4 locks\n", ret?"can":"cannot"); 
2202
2203         /* Ensure the next unlock fails. */
2204         ret = NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 0, 4));
2205         EXPECTED(ret, False);
2206         printf("the same process %s count the lock stack\n", !ret?"can":"cannot"); 
2207
2208         /* Ensure connection 2 can get a write lock. */
2209         status = cli_lock32(cli2, fnum2, 0, 4, 0, WRITE_LOCK);
2210         ret = NT_STATUS_IS_OK(status);
2211         EXPECTED(ret, True);
2212
2213         printf("a different processs %s get a write lock on the unlocked stack\n", ret?"can":"cannot");
2214
2215
2216  fail:
2217         cli_close(cli1, fnum1);
2218         cli_close(cli2, fnum2);
2219         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2220         if (!torture_close_connection(cli1)) {
2221                 correct = False;
2222         }
2223         if (!torture_close_connection(cli2)) {
2224                 correct = False;
2225         }
2226
2227         printf("finished locktest5\n");
2228
2229         return correct;
2230 }
2231
2232 /*
2233   tries the unusual lockingX locktype bits
2234 */
2235 static bool run_locktest6(int dummy)
2236 {
2237         static struct cli_state *cli;
2238         const char *fname[1] = { "\\lock6.txt" };
2239         int i;
2240         uint16_t fnum;
2241         NTSTATUS status;
2242
2243         if (!torture_open_connection(&cli, 0)) {
2244                 return False;
2245         }
2246
2247         cli_sockopt(cli, sockops);
2248
2249         printf("starting locktest6\n");
2250
2251         for (i=0;i<1;i++) {
2252                 printf("Testing %s\n", fname[i]);
2253
2254                 cli_unlink(cli, fname[i], FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2255
2256                 cli_open(cli, fname[i], O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
2257                 status = cli_locktype(cli, fnum, 0, 8, 0, LOCKING_ANDX_CHANGE_LOCKTYPE);
2258                 cli_close(cli, fnum);
2259                 printf("CHANGE_LOCKTYPE gave %s\n", nt_errstr(status));
2260
2261                 cli_open(cli, fname[i], O_RDWR, DENY_NONE, &fnum);
2262                 status = cli_locktype(cli, fnum, 0, 8, 0, LOCKING_ANDX_CANCEL_LOCK);
2263                 cli_close(cli, fnum);
2264                 printf("CANCEL_LOCK gave %s\n", nt_errstr(status));
2265
2266                 cli_unlink(cli, fname[i], FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2267         }
2268
2269         torture_close_connection(cli);
2270
2271         printf("finished locktest6\n");
2272         return True;
2273 }
2274
2275 static bool run_locktest7(int dummy)
2276 {
2277         struct cli_state *cli1;
2278         const char *fname = "\\lockt7.lck";
2279         uint16_t fnum1;
2280         char buf[200];
2281         bool correct = False;
2282         NTSTATUS status;
2283
2284         if (!torture_open_connection(&cli1, 0)) {
2285                 return False;
2286         }
2287
2288         cli_sockopt(cli1, sockops);
2289
2290         printf("starting locktest7\n");
2291
2292         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2293
2294         cli_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
2295
2296         memset(buf, 0, sizeof(buf));
2297
2298         status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 0, sizeof(buf),
2299                               NULL);
2300         if (!NT_STATUS_IS_OK(status)) {
2301                 printf("Failed to create file: %s\n", nt_errstr(status));
2302                 goto fail;
2303         }
2304
2305         cli_setpid(cli1, 1);
2306
2307         status = cli_lock32(cli1, fnum1, 130, 4, 0, READ_LOCK);
2308         if (!NT_STATUS_IS_OK(status)) {
2309                 printf("Unable to apply read lock on range 130:4, error was %s\n", nt_errstr(status));
2310                 goto fail;
2311         } else {
2312                 printf("pid1 successfully locked range 130:4 for READ\n");
2313         }
2314
2315         if (cli_read_old(cli1, fnum1, buf, 130, 4) != 4) {
2316                 printf("pid1 unable to read the range 130:4, error was %s\n", cli_errstr(cli1));
2317                 goto fail;
2318         } else {
2319                 printf("pid1 successfully read the range 130:4\n");
2320         }
2321
2322         status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
2323         if (!NT_STATUS_IS_OK(status)) {
2324                 printf("pid1 unable to write to the range 130:4, error was "
2325                        "%s\n", nt_errstr(status));
2326                 if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
2327                         printf("Incorrect error (should be NT_STATUS_FILE_LOCK_CONFLICT)\n");
2328                         goto fail;
2329                 }
2330         } else {
2331                 printf("pid1 successfully wrote to the range 130:4 (should be denied)\n");
2332                 goto fail;
2333         }
2334
2335         cli_setpid(cli1, 2);
2336
2337         if (cli_read_old(cli1, fnum1, buf, 130, 4) != 4) {
2338                 printf("pid2 unable to read the range 130:4, error was %s\n", cli_errstr(cli1));
2339         } else {
2340                 printf("pid2 successfully read the range 130:4\n");
2341         }
2342
2343         status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
2344         if (!NT_STATUS_IS_OK(status)) {
2345                 printf("pid2 unable to write to the range 130:4, error was "
2346                        "%s\n", nt_errstr(status));
2347                 if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
2348                         printf("Incorrect error (should be NT_STATUS_FILE_LOCK_CONFLICT)\n");
2349                         goto fail;
2350                 }
2351         } else {
2352                 printf("pid2 successfully wrote to the range 130:4 (should be denied)\n");
2353                 goto fail;
2354         }
2355
2356         cli_setpid(cli1, 1);
2357         cli_unlock(cli1, fnum1, 130, 4);
2358
2359         status = cli_lock32(cli1, fnum1, 130, 4, 0, WRITE_LOCK);
2360         if (!NT_STATUS_IS_OK(status)) {
2361                 printf("Unable to apply write lock on range 130:4, error was %s\n", nt_errstr(status));
2362                 goto fail;
2363         } else {
2364                 printf("pid1 successfully locked range 130:4 for WRITE\n");
2365         }
2366
2367         if (cli_read_old(cli1, fnum1, buf, 130, 4) != 4) {
2368                 printf("pid1 unable to read the range 130:4, error was %s\n", cli_errstr(cli1));
2369                 goto fail;
2370         } else {
2371                 printf("pid1 successfully read the range 130:4\n");
2372         }
2373
2374         status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
2375         if (!NT_STATUS_IS_OK(status)) {
2376                 printf("pid1 unable to write to the range 130:4, error was "
2377                        "%s\n", nt_errstr(status));
2378                 goto fail;
2379         } else {
2380                 printf("pid1 successfully wrote to the range 130:4\n");
2381         }
2382
2383         cli_setpid(cli1, 2);
2384
2385         if (cli_read_old(cli1, fnum1, buf, 130, 4) != 4) {
2386                 printf("pid2 unable to read the range 130:4, error was %s\n", cli_errstr(cli1));
2387                 if (NT_STATUS_V(cli_nt_error(cli1)) != NT_STATUS_V(NT_STATUS_FILE_LOCK_CONFLICT)) {
2388                         printf("Incorrect error (should be NT_STATUS_FILE_LOCK_CONFLICT)\n");
2389                         goto fail;
2390                 }
2391         } else {
2392                 printf("pid2 successfully read the range 130:4 (should be denied)\n");
2393                 goto fail;
2394         }
2395
2396         status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
2397         if (!NT_STATUS_IS_OK(status)) {
2398                 printf("pid2 unable to write to the range 130:4, error was "
2399                        "%s\n", nt_errstr(status));
2400                 if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
2401                         printf("Incorrect error (should be NT_STATUS_FILE_LOCK_CONFLICT)\n");
2402                         goto fail;
2403                 }
2404         } else {
2405                 printf("pid2 successfully wrote to the range 130:4 (should be denied)\n");
2406                 goto fail;
2407         }
2408
2409         cli_unlock(cli1, fnum1, 130, 0);
2410         correct = True;
2411
2412 fail:
2413         cli_close(cli1, fnum1);
2414         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2415         torture_close_connection(cli1);
2416
2417         printf("finished locktest7\n");
2418         return correct;
2419 }
2420
2421 /*
2422  * This demonstrates a problem with our use of GPFS share modes: A file
2423  * descriptor sitting in the pending close queue holding a GPFS share mode
2424  * blocks opening a file another time. Happens with Word 2007 temp files.
2425  * With "posix locking = yes" and "gpfs:sharemodes = yes" enabled, the third
2426  * open is denied with NT_STATUS_SHARING_VIOLATION.
2427  */
2428
2429 static bool run_locktest8(int dummy)
2430 {
2431         struct cli_state *cli1;
2432         const char *fname = "\\lockt8.lck";
2433         uint16_t fnum1, fnum2;
2434         char buf[200];
2435         bool correct = False;
2436         NTSTATUS status;
2437
2438         if (!torture_open_connection(&cli1, 0)) {
2439                 return False;
2440         }
2441
2442         cli_sockopt(cli1, sockops);
2443
2444         printf("starting locktest8\n");
2445
2446         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2447
2448         status = cli_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_WRITE,
2449                           &fnum1);
2450         if (!NT_STATUS_IS_OK(status)) {
2451                 d_fprintf(stderr, "cli_open returned %s\n", nt_errstr(status));
2452                 return false;
2453         }
2454
2455         memset(buf, 0, sizeof(buf));
2456
2457         status = cli_open(cli1, fname, O_RDONLY, DENY_NONE, &fnum2);
2458         if (!NT_STATUS_IS_OK(status)) {
2459                 d_fprintf(stderr, "cli_open second time returned %s\n",
2460                           nt_errstr(status));
2461                 goto fail;
2462         }
2463
2464         status = cli_lock32(cli1, fnum2, 1, 1, 0, READ_LOCK);
2465         if (!NT_STATUS_IS_OK(status)) {
2466                 printf("Unable to apply read lock on range 1:1, error was "
2467                        "%s\n", nt_errstr(status));
2468                 goto fail;
2469         }
2470
2471         status = cli_close(cli1, fnum1);
2472         if (!NT_STATUS_IS_OK(status)) {
2473                 d_fprintf(stderr, "cli_close(fnum1) %s\n", nt_errstr(status));
2474                 goto fail;
2475         }
2476
2477         status = cli_open(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
2478         if (!NT_STATUS_IS_OK(status)) {
2479                 d_fprintf(stderr, "cli_open third time returned %s\n",
2480                           nt_errstr(status));
2481                 goto fail;
2482         }
2483
2484         correct = true;
2485
2486 fail:
2487         cli_close(cli1, fnum1);
2488         cli_close(cli1, fnum2);
2489         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2490         torture_close_connection(cli1);
2491
2492         printf("finished locktest8\n");
2493         return correct;
2494 }
2495
2496 /*
2497  * This test is designed to be run in conjunction with
2498  * external NFS or POSIX locks taken in the filesystem.
2499  * It checks that the smbd server will block until the
2500  * lock is released and then acquire it. JRA.
2501  */
2502
2503 static bool got_alarm;
2504 static int alarm_fd;
2505
2506 static void alarm_handler(int dummy)
2507 {
2508         got_alarm = True;
2509 }
2510
2511 static void alarm_handler_parent(int dummy)
2512 {
2513         close(alarm_fd);
2514 }
2515
2516 static void do_local_lock(int read_fd, int write_fd)
2517 {
2518         int fd;
2519         char c = '\0';
2520         struct flock lock;
2521         const char *local_pathname = NULL;
2522         int ret;
2523
2524         local_pathname = talloc_asprintf(talloc_tos(),
2525                         "%s/lockt9.lck", local_path);
2526         if (!local_pathname) {
2527                 printf("child: alloc fail\n");
2528                 exit(1);
2529         }
2530
2531         unlink(local_pathname);
2532         fd = open(local_pathname, O_RDWR|O_CREAT, 0666);
2533         if (fd == -1) {
2534                 printf("child: open of %s failed %s.\n",
2535                         local_pathname, strerror(errno));
2536                 exit(1);
2537         }
2538
2539         /* Now take a fcntl lock. */
2540         lock.l_type = F_WRLCK;
2541         lock.l_whence = SEEK_SET;
2542         lock.l_start = 0;
2543         lock.l_len = 4;
2544         lock.l_pid = getpid();
2545
2546         ret = fcntl(fd,F_SETLK,&lock);
2547         if (ret == -1) {
2548                 printf("child: failed to get lock 0:4 on file %s. Error %s\n",
2549                         local_pathname, strerror(errno));
2550                 exit(1);
2551         } else {
2552                 printf("child: got lock 0:4 on file %s.\n",
2553                         local_pathname );
2554                 fflush(stdout);
2555         }
2556
2557         CatchSignal(SIGALRM, alarm_handler);
2558         alarm(5);
2559         /* Signal the parent. */
2560         if (write(write_fd, &c, 1) != 1) {
2561                 printf("child: start signal fail %s.\n",
2562                         strerror(errno));
2563                 exit(1);
2564         }
2565         alarm(0);
2566
2567         alarm(10);
2568         /* Wait for the parent to be ready. */
2569         if (read(read_fd, &c, 1) != 1) {
2570                 printf("child: reply signal fail %s.\n",
2571                         strerror(errno));
2572                 exit(1);
2573         }
2574         alarm(0);
2575
2576         sleep(5);
2577         close(fd);
2578         printf("child: released lock 0:4 on file %s.\n",
2579                 local_pathname );
2580         fflush(stdout);
2581         exit(0);
2582 }
2583
2584 static bool run_locktest9(int dummy)
2585 {
2586         struct cli_state *cli1;
2587         const char *fname = "\\lockt9.lck";
2588         uint16_t fnum;
2589         bool correct = False;
2590         int pipe_in[2], pipe_out[2];
2591         pid_t child_pid;
2592         char c = '\0';
2593         int ret;
2594         struct timeval start;
2595         double seconds;
2596         NTSTATUS status;
2597
2598         printf("starting locktest9\n");
2599
2600         if (local_path == NULL) {
2601                 d_fprintf(stderr, "locktest9 must be given a local path via -l <localpath>\n");
2602                 return false;
2603         }
2604
2605         if (pipe(pipe_in) == -1 || pipe(pipe_out) == -1) {
2606                 return false;
2607         }
2608
2609         child_pid = fork();
2610         if (child_pid == -1) {
2611                 return false;
2612         }
2613
2614         if (child_pid == 0) {
2615                 /* Child. */
2616                 do_local_lock(pipe_out[0], pipe_in[1]);
2617                 exit(0);
2618         }
2619
2620         close(pipe_out[0]);
2621         close(pipe_in[1]);
2622         pipe_out[0] = -1;
2623         pipe_in[1] = -1;
2624
2625         /* Parent. */
2626         ret = read(pipe_in[0], &c, 1);
2627         if (ret != 1) {
2628                 d_fprintf(stderr, "failed to read start signal from child. %s\n",
2629                         strerror(errno));
2630                 return false;
2631         }
2632
2633         if (!torture_open_connection(&cli1, 0)) {
2634                 return false;
2635         }
2636
2637         cli_sockopt(cli1, sockops);
2638
2639         status = cli_open(cli1, fname, O_RDWR, DENY_NONE,
2640                           &fnum);
2641         if (!NT_STATUS_IS_OK(status)) {
2642                 d_fprintf(stderr, "cli_open returned %s\n", nt_errstr(status));
2643                 return false;
2644         }
2645
2646         /* Ensure the child has the lock. */
2647         status = cli_lock32(cli1, fnum, 0, 4, 0, WRITE_LOCK);
2648         if (NT_STATUS_IS_OK(status)) {
2649                 d_fprintf(stderr, "Got the lock on range 0:4 - this should not happen !\n");
2650                 goto fail;
2651         } else {
2652                 d_printf("Child has the lock.\n");
2653         }
2654
2655         /* Tell the child to wait 5 seconds then exit. */
2656         ret = write(pipe_out[1], &c, 1);
2657         if (ret != 1) {
2658                 d_fprintf(stderr, "failed to send exit signal to child. %s\n",
2659                         strerror(errno));
2660                 goto fail;
2661         }
2662
2663         /* Wait 20 seconds for the lock. */
2664         alarm_fd = cli1->fd;
2665         CatchSignal(SIGALRM, alarm_handler_parent);
2666         alarm(20);
2667
2668         start = timeval_current();
2669
2670         status = cli_lock32(cli1, fnum, 0, 4, -1, WRITE_LOCK);
2671         if (!NT_STATUS_IS_OK(status)) {
2672                 d_fprintf(stderr, "Unable to apply write lock on range 0:4, error was "
2673                        "%s\n", nt_errstr(status));
2674                 goto fail_nofd;
2675         }
2676         alarm(0);
2677
2678         seconds = timeval_elapsed(&start);
2679
2680         printf("Parent got the lock after %.2f seconds.\n",
2681                 seconds);
2682
2683         status = cli_close(cli1, fnum);
2684         if (!NT_STATUS_IS_OK(status)) {
2685                 d_fprintf(stderr, "cli_close(fnum1) %s\n", nt_errstr(status));
2686                 goto fail;
2687         }
2688
2689         correct = true;
2690
2691 fail:
2692         cli_close(cli1, fnum);
2693         torture_close_connection(cli1);
2694
2695 fail_nofd:
2696
2697         printf("finished locktest9\n");
2698         return correct;
2699 }
2700
2701 /*
2702 test whether fnums and tids open on one VC are available on another (a major
2703 security hole)
2704 */
2705 static bool run_fdpasstest(int dummy)
2706 {
2707         struct cli_state *cli1, *cli2;
2708         const char *fname = "\\fdpass.tst";
2709         uint16_t fnum1;
2710         char buf[1024];
2711         NTSTATUS status;
2712
2713         if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
2714                 return False;
2715         }
2716         cli_sockopt(cli1, sockops);
2717         cli_sockopt(cli2, sockops);
2718
2719         printf("starting fdpasstest\n");
2720
2721         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2722
2723         status = cli_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
2724                           &fnum1);
2725         if (!NT_STATUS_IS_OK(status)) {
2726                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
2727                 return False;
2728         }
2729
2730         status = cli_writeall(cli1, fnum1, 0, (const uint8_t *)"hello world\n", 0,
2731                               13, NULL);
2732         if (!NT_STATUS_IS_OK(status)) {
2733                 printf("write failed (%s)\n", nt_errstr(status));
2734                 return False;
2735         }
2736
2737         cli2->vuid = cli1->vuid;
2738         cli_state_set_tid(cli2, cli_state_get_tid(cli1));
2739         cli_setpid(cli2, cli_getpid(cli1));
2740
2741         if (cli_read_old(cli2, fnum1, buf, 0, 13) == 13) {
2742                 printf("read succeeded! nasty security hole [%s]\n",
2743                        buf);
2744                 return False;
2745         }
2746
2747         cli_close(cli1, fnum1);
2748         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2749
2750         torture_close_connection(cli1);
2751         torture_close_connection(cli2);
2752
2753         printf("finished fdpasstest\n");
2754         return True;
2755 }
2756
2757 static bool run_fdsesstest(int dummy)
2758 {
2759         struct cli_state *cli;
2760         uint16 new_vuid;
2761         uint16 saved_vuid;
2762         uint16 new_cnum;
2763         uint16 saved_cnum;
2764         const char *fname = "\\fdsess.tst";
2765         const char *fname1 = "\\fdsess1.tst";
2766         uint16_t fnum1;
2767         uint16_t fnum2;
2768         char buf[1024];
2769         bool ret = True;
2770         NTSTATUS status;
2771
2772         if (!torture_open_connection(&cli, 0))
2773                 return False;
2774         cli_sockopt(cli, sockops);
2775
2776         if (!torture_cli_session_setup2(cli, &new_vuid))
2777                 return False;
2778
2779         saved_cnum = cli_state_get_tid(cli);
2780         if (!NT_STATUS_IS_OK(cli_tcon_andx(cli, share, "?????", "", 1)))
2781                 return False;
2782         new_cnum = cli_state_get_tid(cli);
2783         cli_state_set_tid(cli, saved_cnum);
2784
2785         printf("starting fdsesstest\n");
2786
2787         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2788         cli_unlink(cli, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2789
2790         status = cli_open(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
2791         if (!NT_STATUS_IS_OK(status)) {
2792                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
2793                 return False;
2794         }
2795
2796         status = cli_writeall(cli, fnum1, 0, (const uint8_t *)"hello world\n", 0, 13,
2797                               NULL);
2798         if (!NT_STATUS_IS_OK(status)) {
2799                 printf("write failed (%s)\n", nt_errstr(status));
2800                 return False;
2801         }
2802
2803         saved_vuid = cli->vuid;
2804         cli->vuid = new_vuid;
2805
2806         if (cli_read_old(cli, fnum1, buf, 0, 13) == 13) {
2807                 printf("read succeeded with different vuid! nasty security hole [%s]\n",
2808                        buf);
2809                 ret = False;
2810         }
2811         /* Try to open a file with different vuid, samba cnum. */
2812         if (NT_STATUS_IS_OK(cli_open(cli, fname1, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum2))) {
2813                 printf("create with different vuid, same cnum succeeded.\n");
2814                 cli_close(cli, fnum2);
2815                 cli_unlink(cli, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2816         } else {
2817                 printf("create with different vuid, same cnum failed.\n");
2818                 printf("This will cause problems with service clients.\n");
2819                 ret = False;
2820         }
2821
2822         cli->vuid = saved_vuid;
2823
2824         /* Try with same vuid, different cnum. */
2825         cli_state_set_tid(cli, new_cnum);
2826
2827         if (cli_read_old(cli, fnum1, buf, 0, 13) == 13) {
2828                 printf("read succeeded with different cnum![%s]\n",
2829                        buf);
2830                 ret = False;
2831         }
2832
2833         cli_state_set_tid(cli, saved_cnum);
2834         cli_close(cli, fnum1);
2835         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2836
2837         torture_close_connection(cli);
2838
2839         printf("finished fdsesstest\n");
2840         return ret;
2841 }
2842
2843 /*
2844   This test checks that 
2845
2846   1) the server does not allow an unlink on a file that is open
2847 */
2848 static bool run_unlinktest(int dummy)
2849 {
2850         struct cli_state *cli;
2851         const char *fname = "\\unlink.tst";
2852         uint16_t fnum;
2853         bool correct = True;
2854         NTSTATUS status;
2855
2856         if (!torture_open_connection(&cli, 0)) {
2857                 return False;
2858         }
2859
2860         cli_sockopt(cli, sockops);
2861
2862         printf("starting unlink test\n");
2863
2864         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2865
2866         cli_setpid(cli, 1);
2867
2868         status = cli_open(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
2869         if (!NT_STATUS_IS_OK(status)) {
2870                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
2871                 return False;
2872         }
2873
2874         status = cli_unlink(cli, fname,
2875                             FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2876         if (NT_STATUS_IS_OK(status)) {
2877                 printf("error: server allowed unlink on an open file\n");
2878                 correct = False;
2879         } else {
2880                 correct = check_error(__LINE__, cli, ERRDOS, ERRbadshare, 
2881                                       NT_STATUS_SHARING_VIOLATION);
2882         }
2883
2884         cli_close(cli, fnum);
2885         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2886
2887         if (!torture_close_connection(cli)) {
2888                 correct = False;
2889         }
2890
2891         printf("unlink test finished\n");
2892
2893         return correct;
2894 }
2895
2896
2897 /*
2898 test how many open files this server supports on the one socket
2899 */
2900 static bool run_maxfidtest(int dummy)
2901 {
2902         struct cli_state *cli;
2903         fstring fname;
2904         uint16_t fnums[0x11000];
2905         int i;
2906         int retries=4;
2907         bool correct = True;
2908         NTSTATUS status;
2909
2910         cli = current_cli;
2911
2912         if (retries <= 0) {
2913                 printf("failed to connect\n");
2914                 return False;
2915         }
2916
2917         cli_sockopt(cli, sockops);
2918
2919         for (i=0; i<0x11000; i++) {
2920                 slprintf(fname,sizeof(fname)-1,"\\maxfid.%d.%d", i,(int)getpid());
2921                 status = cli_open(cli, fname, O_RDWR|O_CREAT|O_TRUNC, DENY_NONE,
2922                                   &fnums[i]);
2923                 if (!NT_STATUS_IS_OK(status)) {
2924                         printf("open of %s failed (%s)\n", 
2925                                fname, nt_errstr(status));
2926                         printf("maximum fnum is %d\n", i);
2927                         break;
2928                 }
2929                 printf("%6d\r", i);
2930         }
2931         printf("%6d\n", i);
2932         i--;
2933
2934         printf("cleaning up\n");
2935         for (;i>=0;i--) {
2936                 slprintf(fname,sizeof(fname)-1,"\\maxfid.%d.%d", i,(int)getpid());
2937                 cli_close(cli, fnums[i]);
2938
2939                 status = cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2940                 if (!NT_STATUS_IS_OK(status)) {
2941                         printf("unlink of %s failed (%s)\n", 
2942                                fname, nt_errstr(status));
2943                         correct = False;
2944                 }
2945                 printf("%6d\r", i);
2946         }
2947         printf("%6d\n", 0);
2948
2949         printf("maxfid test finished\n");
2950         if (!torture_close_connection(cli)) {
2951                 correct = False;
2952         }
2953         return correct;
2954 }
2955
2956 /* generate a random buffer */
2957 static void rand_buf(char *buf, int len)
2958 {
2959         while (len--) {
2960                 *buf = (char)sys_random();
2961                 buf++;
2962         }
2963 }
2964
2965 /* send smb negprot commands, not reading the response */
2966 static bool run_negprot_nowait(int dummy)
2967 {
2968         struct tevent_context *ev;
2969         int i;
2970         struct cli_state *cli;
2971         bool correct = True;
2972
2973         printf("starting negprot nowait test\n");
2974
2975         ev = tevent_context_init(talloc_tos());
2976         if (ev == NULL) {
2977                 return false;
2978         }
2979
2980         if (!(cli = open_nbt_connection())) {
2981                 TALLOC_FREE(ev);
2982                 return False;
2983         }
2984
2985         for (i=0;i<50000;i++) {
2986                 struct tevent_req *req;
2987
2988                 req = cli_negprot_send(ev, ev, cli);
2989                 if (req == NULL) {
2990                         TALLOC_FREE(ev);
2991                         return false;
2992                 }
2993                 if (!tevent_req_poll(req, ev)) {
2994                         d_fprintf(stderr, "tevent_req_poll failed: %s\n",
2995                                   strerror(errno));
2996                         TALLOC_FREE(ev);
2997                         return false;
2998                 }
2999                 TALLOC_FREE(req);
3000         }
3001
3002         if (torture_close_connection(cli)) {
3003                 correct = False;
3004         }
3005
3006         printf("finished negprot nowait test\n");
3007
3008         return correct;
3009 }
3010
3011 /* send smb negprot commands, not reading the response */
3012 static bool run_bad_nbt_session(int dummy)
3013 {
3014         struct nmb_name called, calling;
3015         struct sockaddr_storage ss;
3016         NTSTATUS status;
3017         int fd;
3018         bool ret;
3019
3020         printf("starting bad nbt session test\n");
3021
3022         make_nmb_name(&calling, myname, 0x0);
3023         make_nmb_name(&called , host, 0x20);
3024
3025         if (!resolve_name(host, &ss, 0x20, true)) {
3026                 d_fprintf(stderr, "Could not resolve name %s\n", host);
3027                 return false;
3028         }
3029
3030         status = open_socket_out(&ss, 139, 10000, &fd);
3031         if (!NT_STATUS_IS_OK(status)) {
3032                 d_fprintf(stderr, "open_socket_out failed: %s\n",
3033                           nt_errstr(status));
3034                 return false;
3035         }
3036
3037         ret = cli_bad_session_request(fd, &calling, &called);
3038         close(fd);
3039         if (!ret) {
3040                 d_fprintf(stderr, "open_socket_out failed: %s\n",
3041                           nt_errstr(status));
3042                 return false;
3043         }
3044
3045         printf("finished bad nbt session test\n");
3046         return true;
3047 }
3048
3049 /* send random IPC commands */
3050 static bool run_randomipc(int dummy)
3051 {
3052         char *rparam = NULL;
3053         char *rdata = NULL;
3054         unsigned int rdrcnt,rprcnt;
3055         char param[1024];
3056         int api, param_len, i;
3057         struct cli_state *cli;
3058         bool correct = True;
3059         int count = 50000;
3060
3061         printf("starting random ipc test\n");
3062
3063         if (!torture_open_connection(&cli, 0)) {
3064                 return False;
3065         }
3066
3067         for (i=0;i<count;i++) {
3068                 api = sys_random() % 500;
3069                 param_len = (sys_random() % 64);
3070
3071                 rand_buf(param, param_len);
3072
3073                 SSVAL(param,0,api); 
3074
3075                 cli_api(cli, 
3076                         param, param_len, 8,  
3077                         NULL, 0, BUFFER_SIZE, 
3078                         &rparam, &rprcnt,     
3079                         &rdata, &rdrcnt);
3080                 if (i % 100 == 0) {
3081                         printf("%d/%d\r", i,count);
3082                 }
3083         }
3084         printf("%d/%d\n", i, count);
3085
3086         if (!torture_close_connection(cli)) {
3087                 correct = False;
3088         }
3089
3090         printf("finished random ipc test\n");
3091
3092         return correct;
3093 }
3094
3095
3096
3097 static void browse_callback(const char *sname, uint32 stype, 
3098                             const char *comment, void *state)
3099 {
3100         printf("\t%20.20s %08x %s\n", sname, stype, comment);
3101 }
3102
3103
3104
3105 /*
3106   This test checks the browse list code
3107
3108 */
3109 static bool run_browsetest(int dummy)
3110 {
3111         static struct cli_state *cli;
3112         bool correct = True;
3113
3114         printf("starting browse test\n");
3115
3116         if (!torture_open_connection(&cli, 0)) {
3117                 return False;
3118         }
3119
3120         printf("domain list:\n");
3121         cli_NetServerEnum(cli, cli->server_domain, 
3122                           SV_TYPE_DOMAIN_ENUM,
3123                           browse_callback, NULL);
3124
3125         printf("machine list:\n");
3126         cli_NetServerEnum(cli, cli->server_domain, 
3127                           SV_TYPE_ALL,
3128                           browse_callback, NULL);
3129
3130         if (!torture_close_connection(cli)) {
3131                 correct = False;
3132         }
3133
3134         printf("browse test finished\n");
3135
3136         return correct;
3137
3138 }
3139
3140
3141 /*
3142   This checks how the getatr calls works
3143 */
3144 static bool run_attrtest(int dummy)
3145 {
3146         struct cli_state *cli;
3147         uint16_t fnum;
3148         time_t t, t2;
3149         const char *fname = "\\attrib123456789.tst";
3150         bool correct = True;
3151         NTSTATUS status;
3152
3153         printf("starting attrib test\n");
3154
3155         if (!torture_open_connection(&cli, 0)) {
3156                 return False;
3157         }
3158
3159         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3160         cli_open(cli, fname, 
3161                         O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum);
3162         cli_close(cli, fnum);
3163
3164         status = cli_getatr(cli, fname, NULL, NULL, &t);
3165         if (!NT_STATUS_IS_OK(status)) {
3166                 printf("getatr failed (%s)\n", nt_errstr(status));
3167                 correct = False;
3168         }
3169
3170         if (abs(t - time(NULL)) > 60*60*24*10) {
3171                 printf("ERROR: SMBgetatr bug. time is %s",
3172                        ctime(&t));
3173                 t = time(NULL);
3174                 correct = True;
3175         }
3176
3177         t2 = t-60*60*24; /* 1 day ago */
3178
3179         status = cli_setatr(cli, fname, 0, t2);
3180         if (!NT_STATUS_IS_OK(status)) {
3181                 printf("setatr failed (%s)\n", nt_errstr(status));
3182                 correct = True;
3183         }
3184
3185         status = cli_getatr(cli, fname, NULL, NULL, &t);
3186         if (!NT_STATUS_IS_OK(status)) {
3187                 printf("getatr failed (%s)\n", nt_errstr(status));
3188                 correct = True;
3189         }
3190
3191         if (t != t2) {
3192                 printf("ERROR: getatr/setatr bug. times are\n%s",
3193                        ctime(&t));
3194                 printf("%s", ctime(&t2));
3195                 correct = True;
3196         }
3197
3198         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3199
3200         if (!torture_close_connection(cli)) {
3201                 correct = False;
3202         }
3203
3204         printf("attrib test finished\n");
3205
3206         return correct;
3207 }
3208
3209
3210 /*
3211   This checks a couple of trans2 calls
3212 */
3213 static bool run_trans2test(int dummy)
3214 {
3215         struct cli_state *cli;
3216         uint16_t fnum;
3217         SMB_OFF_T size;
3218         time_t c_time, a_time, m_time;
3219         struct timespec c_time_ts, a_time_ts, m_time_ts, w_time_ts, m_time2_ts;
3220         const char *fname = "\\trans2.tst";
3221         const char *dname = "\\trans2";
3222         const char *fname2 = "\\trans2\\trans2.tst";
3223         char *pname;
3224         bool correct = True;
3225         NTSTATUS status;
3226         uint32_t fs_attr;
3227
3228         printf("starting trans2 test\n");
3229
3230         if (!torture_open_connection(&cli, 0)) {
3231                 return False;
3232         }
3233
3234         status = cli_get_fs_attr_info(cli, &fs_attr);
3235         if (!NT_STATUS_IS_OK(status)) {
3236                 printf("ERROR: cli_get_fs_attr_info returned %s\n",
3237                        nt_errstr(status));
3238                 correct = false;
3239         }
3240
3241         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3242         cli_open(cli, fname, O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum);
3243         status = cli_qfileinfo_basic(cli, fnum, NULL, &size, &c_time_ts,
3244                                      &a_time_ts, &w_time_ts, &m_time_ts, NULL);
3245         if (!NT_STATUS_IS_OK(status)) {
3246                 printf("ERROR: qfileinfo failed (%s)\n", nt_errstr(status));
3247                 correct = False;
3248         }
3249
3250         status = cli_qfilename(cli, fnum, talloc_tos(), &pname);
3251         if (!NT_STATUS_IS_OK(status)) {
3252                 printf("ERROR: qfilename failed (%s)\n", nt_errstr(status));
3253                 correct = False;
3254         }
3255
3256         if (strcmp(pname, fname)) {
3257                 printf("qfilename gave different name? [%s] [%s]\n",
3258                        fname, pname);
3259                 correct = False;
3260         }
3261
3262         cli_close(cli, fnum);
3263
3264         sleep(2);
3265
3266         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3267         status = cli_open(cli, fname, O_RDWR | O_CREAT | O_TRUNC, DENY_NONE,
3268                           &fnum);
3269         if (!NT_STATUS_IS_OK(status)) {
3270                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
3271                 return False;
3272         }
3273         cli_close(cli, fnum);
3274
3275         status = cli_qpathinfo1(cli, fname, &c_time, &a_time, &m_time, &size,
3276                                 NULL);
3277         if (!NT_STATUS_IS_OK(status)) {
3278                 printf("ERROR: qpathinfo failed (%s)\n", nt_errstr(status));
3279                 correct = False;
3280         } else {
3281                 if (c_time != m_time) {
3282                         printf("create time=%s", ctime(&c_time));
3283                         printf("modify time=%s", ctime(&m_time));
3284                         printf("This system appears to have sticky create times\n");
3285                 }
3286                 if (a_time % (60*60) == 0) {
3287                         printf("access time=%s", ctime(&a_time));
3288                         printf("This system appears to set a midnight access time\n");
3289                         correct = False;
3290                 }
3291
3292                 if (abs(m_time - time(NULL)) > 60*60*24*7) {
3293                         printf("ERROR: totally incorrect times - maybe word reversed? mtime=%s", ctime(&m_time));
3294                         correct = False;
3295                 }
3296         }
3297
3298
3299         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3300         cli_open(cli, fname, 
3301                         O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum);
3302         cli_close(cli, fnum);
3303         status = cli_qpathinfo2(cli, fname, &c_time_ts, &a_time_ts, &w_time_ts,
3304                                 &m_time_ts, &size, NULL, NULL);
3305         if (!NT_STATUS_IS_OK(status)) {
3306                 printf("ERROR: qpathinfo2 failed (%s)\n", nt_errstr(status));
3307                 correct = False;
3308         } else {
3309                 if (w_time_ts.tv_sec < 60*60*24*2) {
3310                         printf("write time=%s", ctime(&w_time_ts.tv_sec));
3311                         printf("This system appears to set a initial 0 write time\n");
3312                         correct = False;
3313                 }
3314         }
3315
3316         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3317
3318
3319         /* check if the server updates the directory modification time
3320            when creating a new file */
3321         status = cli_mkdir(cli, dname);
3322         if (!NT_STATUS_IS_OK(status)) {
3323                 printf("ERROR: mkdir failed (%s)\n", nt_errstr(status));
3324                 correct = False;
3325         }
3326         sleep(3);
3327         status = cli_qpathinfo2(cli, "\\trans2\\", &c_time_ts, &a_time_ts,
3328                                 &w_time_ts, &m_time_ts, &size, NULL, NULL);
3329         if (!NT_STATUS_IS_OK(status)) {
3330                 printf("ERROR: qpathinfo2 failed (%s)\n", nt_errstr(status));
3331                 correct = False;
3332         }
3333
3334         cli_open(cli, fname2, 
3335                         O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum);
3336         cli_writeall(cli, fnum,  0, (uint8_t *)&fnum, 0, sizeof(fnum), NULL);
3337         cli_close(cli, fnum);
3338         status = cli_qpathinfo2(cli, "\\trans2\\", &c_time_ts, &a_time_ts,
3339                                 &w_time_ts, &m_time2_ts, &size, NULL, NULL);
3340         if (!NT_STATUS_IS_OK(status)) {
3341                 printf("ERROR: qpathinfo2 failed (%s)\n", nt_errstr(status));
3342                 correct = False;
3343         } else {
3344                 if (memcmp(&m_time_ts, &m_time2_ts, sizeof(struct timespec))
3345                     == 0) {
3346                         printf("This system does not update directory modification times\n");
3347                         correct = False;
3348                 }
3349         }
3350         cli_unlink(cli, fname2, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3351         cli_rmdir(cli, dname);
3352
3353         if (!torture_close_connection(cli)) {
3354                 correct = False;
3355         }
3356
3357         printf("trans2 test finished\n");
3358
3359         return correct;
3360 }
3361
3362 /*
3363   This checks new W2K calls.
3364 */
3365
3366 static NTSTATUS new_trans(struct cli_state *pcli, int fnum, int level)
3367 {
3368         uint8_t *buf = NULL;
3369         uint32 len;
3370         NTSTATUS status;
3371
3372         status = cli_qfileinfo(talloc_tos(), pcli, fnum, level, 0,
3373                                pcli->max_xmit, NULL, &buf, &len);
3374         if (!NT_STATUS_IS_OK(status)) {
3375                 printf("ERROR: qfileinfo (%d) failed (%s)\n", level,
3376                        nt_errstr(status));
3377         } else {
3378                 printf("qfileinfo: level %d, len = %u\n", level, len);
3379                 dump_data(0, (uint8 *)buf, len);
3380                 printf("\n");
3381         }
3382         TALLOC_FREE(buf);
3383         return status;
3384 }
3385
3386 static bool run_w2ktest(int dummy)
3387 {
3388         struct cli_state *cli;
3389         uint16_t fnum;
3390         const char *fname = "\\w2ktest\\w2k.tst";
3391         int level;
3392         bool correct = True;
3393
3394         printf("starting w2k test\n");
3395
3396         if (!torture_open_connection(&cli, 0)) {
3397                 return False;
3398         }
3399
3400         cli_open(cli, fname, 
3401                         O_RDWR | O_CREAT , DENY_NONE, &fnum);
3402
3403         for (level = 1004; level < 1040; level++) {
3404                 new_trans(cli, fnum, level);
3405         }
3406
3407         cli_close(cli, fnum);
3408
3409         if (!torture_close_connection(cli)) {
3410                 correct = False;
3411         }
3412
3413         printf("w2k test finished\n");
3414
3415         return correct;
3416 }
3417
3418
3419 /*
3420   this is a harness for some oplock tests
3421  */
3422 static bool run_oplock1(int dummy)
3423 {
3424         struct cli_state *cli1;
3425         const char *fname = "\\lockt1.lck";
3426         uint16_t fnum1;
3427         bool correct = True;
3428         NTSTATUS status;
3429
3430         printf("starting oplock test 1\n");
3431
3432         if (!torture_open_connection(&cli1, 0)) {
3433                 return False;
3434         }
3435
3436         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3437
3438         cli_sockopt(cli1, sockops);
3439
3440         cli1->use_oplocks = True;
3441
3442         status = cli_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
3443                           &fnum1);
3444         if (!NT_STATUS_IS_OK(status)) {
3445                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
3446                 return False;
3447         }
3448
3449         cli1->use_oplocks = False;
3450
3451         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3452         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3453
3454         status = cli_close(cli1, fnum1);
3455         if (!NT_STATUS_IS_OK(status)) {
3456                 printf("close2 failed (%s)\n", nt_errstr(status));
3457                 return False;
3458         }
3459
3460         status = cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3461         if (!NT_STATUS_IS_OK(status)) {
3462                 printf("unlink failed (%s)\n", nt_errstr(status));
3463                 return False;
3464         }
3465
3466         if (!torture_close_connection(cli1)) {
3467                 correct = False;
3468         }
3469
3470         printf("finished oplock test 1\n");
3471
3472         return correct;
3473 }
3474
3475 static bool run_oplock2(int dummy)
3476 {
3477         struct cli_state *cli1, *cli2;
3478         const char *fname = "\\lockt2.lck";
3479         uint16_t fnum1, fnum2;
3480         int saved_use_oplocks = use_oplocks;
3481         char buf[4];
3482         bool correct = True;
3483         volatile bool *shared_correct;
3484         NTSTATUS status;
3485
3486         shared_correct = (volatile bool *)shm_setup(sizeof(bool));
3487         *shared_correct = True;
3488
3489         use_level_II_oplocks = True;
3490         use_oplocks = True;
3491
3492         printf("starting oplock test 2\n");
3493
3494         if (!torture_open_connection(&cli1, 0)) {
3495                 use_level_II_oplocks = False;
3496                 use_oplocks = saved_use_oplocks;
3497                 return False;
3498         }
3499
3500         cli1->use_oplocks = True;
3501         cli1->use_level_II_oplocks = True;
3502
3503         if (!torture_open_connection(&cli2, 1)) {
3504                 use_level_II_oplocks = False;
3505                 use_oplocks = saved_use_oplocks;
3506                 return False;
3507         }
3508
3509         cli2->use_oplocks = True;
3510         cli2->use_level_II_oplocks = True;
3511
3512         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3513
3514         cli_sockopt(cli1, sockops);
3515         cli_sockopt(cli2, sockops);
3516
3517         status = cli_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
3518                           &fnum1);
3519         if (!NT_STATUS_IS_OK(status)) {
3520                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
3521                 return False;
3522         }
3523
3524         /* Don't need the globals any more. */
3525         use_level_II_oplocks = False;
3526         use_oplocks = saved_use_oplocks;
3527
3528         if (fork() == 0) {
3529                 /* Child code */
3530                 status = cli_open(cli2, fname, O_RDWR, DENY_NONE, &fnum2);
3531                 if (!NT_STATUS_IS_OK(status)) {
3532                         printf("second open of %s failed (%s)\n", fname, nt_errstr(status));
3533                         *shared_correct = False;
3534                         exit(0);
3535                 }
3536
3537                 sleep(2);
3538
3539                 status = cli_close(cli2, fnum2);
3540                 if (!NT_STATUS_IS_OK(status)) {
3541                         printf("close2 failed (%s)\n", nt_errstr(status));
3542                         *shared_correct = False;
3543                 }
3544
3545                 exit(0);
3546         }
3547
3548         sleep(2);
3549
3550         /* Ensure cli1 processes the break. Empty file should always return 0
3551          * bytes.  */
3552
3553         if (cli_read_old(cli1, fnum1, buf, 0, 4) != 0) {
3554                 printf("read on fnum1 failed (%s)\n", cli_errstr(cli1));
3555                 correct = False;
3556         }
3557
3558         /* Should now be at level II. */
3559         /* Test if sending a write locks causes a break to none. */
3560         status = cli_lock32(cli1, fnum1, 0, 4, 0, READ_LOCK);
3561         if (!NT_STATUS_IS_OK(status)) {
3562                 printf("lock failed (%s)\n", nt_errstr(status));
3563                 correct = False;
3564         }
3565
3566         cli_unlock(cli1, fnum1, 0, 4);
3567
3568         sleep(2);
3569
3570         status = cli_lock32(cli1, fnum1, 0, 4, 0, WRITE_LOCK);
3571         if (!NT_STATUS_IS_OK(status)) {
3572                 printf("lock failed (%s)\n", nt_errstr(status));
3573                 correct = False;
3574         }
3575
3576         cli_unlock(cli1, fnum1, 0, 4);
3577
3578         sleep(2);
3579
3580         cli_read_old(cli1, fnum1, buf, 0, 4);
3581
3582         status = cli_close(cli1, fnum1);
3583         if (!NT_STATUS_IS_OK(status)) {
3584                 printf("close1 failed (%s)\n", nt_errstr(status));
3585                 correct = False;
3586         }
3587
3588         sleep(4);
3589
3590         status = cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3591         if (!NT_STATUS_IS_OK(status)) {
3592                 printf("unlink failed (%s)\n", nt_errstr(status));
3593                 correct = False;
3594         }
3595
3596         if (!torture_close_connection(cli1)) {
3597                 correct = False;
3598         }
3599
3600         if (!*shared_correct) {
3601                 correct = False;
3602         }
3603
3604         printf("finished oplock test 2\n");
3605
3606         return correct;
3607 }
3608
3609 struct oplock4_state {
3610         struct tevent_context *ev;
3611         struct cli_state *cli;
3612         bool *got_break;
3613         uint16_t *fnum2;
3614 };
3615
3616 static void oplock4_got_break(struct tevent_req *req);
3617 static void oplock4_got_open(struct tevent_req *req);
3618
3619 static bool run_oplock4(int dummy)
3620 {
3621         struct tevent_context *ev;
3622         struct cli_state *cli1, *cli2;
3623         struct tevent_req *oplock_req, *open_req;
3624         const char *fname = "\\lockt4.lck";
3625         const char *fname_ln = "\\lockt4_ln.lck";
3626         uint16_t fnum1, fnum2;
3627         int saved_use_oplocks = use_oplocks;
3628         NTSTATUS status;
3629         bool correct = true;
3630
3631         bool got_break;
3632
3633         struct oplock4_state *state;
3634
3635         printf("starting oplock test 4\n");
3636
3637         if (!torture_open_connection(&cli1, 0)) {
3638                 use_level_II_oplocks = false;
3639                 use_oplocks = saved_use_oplocks;
3640                 return false;
3641         }
3642
3643         if (!torture_open_connection(&cli2, 1)) {
3644                 use_level_II_oplocks = false;
3645                 use_oplocks = saved_use_oplocks;
3646                 return false;
3647         }
3648
3649         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3650         cli_unlink(cli1, fname_ln, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3651
3652         cli_sockopt(cli1, sockops);
3653         cli_sockopt(cli2, sockops);
3654
3655         /* Create the file. */
3656         status = cli_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
3657                           &fnum1);
3658         if (!NT_STATUS_IS_OK(status)) {
3659                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
3660                 return false;
3661         }
3662
3663         status = cli_close(cli1, fnum1);
3664         if (!NT_STATUS_IS_OK(status)) {
3665                 printf("close1 failed (%s)\n", nt_errstr(status));
3666                 return false;
3667         }
3668
3669         /* Now create a hardlink. */
3670         status = cli_nt_hardlink(cli1, fname, fname_ln);
3671         if (!NT_STATUS_IS_OK(status)) {
3672                 printf("nt hardlink failed (%s)\n", nt_errstr(status));
3673                 return false;
3674         }
3675
3676         /* Prove that opening hardlinks cause deny modes to conflict. */
3677         status = cli_open(cli1, fname, O_RDWR, DENY_ALL, &fnum1);
3678         if (!NT_STATUS_IS_OK(status)) {
3679                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
3680                 return false;
3681         }
3682
3683         status = cli_open(cli1, fname_ln, O_RDWR, DENY_NONE, &fnum2);
3684         if (NT_STATUS_IS_OK(status)) {
3685                 printf("open of %s succeeded - should fail with sharing violation.\n",
3686                         fname_ln);
3687                 return false;
3688         }
3689
3690         if (!NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
3691                 printf("open of %s should fail with sharing violation. Got %s\n",
3692                         fname_ln, nt_errstr(status));
3693                 return false;
3694         }
3695
3696         status = cli_close(cli1, fnum1);
3697         if (!NT_STATUS_IS_OK(status)) {
3698                 printf("close1 failed (%s)\n", nt_errstr(status));
3699                 return false;
3700         }
3701
3702         cli1->use_oplocks = true;
3703         cli1->use_level_II_oplocks = true;
3704
3705         cli2->use_oplocks = true;
3706         cli2->use_level_II_oplocks = true;
3707
3708         status = cli_open(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
3709         if (!NT_STATUS_IS_OK(status)) {
3710                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
3711                 return false;
3712         }
3713
3714         ev = tevent_context_init(talloc_tos());
3715         if (ev == NULL) {
3716                 printf("tevent_req_create failed\n");
3717                 return false;
3718         }
3719
3720         state = talloc(ev, struct oplock4_state);
3721         if (state == NULL) {
3722                 printf("talloc failed\n");
3723                 return false;
3724         }
3725         state->ev = ev;
3726         state->cli = cli1;
3727         state->got_break = &got_break;
3728         state->fnum2 = &fnum2;
3729
3730         oplock_req = cli_smb_oplock_break_waiter_send(
3731                 talloc_tos(), ev, cli1);
3732         if (oplock_req == NULL) {
3733                 printf("cli_smb_oplock_break_waiter_send failed\n");
3734                 return false;
3735         }
3736         tevent_req_set_callback(oplock_req, oplock4_got_break, state);
3737
3738         open_req = cli_open_send(
3739                 talloc_tos(), ev, cli2, fname_ln, O_RDWR, DENY_NONE);
3740         if (oplock_req == NULL) {
3741                 printf("cli_open_send failed\n");
3742                 return false;
3743         }
3744         tevent_req_set_callback(open_req, oplock4_got_open, state);
3745
3746         got_break = false;
3747         fnum2 = 0xffff;
3748
3749         while (!got_break || fnum2 == 0xffff) {
3750                 int ret;
3751                 ret = tevent_loop_once(ev);
3752                 if (ret == -1) {
3753                         printf("tevent_loop_once failed: %s\n",
3754                                strerror(errno));
3755                         return false;
3756                 }
3757         }
3758
3759         status = cli_close(cli2, fnum2);
3760         if (!NT_STATUS_IS_OK(status)) {
3761                 printf("close2 failed (%s)\n", nt_errstr(status));
3762                 correct = false;
3763         }
3764
3765         status = cli_close(cli1, fnum1);
3766         if (!NT_STATUS_IS_OK(status)) {
3767                 printf("close1 failed (%s)\n", nt_errstr(status));
3768                 correct = false;
3769         }
3770
3771         status = cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3772         if (!NT_STATUS_IS_OK(status)) {
3773                 printf("unlink failed (%s)\n", nt_errstr(status));
3774                 correct = false;
3775         }
3776
3777         status = cli_unlink(cli1, fname_ln, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3778         if (!NT_STATUS_IS_OK(status)) {
3779                 printf("unlink failed (%s)\n", nt_errstr(status));
3780                 correct = false;
3781         }
3782
3783         if (!torture_close_connection(cli1)) {
3784                 correct = false;
3785         }
3786
3787         if (!got_break) {
3788                 correct = false;
3789         }
3790
3791         printf("finished oplock test 4\n");
3792
3793         return correct;
3794 }
3795
3796 static void oplock4_got_break(struct tevent_req *req)
3797 {
3798         struct oplock4_state *state = tevent_req_callback_data(
3799                 req, struct oplock4_state);
3800         uint16_t fnum;
3801         uint8_t level;
3802         NTSTATUS status;
3803
3804         status = cli_smb_oplock_break_waiter_recv(req, &fnum, &level);
3805         TALLOC_FREE(req);
3806         if (!NT_STATUS_IS_OK(status)) {
3807                 printf("cli_smb_oplock_break_waiter_recv returned %s\n",
3808                        nt_errstr(status));
3809                 return;
3810         }
3811         *state->got_break = true;
3812
3813         req = cli_oplock_ack_send(state, state->ev, state->cli, fnum,
3814                                   NO_OPLOCK);
3815         if (req == NULL) {
3816                 printf("cli_oplock_ack_send failed\n");
3817                 return;
3818         }
3819 }
3820
3821 static void oplock4_got_open(struct tevent_req *req)
3822 {
3823         struct oplock4_state *state = tevent_req_callback_data(
3824                 req, struct oplock4_state);
3825         NTSTATUS status;
3826
3827         status = cli_open_recv(req, state->fnum2);
3828         if (!NT_STATUS_IS_OK(status)) {
3829                 printf("cli_open_recv returned %s\n", nt_errstr(status));
3830                 *state->fnum2 = 0xffff;
3831         }
3832 }
3833
3834 /*
3835   Test delete on close semantics.
3836  */
3837 static bool run_deletetest(int dummy)
3838 {
3839         struct cli_state *cli1 = NULL;
3840         struct cli_state *cli2 = NULL;
3841         const char *fname = "\\delete.file";
3842         uint16_t fnum1 = (uint16_t)-1;
3843         uint16_t fnum2 = (uint16_t)-1;
3844         bool correct = True;
3845         NTSTATUS status;
3846
3847         printf("starting delete test\n");
3848
3849         if (!torture_open_connection(&cli1, 0)) {
3850                 return False;
3851         }
3852
3853         cli_sockopt(cli1, sockops);