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