s3-torture: run_locktest5(): replace cli_lock() with cli_lock32()
[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
1801                 status = cli_lock32(cli1, fnum1, offset-1, 1, 0, WRITE_LOCK);
1802                 if (!NT_STATUS_IS_OK(status)) {
1803                         printf("lock1 %d failed (%s)\n", 
1804                                i,
1805                                nt_errstr(status));
1806                         return False;
1807                 }
1808
1809                 status = cli_lock32(cli2, fnum2, offset-2, 1, 0, WRITE_LOCK);
1810                 if (!NT_STATUS_IS_OK(status)) {
1811                         printf("lock2 %d failed (%s)\n", 
1812                                i,
1813                                nt_errstr(status));
1814                         return False;
1815                 }
1816         }
1817
1818         for (offset=i=0;i<torture_numops;i++) {
1819                 NEXT_OFFSET;
1820
1821                 status = cli_lock32(cli1, fnum1, offset-2, 1, 0, WRITE_LOCK);
1822                 if (NT_STATUS_IS_OK(status)) {
1823                         printf("error: lock1 %d succeeded!\n", i);
1824                         return False;
1825                 }
1826
1827                 status = cli_lock32(cli2, fnum2, offset-1, 1, 0, WRITE_LOCK);
1828                 if (NT_STATUS_IS_OK(status)) {
1829                         printf("error: lock2 %d succeeded!\n", i);
1830                         return False;
1831                 }
1832
1833                 status = cli_lock32(cli1, fnum1, offset-1, 1, 0, WRITE_LOCK);
1834                 if (NT_STATUS_IS_OK(status)) {
1835                         printf("error: lock3 %d succeeded!\n", i);
1836                         return False;
1837                 }
1838
1839                 status = cli_lock32(cli2, fnum2, offset-2, 1, 0, WRITE_LOCK);
1840                 if (NT_STATUS_IS_OK(status)) {
1841                         printf("error: lock4 %d succeeded!\n", i);
1842                         return False;
1843                 }
1844         }
1845
1846         for (offset=i=0;i<torture_numops;i++) {
1847                 NEXT_OFFSET;
1848
1849                 status = cli_unlock(cli1, fnum1, offset-1, 1);
1850                 if (!NT_STATUS_IS_OK(status)) {
1851                         printf("unlock1 %d failed (%s)\n", 
1852                                i,
1853                                nt_errstr(status));
1854                         return False;
1855                 }
1856
1857                 status = cli_unlock(cli2, fnum2, offset-2, 1);
1858                 if (!NT_STATUS_IS_OK(status)) {
1859                         printf("unlock2 %d failed (%s)\n", 
1860                                i,
1861                                nt_errstr(status));
1862                         return False;
1863                 }
1864         }
1865
1866         status = cli_close(cli1, fnum1);
1867         if (!NT_STATUS_IS_OK(status)) {
1868                 printf("close1 failed (%s)\n", nt_errstr(status));
1869                 return False;
1870         }
1871
1872         status = cli_close(cli2, fnum2);
1873         if (!NT_STATUS_IS_OK(status)) {
1874                 printf("close2 failed (%s)\n", nt_errstr(status));
1875                 return False;
1876         }
1877
1878         status = cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1879         if (!NT_STATUS_IS_OK(status)) {
1880                 printf("unlink failed (%s)\n", nt_errstr(status));
1881                 return False;
1882         }
1883
1884         if (!torture_close_connection(cli1)) {
1885                 correct = False;
1886         }
1887
1888         if (!torture_close_connection(cli2)) {
1889                 correct = False;
1890         }
1891
1892         printf("finished locktest3\n");
1893
1894         return correct;
1895 }
1896
1897 #define EXPECTED(ret, v) if ((ret) != (v)) { \
1898         printf("** "); correct = False; \
1899         }
1900
1901 /*
1902   looks at overlapping locks
1903 */
1904 static bool run_locktest4(int dummy)
1905 {
1906         static struct cli_state *cli1, *cli2;
1907         const char *fname = "\\lockt4.lck";
1908         uint16_t fnum1, fnum2, f;
1909         bool ret;
1910         char buf[1000];
1911         bool correct = True;
1912         NTSTATUS status;
1913
1914         if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
1915                 return False;
1916         }
1917
1918         cli_sockopt(cli1, sockops);
1919         cli_sockopt(cli2, sockops);
1920
1921         printf("starting locktest4\n");
1922
1923         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1924
1925         cli_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
1926         cli_open(cli2, fname, O_RDWR, DENY_NONE, &fnum2);
1927
1928         memset(buf, 0, sizeof(buf));
1929
1930         status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 0, sizeof(buf),
1931                               NULL);
1932         if (!NT_STATUS_IS_OK(status)) {
1933                 printf("Failed to create file: %s\n", nt_errstr(status));
1934                 correct = False;
1935                 goto fail;
1936         }
1937
1938         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 4, 0, WRITE_LOCK)) &&
1939               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 2, 4, 0, WRITE_LOCK));
1940         EXPECTED(ret, False);
1941         printf("the same process %s set overlapping write locks\n", ret?"can":"cannot");
1942
1943         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 10, 4, 0, READ_LOCK)) &&
1944               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 12, 4, 0, READ_LOCK));
1945         EXPECTED(ret, True);
1946         printf("the same process %s set overlapping read locks\n", ret?"can":"cannot");
1947
1948         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 20, 4, 0, WRITE_LOCK)) &&
1949               NT_STATUS_IS_OK(cli_lock32(cli2, fnum2, 22, 4, 0, WRITE_LOCK));
1950         EXPECTED(ret, False);
1951         printf("a different connection %s set overlapping write locks\n", ret?"can":"cannot");
1952
1953         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 30, 4, 0, READ_LOCK)) &&
1954               NT_STATUS_IS_OK(cli_lock32(cli2, fnum2, 32, 4, 0, READ_LOCK));
1955         EXPECTED(ret, True);
1956         printf("a different connection %s set overlapping read locks\n", ret?"can":"cannot");
1957
1958         ret = (cli_setpid(cli1, 1),
1959               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 40, 4, 0, WRITE_LOCK))) &&
1960               (cli_setpid(cli1, 2),
1961               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 42, 4, 0, WRITE_LOCK)));
1962         EXPECTED(ret, False);
1963         printf("a different pid %s set overlapping write locks\n", ret?"can":"cannot");
1964
1965         ret = (cli_setpid(cli1, 1),
1966               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 50, 4, 0, READ_LOCK))) &&
1967               (cli_setpid(cli1, 2),
1968               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 52, 4, 0, READ_LOCK)));
1969         EXPECTED(ret, True);
1970         printf("a different pid %s set overlapping read locks\n", ret?"can":"cannot");
1971
1972         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 60, 4, 0, READ_LOCK)) &&
1973               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 60, 4, 0, READ_LOCK));
1974         EXPECTED(ret, True);
1975         printf("the same process %s set the same read lock twice\n", ret?"can":"cannot");
1976
1977         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 70, 4, 0, WRITE_LOCK)) &&
1978               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 70, 4, 0, WRITE_LOCK));
1979         EXPECTED(ret, False);
1980         printf("the same process %s set the same write lock twice\n", ret?"can":"cannot");
1981
1982         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 80, 4, 0, READ_LOCK)) &&
1983               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 80, 4, 0, WRITE_LOCK));
1984         EXPECTED(ret, False);
1985         printf("the same process %s overlay a read lock with a write lock\n", ret?"can":"cannot");
1986
1987         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 90, 4, 0, WRITE_LOCK)) &&
1988               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 90, 4, 0, READ_LOCK));
1989         EXPECTED(ret, True);
1990         printf("the same process %s overlay a write lock with a read lock\n", ret?"can":"cannot");
1991
1992         ret = (cli_setpid(cli1, 1),
1993              NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 100, 4, 0, WRITE_LOCK))) &&
1994              (cli_setpid(cli1, 2),
1995              NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 100, 4, 0, READ_LOCK)));
1996         EXPECTED(ret, False);
1997         printf("a different pid %s overlay a write lock with a read lock\n", ret?"can":"cannot");
1998
1999         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 110, 4, 0, READ_LOCK)) &&
2000               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 112, 4, 0, READ_LOCK)) &&
2001               NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 110, 6));
2002         EXPECTED(ret, False);
2003         printf("the same process %s coalesce read locks\n", ret?"can":"cannot");
2004
2005
2006         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 120, 4, 0, WRITE_LOCK)) &&
2007               (cli_read(cli2, fnum2, buf, 120, 4) == 4);
2008         EXPECTED(ret, False);
2009         printf("this server %s strict write locking\n", ret?"doesn't do":"does");
2010
2011         status = cli_lock32(cli1, fnum1, 130, 4, 0, READ_LOCK);
2012         ret = NT_STATUS_IS_OK(status);
2013         if (ret) {
2014                 status = cli_writeall(cli2, fnum2, 0, (uint8_t *)buf, 130, 4,
2015                                       NULL);
2016                 ret = NT_STATUS_IS_OK(status);
2017         }
2018         EXPECTED(ret, False);
2019         printf("this server %s strict read locking\n", ret?"doesn't do":"does");
2020
2021
2022         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 140, 4, 0, READ_LOCK)) &&
2023               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 140, 4, 0, READ_LOCK)) &&
2024               NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 140, 4)) &&
2025               NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 140, 4));
2026         EXPECTED(ret, True);
2027         printf("this server %s do recursive read locking\n", ret?"does":"doesn't");
2028
2029
2030         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 150, 4, 0, WRITE_LOCK)) &&
2031               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 150, 4, 0, READ_LOCK)) &&
2032               NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 150, 4)) &&
2033               (cli_read(cli2, fnum2, buf, 150, 4) == 4) &&
2034               !(NT_STATUS_IS_OK(cli_writeall(cli2, fnum2, 0, (uint8_t *)buf,
2035                                              150, 4, NULL))) &&
2036               NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 150, 4));
2037         EXPECTED(ret, True);
2038         printf("this server %s do recursive lock overlays\n", ret?"does":"doesn't");
2039
2040         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 160, 4, 0, READ_LOCK)) &&
2041               NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 160, 4)) &&
2042               NT_STATUS_IS_OK(cli_writeall(cli2, fnum2, 0, (uint8_t *)buf,
2043                                            160, 4, NULL)) &&
2044               (cli_read(cli2, fnum2, buf, 160, 4) == 4);                
2045         EXPECTED(ret, True);
2046         printf("the same process %s remove a read lock using write locking\n", ret?"can":"cannot");
2047
2048         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 170, 4, 0, WRITE_LOCK)) &&
2049               NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 170, 4)) &&
2050               NT_STATUS_IS_OK(cli_writeall(cli2, fnum2, 0, (uint8_t *)buf,
2051                                            170, 4, NULL)) &&
2052               (cli_read(cli2, fnum2, buf, 170, 4) == 4);                
2053         EXPECTED(ret, True);
2054         printf("the same process %s remove a write lock using read locking\n", ret?"can":"cannot");
2055
2056         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 190, 4, 0, WRITE_LOCK)) &&
2057               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 190, 4, 0, READ_LOCK)) &&
2058               NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 190, 4)) &&
2059               !NT_STATUS_IS_OK(cli_writeall(cli2, fnum2, 0, (uint8_t *)buf,
2060                                             190, 4, NULL)) &&
2061               (cli_read(cli2, fnum2, buf, 190, 4) == 4);                
2062         EXPECTED(ret, True);
2063         printf("the same process %s remove the first lock first\n", ret?"does":"doesn't");
2064
2065         cli_close(cli1, fnum1);
2066         cli_close(cli2, fnum2);
2067         cli_open(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
2068         cli_open(cli1, fname, O_RDWR, DENY_NONE, &f);
2069         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 8, 0, READ_LOCK)) &&
2070               NT_STATUS_IS_OK(cli_lock32(cli1, f, 0, 1, 0, READ_LOCK)) &&
2071               NT_STATUS_IS_OK(cli_close(cli1, fnum1)) &&
2072               NT_STATUS_IS_OK(cli_open(cli1, fname, O_RDWR, DENY_NONE, &fnum1)) &&
2073               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 7, 1, 0, WRITE_LOCK));
2074         cli_close(cli1, f);
2075         cli_close(cli1, fnum1);
2076         EXPECTED(ret, True);
2077         printf("the server %s have the NT byte range lock bug\n", !ret?"does":"doesn't");
2078
2079  fail:
2080         cli_close(cli1, fnum1);
2081         cli_close(cli2, fnum2);
2082         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2083         torture_close_connection(cli1);
2084         torture_close_connection(cli2);
2085
2086         printf("finished locktest4\n");
2087         return correct;
2088 }
2089
2090 /*
2091   looks at lock upgrade/downgrade.
2092 */
2093 static bool run_locktest5(int dummy)
2094 {
2095         static struct cli_state *cli1, *cli2;
2096         const char *fname = "\\lockt5.lck";
2097         uint16_t fnum1, fnum2, fnum3;
2098         bool ret;
2099         char buf[1000];
2100         bool correct = True;
2101         NTSTATUS status;
2102
2103         if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
2104                 return False;
2105         }
2106
2107         cli_sockopt(cli1, sockops);
2108         cli_sockopt(cli2, sockops);
2109
2110         printf("starting locktest5\n");
2111
2112         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2113
2114         cli_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
2115         cli_open(cli2, fname, O_RDWR, DENY_NONE, &fnum2);
2116         cli_open(cli1, fname, O_RDWR, DENY_NONE, &fnum3);
2117
2118         memset(buf, 0, sizeof(buf));
2119
2120         status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 0, sizeof(buf),
2121                               NULL);
2122         if (!NT_STATUS_IS_OK(status)) {
2123                 printf("Failed to create file: %s\n", nt_errstr(status));
2124                 correct = False;
2125                 goto fail;
2126         }
2127
2128         /* Check for NT bug... */
2129         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 8, 0, READ_LOCK)) &&
2130               NT_STATUS_IS_OK(cli_lock32(cli1, fnum3, 0, 1, 0, READ_LOCK));
2131         cli_close(cli1, fnum1);
2132         cli_open(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
2133         status = cli_lock32(cli1, fnum1, 7, 1, 0, WRITE_LOCK);
2134         ret = NT_STATUS_IS_OK(status);
2135         EXPECTED(ret, True);
2136         printf("this server %s the NT locking bug\n", ret ? "doesn't have" : "has");
2137         cli_close(cli1, fnum1);
2138         cli_open(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
2139         cli_unlock(cli1, fnum3, 0, 1);
2140
2141         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 4, 0, WRITE_LOCK)) &&
2142               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 1, 1, 0, READ_LOCK));
2143         EXPECTED(ret, True);
2144         printf("the same process %s overlay a write with a read lock\n", ret?"can":"cannot");
2145
2146         status = cli_lock32(cli2, fnum2, 0, 4, 0, READ_LOCK);
2147         ret = NT_STATUS_IS_OK(status);
2148         EXPECTED(ret, False);
2149
2150         printf("a different processs %s get a read lock on the first process lock stack\n", ret?"can":"cannot");
2151
2152         /* Unlock the process 2 lock. */
2153         cli_unlock(cli2, fnum2, 0, 4);
2154
2155         status = cli_lock32(cli1, fnum3, 0, 4, 0, READ_LOCK);
2156         ret = NT_STATUS_IS_OK(status);
2157         EXPECTED(ret, False);
2158
2159         printf("the same processs on a different fnum %s get a read lock\n", ret?"can":"cannot");
2160
2161         /* Unlock the process 1 fnum3 lock. */
2162         cli_unlock(cli1, fnum3, 0, 4);
2163
2164         /* Stack 2 more locks here. */
2165         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 4, 0, READ_LOCK)) &&
2166               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 4, 0, READ_LOCK));
2167
2168         EXPECTED(ret, True);
2169         printf("the same process %s stack read locks\n", ret?"can":"cannot");
2170
2171         /* Unlock the first process lock, then check this was the WRITE lock that was
2172                 removed. */
2173
2174         ret = NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 0, 4)) &&
2175               NT_STATUS_IS_OK(cli_lock32(cli2, fnum2, 0, 4, 0, READ_LOCK));
2176
2177         EXPECTED(ret, True);
2178         printf("the first unlock removes the %s lock\n", ret?"WRITE":"READ");
2179
2180         /* Unlock the process 2 lock. */
2181         cli_unlock(cli2, fnum2, 0, 4);
2182
2183         /* We should have 3 stacked locks here. Ensure we need to do 3 unlocks. */
2184
2185         ret = NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 1, 1)) &&
2186                   NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 0, 4)) &&
2187                   NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 0, 4));
2188
2189         EXPECTED(ret, True);
2190         printf("the same process %s unlock the stack of 4 locks\n", ret?"can":"cannot"); 
2191
2192         /* Ensure the next unlock fails. */
2193         ret = NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 0, 4));
2194         EXPECTED(ret, False);
2195         printf("the same process %s count the lock stack\n", !ret?"can":"cannot"); 
2196
2197         /* Ensure connection 2 can get a write lock. */
2198         status = cli_lock32(cli2, fnum2, 0, 4, 0, WRITE_LOCK);
2199         ret = NT_STATUS_IS_OK(status);
2200         EXPECTED(ret, True);
2201
2202         printf("a different processs %s get a write lock on the unlocked stack\n", ret?"can":"cannot");
2203
2204
2205  fail:
2206         cli_close(cli1, fnum1);
2207         cli_close(cli2, fnum2);
2208         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2209         if (!torture_close_connection(cli1)) {
2210                 correct = False;
2211         }
2212         if (!torture_close_connection(cli2)) {
2213                 correct = False;
2214         }
2215
2216         printf("finished locktest5\n");
2217
2218         return correct;
2219 }
2220
2221 /*
2222   tries the unusual lockingX locktype bits
2223 */
2224 static bool run_locktest6(int dummy)
2225 {
2226         static struct cli_state *cli;
2227         const char *fname[1] = { "\\lock6.txt" };
2228         int i;
2229         uint16_t fnum;
2230         NTSTATUS status;
2231
2232         if (!torture_open_connection(&cli, 0)) {
2233                 return False;
2234         }
2235
2236         cli_sockopt(cli, sockops);
2237
2238         printf("starting locktest6\n");
2239
2240         for (i=0;i<1;i++) {
2241                 printf("Testing %s\n", fname[i]);
2242
2243                 cli_unlink(cli, fname[i], FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2244
2245                 cli_open(cli, fname[i], O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
2246                 status = cli_locktype(cli, fnum, 0, 8, 0, LOCKING_ANDX_CHANGE_LOCKTYPE);
2247                 cli_close(cli, fnum);
2248                 printf("CHANGE_LOCKTYPE gave %s\n", nt_errstr(status));
2249
2250                 cli_open(cli, fname[i], O_RDWR, DENY_NONE, &fnum);
2251                 status = cli_locktype(cli, fnum, 0, 8, 0, LOCKING_ANDX_CANCEL_LOCK);
2252                 cli_close(cli, fnum);
2253                 printf("CANCEL_LOCK gave %s\n", nt_errstr(status));
2254
2255                 cli_unlink(cli, fname[i], FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2256         }
2257
2258         torture_close_connection(cli);
2259
2260         printf("finished locktest6\n");
2261         return True;
2262 }
2263
2264 static bool run_locktest7(int dummy)
2265 {
2266         struct cli_state *cli1;
2267         const char *fname = "\\lockt7.lck";
2268         uint16_t fnum1;
2269         char buf[200];
2270         bool correct = False;
2271         NTSTATUS status;
2272
2273         if (!torture_open_connection(&cli1, 0)) {
2274                 return False;
2275         }
2276
2277         cli_sockopt(cli1, sockops);
2278
2279         printf("starting locktest7\n");
2280
2281         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2282
2283         cli_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
2284
2285         memset(buf, 0, sizeof(buf));
2286
2287         status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 0, sizeof(buf),
2288                               NULL);
2289         if (!NT_STATUS_IS_OK(status)) {
2290                 printf("Failed to create file: %s\n", nt_errstr(status));
2291                 goto fail;
2292         }
2293
2294         cli_setpid(cli1, 1);
2295
2296         status = cli_lock32(cli1, fnum1, 130, 4, 0, READ_LOCK);
2297         if (!NT_STATUS_IS_OK(status)) {
2298                 printf("Unable to apply read lock on range 130:4, error was %s\n", nt_errstr(status));
2299                 goto fail;
2300         } else {
2301                 printf("pid1 successfully locked range 130:4 for READ\n");
2302         }
2303
2304         if (cli_read(cli1, fnum1, buf, 130, 4) != 4) {
2305                 printf("pid1 unable to read the range 130:4, error was %s\n", cli_errstr(cli1));
2306                 goto fail;
2307         } else {
2308                 printf("pid1 successfully read the range 130:4\n");
2309         }
2310
2311         status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
2312         if (!NT_STATUS_IS_OK(status)) {
2313                 printf("pid1 unable to write to the range 130:4, error was "
2314                        "%s\n", nt_errstr(status));
2315                 if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
2316                         printf("Incorrect error (should be NT_STATUS_FILE_LOCK_CONFLICT)\n");
2317                         goto fail;
2318                 }
2319         } else {
2320                 printf("pid1 successfully wrote to the range 130:4 (should be denied)\n");
2321                 goto fail;
2322         }
2323
2324         cli_setpid(cli1, 2);
2325
2326         if (cli_read(cli1, fnum1, buf, 130, 4) != 4) {
2327                 printf("pid2 unable to read the range 130:4, error was %s\n", cli_errstr(cli1));
2328         } else {
2329                 printf("pid2 successfully read the range 130:4\n");
2330         }
2331
2332         status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
2333         if (!NT_STATUS_IS_OK(status)) {
2334                 printf("pid2 unable to write to the range 130:4, error was "
2335                        "%s\n", nt_errstr(status));
2336                 if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
2337                         printf("Incorrect error (should be NT_STATUS_FILE_LOCK_CONFLICT)\n");
2338                         goto fail;
2339                 }
2340         } else {
2341                 printf("pid2 successfully wrote to the range 130:4 (should be denied)\n");
2342                 goto fail;
2343         }
2344
2345         cli_setpid(cli1, 1);
2346         cli_unlock(cli1, fnum1, 130, 4);
2347
2348         status = cli_lock32(cli1, fnum1, 130, 4, 0, WRITE_LOCK);
2349         if (!NT_STATUS_IS_OK(status)) {
2350                 printf("Unable to apply write lock on range 130:4, error was %s\n", nt_errstr(status));
2351                 goto fail;
2352         } else {
2353                 printf("pid1 successfully locked range 130:4 for WRITE\n");
2354         }
2355
2356         if (cli_read(cli1, fnum1, buf, 130, 4) != 4) {
2357                 printf("pid1 unable to read the range 130:4, error was %s\n", cli_errstr(cli1));
2358                 goto fail;
2359         } else {
2360                 printf("pid1 successfully read the range 130:4\n");
2361         }
2362
2363         status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
2364         if (!NT_STATUS_IS_OK(status)) {
2365                 printf("pid1 unable to write to the range 130:4, error was "
2366                        "%s\n", nt_errstr(status));
2367                 goto fail;
2368         } else {
2369                 printf("pid1 successfully wrote to the range 130:4\n");
2370         }
2371
2372         cli_setpid(cli1, 2);
2373
2374         if (cli_read(cli1, fnum1, buf, 130, 4) != 4) {
2375                 printf("pid2 unable to read the range 130:4, error was %s\n", cli_errstr(cli1));
2376                 if (NT_STATUS_V(cli_nt_error(cli1)) != NT_STATUS_V(NT_STATUS_FILE_LOCK_CONFLICT)) {
2377                         printf("Incorrect error (should be NT_STATUS_FILE_LOCK_CONFLICT)\n");
2378                         goto fail;
2379                 }
2380         } else {
2381                 printf("pid2 successfully read the range 130:4 (should be denied)\n");
2382                 goto fail;
2383         }
2384
2385         status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
2386         if (!NT_STATUS_IS_OK(status)) {
2387                 printf("pid2 unable to write to the range 130:4, error was "
2388                        "%s\n", nt_errstr(status));
2389                 if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
2390                         printf("Incorrect error (should be NT_STATUS_FILE_LOCK_CONFLICT)\n");
2391                         goto fail;
2392                 }
2393         } else {
2394                 printf("pid2 successfully wrote to the range 130:4 (should be denied)\n");
2395                 goto fail;
2396         }
2397
2398         cli_unlock(cli1, fnum1, 130, 0);
2399         correct = True;
2400
2401 fail:
2402         cli_close(cli1, fnum1);
2403         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2404         torture_close_connection(cli1);
2405
2406         printf("finished locktest7\n");
2407         return correct;
2408 }
2409
2410 /*
2411  * This demonstrates a problem with our use of GPFS share modes: A file
2412  * descriptor sitting in the pending close queue holding a GPFS share mode
2413  * blocks opening a file another time. Happens with Word 2007 temp files.
2414  * With "posix locking = yes" and "gpfs:sharemodes = yes" enabled, the third
2415  * open is denied with NT_STATUS_SHARING_VIOLATION.
2416  */
2417
2418 static bool run_locktest8(int dummy)
2419 {
2420         struct cli_state *cli1;
2421         const char *fname = "\\lockt8.lck";
2422         uint16_t fnum1, fnum2;
2423         char buf[200];
2424         bool correct = False;
2425         NTSTATUS status;
2426
2427         if (!torture_open_connection(&cli1, 0)) {
2428                 return False;
2429         }
2430
2431         cli_sockopt(cli1, sockops);
2432
2433         printf("starting locktest8\n");
2434
2435         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2436
2437         status = cli_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_WRITE,
2438                           &fnum1);
2439         if (!NT_STATUS_IS_OK(status)) {
2440                 d_fprintf(stderr, "cli_open returned %s\n", nt_errstr(status));
2441                 return false;
2442         }
2443
2444         memset(buf, 0, sizeof(buf));
2445
2446         status = cli_open(cli1, fname, O_RDONLY, DENY_NONE, &fnum2);
2447         if (!NT_STATUS_IS_OK(status)) {
2448                 d_fprintf(stderr, "cli_open second time returned %s\n",
2449                           nt_errstr(status));
2450                 goto fail;
2451         }
2452
2453         status = cli_lock32(cli1, fnum2, 1, 1, 0, READ_LOCK);
2454         if (!NT_STATUS_IS_OK(status)) {
2455                 printf("Unable to apply read lock on range 1:1, error was "
2456                        "%s\n", nt_errstr(status));
2457                 goto fail;
2458         }
2459
2460         status = cli_close(cli1, fnum1);
2461         if (!NT_STATUS_IS_OK(status)) {
2462                 d_fprintf(stderr, "cli_close(fnum1) %s\n", nt_errstr(status));
2463                 goto fail;
2464         }
2465
2466         status = cli_open(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
2467         if (!NT_STATUS_IS_OK(status)) {
2468                 d_fprintf(stderr, "cli_open third time returned %s\n",
2469                           nt_errstr(status));
2470                 goto fail;
2471         }
2472
2473         correct = true;
2474
2475 fail:
2476         cli_close(cli1, fnum1);
2477         cli_close(cli1, fnum2);
2478         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2479         torture_close_connection(cli1);
2480
2481         printf("finished locktest8\n");
2482         return correct;
2483 }
2484
2485 /*
2486  * This test is designed to be run in conjunction with
2487  * external NFS or POSIX locks taken in the filesystem.
2488  * It checks that the smbd server will block until the
2489  * lock is released and then acquire it. JRA.
2490  */
2491
2492 static bool got_alarm;
2493 static int alarm_fd;
2494
2495 static void alarm_handler(int dummy)
2496 {
2497         got_alarm = True;
2498 }
2499
2500 static void alarm_handler_parent(int dummy)
2501 {
2502         close(alarm_fd);
2503 }
2504
2505 static void do_local_lock(int read_fd, int write_fd)
2506 {
2507         int fd;
2508         char c = '\0';
2509         struct flock lock;
2510         const char *local_pathname = NULL;
2511         int ret;
2512
2513         local_pathname = talloc_asprintf(talloc_tos(),
2514                         "%s/lockt9.lck", local_path);
2515         if (!local_pathname) {
2516                 printf("child: alloc fail\n");
2517                 exit(1);
2518         }
2519
2520         unlink(local_pathname);
2521         fd = open(local_pathname, O_RDWR|O_CREAT, 0666);
2522         if (fd == -1) {
2523                 printf("child: open of %s failed %s.\n",
2524                         local_pathname, strerror(errno));
2525                 exit(1);
2526         }
2527
2528         /* Now take a fcntl lock. */
2529         lock.l_type = F_WRLCK;
2530         lock.l_whence = SEEK_SET;
2531         lock.l_start = 0;
2532         lock.l_len = 4;
2533         lock.l_pid = getpid();
2534
2535         ret = fcntl(fd,F_SETLK,&lock);
2536         if (ret == -1) {
2537                 printf("child: failed to get lock 0:4 on file %s. Error %s\n",
2538                         local_pathname, strerror(errno));
2539                 exit(1);
2540         } else {
2541                 printf("child: got lock 0:4 on file %s.\n",
2542                         local_pathname );
2543                 fflush(stdout);
2544         }
2545
2546         CatchSignal(SIGALRM, alarm_handler);
2547         alarm(5);
2548         /* Signal the parent. */
2549         if (write(write_fd, &c, 1) != 1) {
2550                 printf("child: start signal fail %s.\n",
2551                         strerror(errno));
2552                 exit(1);
2553         }
2554         alarm(0);
2555
2556         alarm(10);
2557         /* Wait for the parent to be ready. */
2558         if (read(read_fd, &c, 1) != 1) {
2559                 printf("child: reply signal fail %s.\n",
2560                         strerror(errno));
2561                 exit(1);
2562         }
2563         alarm(0);
2564
2565         sleep(5);
2566         close(fd);
2567         printf("child: released lock 0:4 on file %s.\n",
2568                 local_pathname );
2569         fflush(stdout);
2570         exit(0);
2571 }
2572
2573 static bool run_locktest9(int dummy)
2574 {
2575         struct cli_state *cli1;
2576         const char *fname = "\\lockt9.lck";
2577         uint16_t fnum;
2578         bool correct = False;
2579         int pipe_in[2], pipe_out[2];
2580         pid_t child_pid;
2581         char c = '\0';
2582         int ret;
2583         struct timeval start;
2584         double seconds;
2585         NTSTATUS status;
2586
2587         printf("starting locktest9\n");
2588
2589         if (local_path == NULL) {
2590                 d_fprintf(stderr, "locktest9 must be given a local path via -l <localpath>\n");
2591                 return false;
2592         }
2593
2594         if (pipe(pipe_in) == -1 || pipe(pipe_out) == -1) {
2595                 return false;
2596         }
2597
2598         child_pid = fork();
2599         if (child_pid == -1) {
2600                 return false;
2601         }
2602
2603         if (child_pid == 0) {
2604                 /* Child. */
2605                 do_local_lock(pipe_out[0], pipe_in[1]);
2606                 exit(0);
2607         }
2608
2609         close(pipe_out[0]);
2610         close(pipe_in[1]);
2611         pipe_out[0] = -1;
2612         pipe_in[1] = -1;
2613
2614         /* Parent. */
2615         ret = read(pipe_in[0], &c, 1);
2616         if (ret != 1) {
2617                 d_fprintf(stderr, "failed to read start signal from child. %s\n",
2618                         strerror(errno));
2619                 return false;
2620         }
2621
2622         if (!torture_open_connection(&cli1, 0)) {
2623                 return false;
2624         }
2625
2626         cli_sockopt(cli1, sockops);
2627
2628         status = cli_open(cli1, fname, O_RDWR, DENY_NONE,
2629                           &fnum);
2630         if (!NT_STATUS_IS_OK(status)) {
2631                 d_fprintf(stderr, "cli_open returned %s\n", nt_errstr(status));
2632                 return false;
2633         }
2634
2635         /* Ensure the child has the lock. */
2636         status = cli_lock32(cli1, fnum, 0, 4, 0, WRITE_LOCK);
2637         if (NT_STATUS_IS_OK(status)) {
2638                 d_fprintf(stderr, "Got the lock on range 0:4 - this should not happen !\n");
2639                 goto fail;
2640         } else {
2641                 d_printf("Child has the lock.\n");
2642         }
2643
2644         /* Tell the child to wait 5 seconds then exit. */
2645         ret = write(pipe_out[1], &c, 1);
2646         if (ret != 1) {
2647                 d_fprintf(stderr, "failed to send exit signal to child. %s\n",
2648                         strerror(errno));
2649                 goto fail;
2650         }
2651
2652         /* Wait 20 seconds for the lock. */
2653         alarm_fd = cli1->fd;
2654         CatchSignal(SIGALRM, alarm_handler_parent);
2655         alarm(20);
2656
2657         start = timeval_current();
2658
2659         status = cli_lock32(cli1, fnum, 0, 4, -1, WRITE_LOCK);
2660         if (!NT_STATUS_IS_OK(status)) {
2661                 d_fprintf(stderr, "Unable to apply write lock on range 0:4, error was "
2662                        "%s\n", nt_errstr(status));
2663                 goto fail_nofd;
2664         }
2665         alarm(0);
2666
2667         seconds = timeval_elapsed(&start);
2668
2669         printf("Parent got the lock after %.2f seconds.\n",
2670                 seconds);
2671
2672         status = cli_close(cli1, fnum);
2673         if (!NT_STATUS_IS_OK(status)) {
2674                 d_fprintf(stderr, "cli_close(fnum1) %s\n", nt_errstr(status));
2675                 goto fail;
2676         }
2677
2678         correct = true;
2679
2680 fail:
2681         cli_close(cli1, fnum);
2682         torture_close_connection(cli1);
2683
2684 fail_nofd:
2685
2686         printf("finished locktest9\n");
2687         return correct;
2688 }
2689
2690 /*
2691 test whether fnums and tids open on one VC are available on another (a major
2692 security hole)
2693 */
2694 static bool run_fdpasstest(int dummy)
2695 {
2696         struct cli_state *cli1, *cli2;
2697         const char *fname = "\\fdpass.tst";
2698         uint16_t fnum1;
2699         char buf[1024];
2700         NTSTATUS status;
2701
2702         if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
2703                 return False;
2704         }
2705         cli_sockopt(cli1, sockops);
2706         cli_sockopt(cli2, sockops);
2707
2708         printf("starting fdpasstest\n");
2709
2710         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2711
2712         status = cli_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
2713                           &fnum1);
2714         if (!NT_STATUS_IS_OK(status)) {
2715                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
2716                 return False;
2717         }
2718
2719         status = cli_writeall(cli1, fnum1, 0, (const uint8_t *)"hello world\n", 0,
2720                               13, NULL);
2721         if (!NT_STATUS_IS_OK(status)) {
2722                 printf("write failed (%s)\n", nt_errstr(status));
2723                 return False;
2724         }
2725
2726         cli2->vuid = cli1->vuid;
2727         cli2->cnum = cli1->cnum;
2728         cli2->pid = cli1->pid;
2729
2730         if (cli_read(cli2, fnum1, buf, 0, 13) == 13) {
2731                 printf("read succeeded! nasty security hole [%s]\n",
2732                        buf);
2733                 return False;
2734         }
2735
2736         cli_close(cli1, fnum1);
2737         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2738
2739         torture_close_connection(cli1);
2740         torture_close_connection(cli2);
2741
2742         printf("finished fdpasstest\n");
2743         return True;
2744 }
2745
2746 static bool run_fdsesstest(int dummy)
2747 {
2748         struct cli_state *cli;
2749         uint16 new_vuid;
2750         uint16 saved_vuid;
2751         uint16 new_cnum;
2752         uint16 saved_cnum;
2753         const char *fname = "\\fdsess.tst";
2754         const char *fname1 = "\\fdsess1.tst";
2755         uint16_t fnum1;
2756         uint16_t fnum2;
2757         char buf[1024];
2758         bool ret = True;
2759         NTSTATUS status;
2760
2761         if (!torture_open_connection(&cli, 0))
2762                 return False;
2763         cli_sockopt(cli, sockops);
2764
2765         if (!torture_cli_session_setup2(cli, &new_vuid))
2766                 return False;
2767
2768         saved_cnum = cli->cnum;
2769         if (!NT_STATUS_IS_OK(cli_tcon_andx(cli, share, "?????", "", 1)))
2770                 return False;
2771         new_cnum = cli->cnum;
2772         cli->cnum = saved_cnum;
2773
2774         printf("starting fdsesstest\n");
2775
2776         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2777         cli_unlink(cli, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2778
2779         status = cli_open(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
2780         if (!NT_STATUS_IS_OK(status)) {
2781                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
2782                 return False;
2783         }
2784
2785         status = cli_writeall(cli, fnum1, 0, (const uint8_t *)"hello world\n", 0, 13,
2786                               NULL);
2787         if (!NT_STATUS_IS_OK(status)) {
2788                 printf("write failed (%s)\n", nt_errstr(status));
2789                 return False;
2790         }
2791
2792         saved_vuid = cli->vuid;
2793         cli->vuid = new_vuid;
2794
2795         if (cli_read(cli, fnum1, buf, 0, 13) == 13) {
2796                 printf("read succeeded with different vuid! nasty security hole [%s]\n",
2797                        buf);
2798                 ret = False;
2799         }
2800         /* Try to open a file with different vuid, samba cnum. */
2801         if (NT_STATUS_IS_OK(cli_open(cli, fname1, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum2))) {
2802                 printf("create with different vuid, same cnum succeeded.\n");
2803                 cli_close(cli, fnum2);
2804                 cli_unlink(cli, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2805         } else {
2806                 printf("create with different vuid, same cnum failed.\n");
2807                 printf("This will cause problems with service clients.\n");
2808                 ret = False;
2809         }
2810
2811         cli->vuid = saved_vuid;
2812
2813         /* Try with same vuid, different cnum. */
2814         cli->cnum = new_cnum;
2815
2816         if (cli_read(cli, fnum1, buf, 0, 13) == 13) {
2817                 printf("read succeeded with different cnum![%s]\n",
2818                        buf);
2819                 ret = False;
2820         }
2821
2822         cli->cnum = saved_cnum;
2823         cli_close(cli, fnum1);
2824         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2825
2826         torture_close_connection(cli);
2827
2828         printf("finished fdsesstest\n");
2829         return ret;
2830 }
2831
2832 /*
2833   This test checks that 
2834
2835   1) the server does not allow an unlink on a file that is open
2836 */
2837 static bool run_unlinktest(int dummy)
2838 {
2839         struct cli_state *cli;
2840         const char *fname = "\\unlink.tst";
2841         uint16_t fnum;
2842         bool correct = True;
2843         NTSTATUS status;
2844
2845         if (!torture_open_connection(&cli, 0)) {
2846                 return False;
2847         }
2848
2849         cli_sockopt(cli, sockops);
2850
2851         printf("starting unlink test\n");
2852
2853         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2854
2855         cli_setpid(cli, 1);
2856
2857         status = cli_open(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
2858         if (!NT_STATUS_IS_OK(status)) {
2859                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
2860                 return False;
2861         }
2862
2863         status = cli_unlink(cli, fname,
2864                             FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2865         if (NT_STATUS_IS_OK(status)) {
2866                 printf("error: server allowed unlink on an open file\n");
2867                 correct = False;
2868         } else {
2869                 correct = check_error(__LINE__, cli, ERRDOS, ERRbadshare, 
2870                                       NT_STATUS_SHARING_VIOLATION);
2871         }
2872
2873         cli_close(cli, fnum);
2874         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2875
2876         if (!torture_close_connection(cli)) {
2877                 correct = False;
2878         }
2879
2880         printf("unlink test finished\n");
2881
2882         return correct;
2883 }
2884
2885
2886 /*
2887 test how many open files this server supports on the one socket
2888 */
2889 static bool run_maxfidtest(int dummy)
2890 {
2891         struct cli_state *cli;
2892         fstring fname;
2893         uint16_t fnums[0x11000];
2894         int i;
2895         int retries=4;
2896         bool correct = True;
2897         NTSTATUS status;
2898
2899         cli = current_cli;
2900
2901         if (retries <= 0) {
2902                 printf("failed to connect\n");
2903                 return False;
2904         }
2905
2906         cli_sockopt(cli, sockops);
2907
2908         for (i=0; i<0x11000; i++) {
2909                 slprintf(fname,sizeof(fname)-1,"\\maxfid.%d.%d", i,(int)getpid());
2910                 status = cli_open(cli, fname, O_RDWR|O_CREAT|O_TRUNC, DENY_NONE,
2911                                   &fnums[i]);
2912                 if (!NT_STATUS_IS_OK(status)) {
2913                         printf("open of %s failed (%s)\n", 
2914                                fname, nt_errstr(status));
2915                         printf("maximum fnum is %d\n", i);
2916                         break;
2917                 }
2918                 printf("%6d\r", i);
2919         }
2920         printf("%6d\n", i);
2921         i--;
2922
2923         printf("cleaning up\n");
2924         for (;i>=0;i--) {
2925                 slprintf(fname,sizeof(fname)-1,"\\maxfid.%d.%d", i,(int)getpid());
2926                 cli_close(cli, fnums[i]);
2927
2928                 status = cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2929                 if (!NT_STATUS_IS_OK(status)) {
2930                         printf("unlink of %s failed (%s)\n", 
2931                                fname, nt_errstr(status));
2932                         correct = False;
2933                 }
2934                 printf("%6d\r", i);
2935         }
2936         printf("%6d\n", 0);
2937
2938         printf("maxfid test finished\n");
2939         if (!torture_close_connection(cli)) {
2940                 correct = False;
2941         }
2942         return correct;
2943 }
2944
2945 /* generate a random buffer */
2946 static void rand_buf(char *buf, int len)
2947 {
2948         while (len--) {
2949                 *buf = (char)sys_random();
2950                 buf++;
2951         }
2952 }
2953
2954 /* send smb negprot commands, not reading the response */
2955 static bool run_negprot_nowait(int dummy)
2956 {
2957         struct tevent_context *ev;
2958         int i;
2959         struct cli_state *cli;
2960         bool correct = True;
2961
2962         printf("starting negprot nowait test\n");
2963
2964         ev = tevent_context_init(talloc_tos());
2965         if (ev == NULL) {
2966                 return false;
2967         }
2968
2969         if (!(cli = open_nbt_connection())) {
2970                 TALLOC_FREE(ev);
2971                 return False;
2972         }
2973
2974         for (i=0;i<50000;i++) {
2975                 struct tevent_req *req;
2976
2977                 req = cli_negprot_send(ev, ev, cli);
2978                 if (req == NULL) {
2979                         TALLOC_FREE(ev);
2980                         return false;
2981                 }
2982                 if (!tevent_req_poll(req, ev)) {
2983                         d_fprintf(stderr, "tevent_req_poll failed: %s\n",
2984                                   strerror(errno));
2985                         TALLOC_FREE(ev);
2986                         return false;
2987                 }
2988                 TALLOC_FREE(req);
2989         }
2990
2991         if (torture_close_connection(cli)) {
2992                 correct = False;
2993         }
2994
2995         printf("finished negprot nowait test\n");
2996
2997         return correct;
2998 }
2999
3000 /* send smb negprot commands, not reading the response */
3001 static bool run_bad_nbt_session(int dummy)
3002 {
3003         struct nmb_name called, calling;
3004         struct sockaddr_storage ss;
3005         NTSTATUS status;
3006         int fd;
3007         bool ret;
3008
3009         printf("starting bad nbt session test\n");
3010
3011         make_nmb_name(&calling, myname, 0x0);
3012         make_nmb_name(&called , host, 0x20);
3013
3014         if (!resolve_name(host, &ss, 0x20, true)) {
3015                 d_fprintf(stderr, "Could not resolve name %s\n", host);
3016                 return false;
3017         }
3018
3019         status = open_socket_out(&ss, 139, 10000, &fd);
3020         if (!NT_STATUS_IS_OK(status)) {
3021                 d_fprintf(stderr, "open_socket_out failed: %s\n",
3022                           nt_errstr(status));
3023                 return false;
3024         }
3025
3026         ret = cli_bad_session_request(fd, &calling, &called);
3027         close(fd);
3028         if (!ret) {
3029                 d_fprintf(stderr, "open_socket_out failed: %s\n",
3030                           nt_errstr(status));
3031                 return false;
3032         }
3033
3034         printf("finished bad nbt session test\n");
3035         return true;
3036 }
3037
3038 /* send random IPC commands */
3039 static bool run_randomipc(int dummy)
3040 {
3041         char *rparam = NULL;
3042         char *rdata = NULL;
3043         unsigned int rdrcnt,rprcnt;
3044         char param[1024];
3045         int api, param_len, i;
3046         struct cli_state *cli;
3047         bool correct = True;
3048         int count = 50000;
3049
3050         printf("starting random ipc test\n");
3051
3052         if (!torture_open_connection(&cli, 0)) {
3053                 return False;
3054         }
3055
3056         for (i=0;i<count;i++) {
3057                 api = sys_random() % 500;
3058                 param_len = (sys_random() % 64);
3059
3060                 rand_buf(param, param_len);
3061
3062                 SSVAL(param,0,api); 
3063
3064                 cli_api(cli, 
3065                         param, param_len, 8,  
3066                         NULL, 0, BUFFER_SIZE, 
3067                         &rparam, &rprcnt,     
3068                         &rdata, &rdrcnt);
3069                 if (i % 100 == 0) {
3070                         printf("%d/%d\r", i,count);
3071                 }
3072         }
3073         printf("%d/%d\n", i, count);
3074
3075         if (!torture_close_connection(cli)) {
3076                 correct = False;
3077         }
3078
3079         printf("finished random ipc test\n");
3080
3081         return correct;
3082 }
3083
3084
3085
3086 static void browse_callback(const char *sname, uint32 stype, 
3087                             const char *comment, void *state)
3088 {
3089         printf("\t%20.20s %08x %s\n", sname, stype, comment);
3090 }
3091
3092
3093
3094 /*
3095   This test checks the browse list code
3096
3097 */
3098 static bool run_browsetest(int dummy)
3099 {
3100         static struct cli_state *cli;
3101         bool correct = True;
3102
3103         printf("starting browse test\n");
3104
3105         if (!torture_open_connection(&cli, 0)) {
3106                 return False;
3107         }
3108
3109         printf("domain list:\n");
3110         cli_NetServerEnum(cli, cli->server_domain, 
3111                           SV_TYPE_DOMAIN_ENUM,
3112                           browse_callback, NULL);
3113
3114         printf("machine list:\n");
3115         cli_NetServerEnum(cli, cli->server_domain, 
3116                           SV_TYPE_ALL,
3117                           browse_callback, NULL);
3118
3119         if (!torture_close_connection(cli)) {
3120                 correct = False;
3121         }
3122
3123         printf("browse test finished\n");
3124
3125         return correct;
3126
3127 }
3128
3129
3130 /*
3131   This checks how the getatr calls works
3132 */
3133 static bool run_attrtest(int dummy)
3134 {
3135         struct cli_state *cli;
3136         uint16_t fnum;
3137         time_t t, t2;
3138         const char *fname = "\\attrib123456789.tst";
3139         bool correct = True;
3140         NTSTATUS status;
3141
3142         printf("starting attrib test\n");
3143
3144         if (!torture_open_connection(&cli, 0)) {
3145                 return False;
3146         }
3147
3148         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3149         cli_open(cli, fname, 
3150                         O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum);
3151         cli_close(cli, fnum);
3152
3153         status = cli_getatr(cli, fname, NULL, NULL, &t);
3154         if (!NT_STATUS_IS_OK(status)) {
3155                 printf("getatr failed (%s)\n", nt_errstr(status));
3156                 correct = False;
3157         }
3158
3159         if (abs(t - time(NULL)) > 60*60*24*10) {
3160                 printf("ERROR: SMBgetatr bug. time is %s",
3161                        ctime(&t));
3162                 t = time(NULL);
3163                 correct = True;
3164         }
3165
3166         t2 = t-60*60*24; /* 1 day ago */
3167
3168         status = cli_setatr(cli, fname, 0, t2);
3169         if (!NT_STATUS_IS_OK(status)) {
3170                 printf("setatr failed (%s)\n", nt_errstr(status));
3171                 correct = True;
3172         }
3173
3174         status = cli_getatr(cli, fname, NULL, NULL, &t);
3175         if (!NT_STATUS_IS_OK(status)) {
3176                 printf("getatr failed (%s)\n", nt_errstr(status));
3177                 correct = True;
3178         }
3179
3180         if (t != t2) {
3181                 printf("ERROR: getatr/setatr bug. times are\n%s",
3182                        ctime(&t));
3183                 printf("%s", ctime(&t2));
3184                 correct = True;
3185         }
3186
3187         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3188
3189         if (!torture_close_connection(cli)) {
3190                 correct = False;
3191         }
3192
3193         printf("attrib test finished\n");
3194
3195         return correct;
3196 }
3197
3198
3199 /*
3200   This checks a couple of trans2 calls
3201 */
3202 static bool run_trans2test(int dummy)
3203 {
3204         struct cli_state *cli;
3205         uint16_t fnum;
3206         SMB_OFF_T size;
3207         time_t c_time, a_time, m_time;
3208         struct timespec c_time_ts, a_time_ts, m_time_ts, w_time_ts, m_time2_ts;
3209         const char *fname = "\\trans2.tst";
3210         const char *dname = "\\trans2";
3211         const char *fname2 = "\\trans2\\trans2.tst";
3212         char *pname;
3213         bool correct = True;
3214         NTSTATUS status;
3215         uint32_t fs_attr;
3216
3217         printf("starting trans2 test\n");
3218
3219         if (!torture_open_connection(&cli, 0)) {
3220                 return False;
3221         }
3222
3223         status = cli_get_fs_attr_info(cli, &fs_attr);
3224         if (!NT_STATUS_IS_OK(status)) {
3225                 printf("ERROR: cli_get_fs_attr_info returned %s\n",
3226                        nt_errstr(status));
3227                 correct = false;
3228         }
3229
3230         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3231         cli_open(cli, fname, O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum);
3232         status = cli_qfileinfo_basic(cli, fnum, NULL, &size, &c_time_ts,
3233                                      &a_time_ts, &w_time_ts, &m_time_ts, NULL);
3234         if (!NT_STATUS_IS_OK(status)) {
3235                 printf("ERROR: qfileinfo failed (%s)\n", nt_errstr(status));
3236                 correct = False;
3237         }
3238
3239         status = cli_qfilename(cli, fnum, talloc_tos(), &pname);
3240         if (!NT_STATUS_IS_OK(status)) {
3241                 printf("ERROR: qfilename failed (%s)\n", nt_errstr(status));
3242                 correct = False;
3243         }
3244
3245         if (strcmp(pname, fname)) {
3246                 printf("qfilename gave different name? [%s] [%s]\n",
3247                        fname, pname);
3248                 correct = False;
3249         }
3250
3251         cli_close(cli, fnum);
3252
3253         sleep(2);
3254
3255         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3256         status = cli_open(cli, fname, O_RDWR | O_CREAT | O_TRUNC, DENY_NONE,
3257                           &fnum);
3258         if (!NT_STATUS_IS_OK(status)) {
3259                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
3260                 return False;
3261         }
3262         cli_close(cli, fnum);
3263
3264         status = cli_qpathinfo1(cli, fname, &c_time, &a_time, &m_time, &size,
3265                                 NULL);
3266         if (!NT_STATUS_IS_OK(status)) {
3267                 printf("ERROR: qpathinfo failed (%s)\n", nt_errstr(status));
3268                 correct = False;
3269         } else {
3270                 if (c_time != m_time) {
3271                         printf("create time=%s", ctime(&c_time));
3272                         printf("modify time=%s", ctime(&m_time));
3273                         printf("This system appears to have sticky create times\n");
3274                 }
3275                 if (a_time % (60*60) == 0) {
3276                         printf("access time=%s", ctime(&a_time));
3277                         printf("This system appears to set a midnight access time\n");
3278                         correct = False;
3279                 }
3280
3281                 if (abs(m_time - time(NULL)) > 60*60*24*7) {
3282                         printf("ERROR: totally incorrect times - maybe word reversed? mtime=%s", ctime(&m_time));
3283                         correct = False;
3284                 }
3285         }
3286
3287
3288         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3289         cli_open(cli, fname, 
3290                         O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum);
3291         cli_close(cli, fnum);
3292         status = cli_qpathinfo2(cli, fname, &c_time_ts, &a_time_ts, &w_time_ts,
3293                                 &m_time_ts, &size, NULL, NULL);
3294         if (!NT_STATUS_IS_OK(status)) {
3295                 printf("ERROR: qpathinfo2 failed (%s)\n", nt_errstr(status));
3296                 correct = False;
3297         } else {
3298                 if (w_time_ts.tv_sec < 60*60*24*2) {
3299                         printf("write time=%s", ctime(&w_time_ts.tv_sec));
3300                         printf("This system appears to set a initial 0 write time\n");
3301                         correct = False;
3302                 }
3303         }
3304
3305         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3306
3307
3308         /* check if the server updates the directory modification time
3309            when creating a new file */
3310         status = cli_mkdir(cli, dname);
3311         if (!NT_STATUS_IS_OK(status)) {
3312                 printf("ERROR: mkdir failed (%s)\n", nt_errstr(status));
3313                 correct = False;
3314         }
3315         sleep(3);
3316         status = cli_qpathinfo2(cli, "\\trans2\\", &c_time_ts, &a_time_ts,
3317                                 &w_time_ts, &m_time_ts, &size, NULL, NULL);
3318         if (!NT_STATUS_IS_OK(status)) {
3319                 printf("ERROR: qpathinfo2 failed (%s)\n", nt_errstr(status));
3320                 correct = False;
3321         }
3322
3323         cli_open(cli, fname2, 
3324                         O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum);
3325         cli_writeall(cli, fnum,  0, (uint8_t *)&fnum, 0, sizeof(fnum), NULL);
3326         cli_close(cli, fnum);
3327         status = cli_qpathinfo2(cli, "\\trans2\\", &c_time_ts, &a_time_ts,
3328                                 &w_time_ts, &m_time2_ts, &size, NULL, NULL);
3329         if (!NT_STATUS_IS_OK(status)) {
3330                 printf("ERROR: qpathinfo2 failed (%s)\n", nt_errstr(status));
3331                 correct = False;
3332         } else {
3333                 if (memcmp(&m_time_ts, &m_time2_ts, sizeof(struct timespec))
3334                     == 0) {
3335                         printf("This system does not update directory modification times\n");
3336                         correct = False;
3337                 }
3338         }
3339         cli_unlink(cli, fname2, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3340         cli_rmdir(cli, dname);
3341
3342         if (!torture_close_connection(cli)) {
3343                 correct = False;
3344         }
3345
3346         printf("trans2 test finished\n");
3347
3348         return correct;
3349 }
3350
3351 /*
3352   This checks new W2K calls.
3353 */
3354
3355 static NTSTATUS new_trans(struct cli_state *pcli, int fnum, int level)
3356 {
3357         uint8_t *buf = NULL;
3358         uint32 len;
3359         NTSTATUS status;
3360
3361         status = cli_qfileinfo(talloc_tos(), pcli, fnum, level, 0,
3362                                pcli->max_xmit, NULL, &buf, &len);
3363         if (!NT_STATUS_IS_OK(status)) {
3364                 printf("ERROR: qfileinfo (%d) failed (%s)\n", level,
3365                        nt_errstr(status));
3366         } else {
3367                 printf("qfileinfo: level %d, len = %u\n", level, len);
3368                 dump_data(0, (uint8 *)buf, len);
3369                 printf("\n");
3370         }
3371         TALLOC_FREE(buf);
3372         return status;
3373 }
3374
3375 static bool run_w2ktest(int dummy)
3376 {
3377         struct cli_state *cli;
3378         uint16_t fnum;
3379         const char *fname = "\\w2ktest\\w2k.tst";
3380         int level;
3381         bool correct = True;
3382
3383         printf("starting w2k test\n");
3384
3385         if (!torture_open_connection(&cli, 0)) {
3386                 return False;
3387         }
3388
3389         cli_open(cli, fname, 
3390                         O_RDWR | O_CREAT , DENY_NONE, &fnum);
3391
3392         for (level = 1004; level < 1040; level++) {
3393                 new_trans(cli, fnum, level);
3394         }
3395
3396         cli_close(cli, fnum);
3397
3398         if (!torture_close_connection(cli)) {
3399                 correct = False;
3400         }
3401
3402         printf("w2k test finished\n");
3403
3404         return correct;
3405 }
3406
3407
3408 /*
3409   this is a harness for some oplock tests
3410  */
3411 static bool run_oplock1(int dummy)
3412 {
3413         struct cli_state *cli1;
3414         const char *fname = "\\lockt1.lck";
3415         uint16_t fnum1;
3416         bool correct = True;
3417         NTSTATUS status;
3418
3419         printf("starting oplock test 1\n");
3420
3421         if (!torture_open_connection(&cli1, 0)) {
3422                 return False;
3423         }
3424
3425         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3426
3427         cli_sockopt(cli1, sockops);
3428
3429         cli1->use_oplocks = True;
3430
3431         status = cli_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
3432                           &fnum1);
3433         if (!NT_STATUS_IS_OK(status)) {
3434                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
3435                 return False;
3436         }
3437
3438         cli1->use_oplocks = False;
3439
3440         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3441         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3442
3443         status = cli_close(cli1, fnum1);
3444         if (!NT_STATUS_IS_OK(status)) {
3445                 printf("close2 failed (%s)\n", nt_errstr(status));
3446                 return False;
3447         }
3448
3449         status = cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3450         if (!NT_STATUS_IS_OK(status)) {
3451                 printf("unlink failed (%s)\n", nt_errstr(status));
3452                 return False;
3453         }
3454
3455         if (!torture_close_connection(cli1)) {
3456                 correct = False;
3457         }
3458
3459         printf("finished oplock test 1\n");
3460
3461         return correct;
3462 }
3463
3464 static bool run_oplock2(int dummy)
3465 {
3466         struct cli_state *cli1, *cli2;
3467         const char *fname = "\\lockt2.lck";
3468         uint16_t fnum1, fnum2;
3469         int saved_use_oplocks = use_oplocks;
3470         char buf[4];
3471         bool correct = True;
3472         volatile bool *shared_correct;
3473         NTSTATUS status;
3474
3475         shared_correct = (volatile bool *)shm_setup(sizeof(bool));
3476         *shared_correct = True;
3477
3478         use_level_II_oplocks = True;
3479         use_oplocks = True;
3480
3481         printf("starting oplock test 2\n");
3482
3483         if (!torture_open_connection(&cli1, 0)) {
3484                 use_level_II_oplocks = False;
3485                 use_oplocks = saved_use_oplocks;
3486                 return False;
3487         }
3488
3489         cli1->use_oplocks = True;
3490         cli1->use_level_II_oplocks = True;
3491
3492         if (!torture_open_connection(&cli2, 1)) {
3493                 use_level_II_oplocks = False;
3494                 use_oplocks = saved_use_oplocks;
3495                 return False;
3496         }
3497
3498         cli2->use_oplocks = True;
3499         cli2->use_level_II_oplocks = True;
3500
3501         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3502
3503         cli_sockopt(cli1, sockops);
3504         cli_sockopt(cli2, sockops);
3505
3506         status = cli_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
3507                           &fnum1);
3508         if (!NT_STATUS_IS_OK(status)) {
3509                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
3510                 return False;
3511         }
3512
3513         /* Don't need the globals any more. */
3514         use_level_II_oplocks = False;
3515         use_oplocks = saved_use_oplocks;
3516
3517         if (fork() == 0) {
3518                 /* Child code */
3519                 status = cli_open(cli2, fname, O_RDWR, DENY_NONE, &fnum2);
3520                 if (!NT_STATUS_IS_OK(status)) {
3521                         printf("second open of %s failed (%s)\n", fname, nt_errstr(status));
3522                         *shared_correct = False;
3523                         exit(0);
3524                 }
3525
3526                 sleep(2);
3527
3528                 status = cli_close(cli2, fnum2);
3529                 if (!NT_STATUS_IS_OK(status)) {
3530                         printf("close2 failed (%s)\n", nt_errstr(status));
3531                         *shared_correct = False;
3532                 }
3533
3534                 exit(0);
3535         }
3536
3537         sleep(2);
3538
3539         /* Ensure cli1 processes the break. Empty file should always return 0
3540          * bytes.  */
3541
3542         if (cli_read(cli1, fnum1, buf, 0, 4) != 0) {
3543                 printf("read on fnum1 failed (%s)\n", cli_errstr(cli1));
3544                 correct = False;
3545         }
3546
3547         /* Should now be at level II. */
3548         /* Test if sending a write locks causes a break to none. */
3549         status = cli_lock32(cli1, fnum1, 0, 4, 0, READ_LOCK);
3550         if (!NT_STATUS_IS_OK(status)) {
3551                 printf("lock failed (%s)\n", nt_errstr(status));
3552                 correct = False;
3553         }
3554
3555         cli_unlock(cli1, fnum1, 0, 4);
3556
3557         sleep(2);
3558
3559         status = cli_lock32(cli1, fnum1, 0, 4, 0, WRITE_LOCK);
3560         if (!NT_STATUS_IS_OK(status)) {
3561                 printf("lock failed (%s)\n", nt_errstr(status));
3562                 correct = False;
3563         }
3564
3565         cli_unlock(cli1, fnum1, 0, 4);
3566
3567         sleep(2);
3568
3569         cli_read(cli1, fnum1, buf, 0, 4);
3570
3571         status = cli_close(cli1, fnum1);
3572         if (!NT_STATUS_IS_OK(status)) {
3573                 printf("close1 failed (%s)\n", nt_errstr(status));
3574                 correct = False;
3575         }
3576
3577         sleep(4);
3578
3579         status = cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3580         if (!NT_STATUS_IS_OK(status)) {
3581                 printf("unlink failed (%s)\n", nt_errstr(status));
3582                 correct = False;
3583         }
3584
3585         if (!torture_close_connection(cli1)) {
3586                 correct = False;
3587         }
3588
3589         if (!*shared_correct) {
3590                 correct = False;
3591         }
3592
3593         printf("finished oplock test 2\n");
3594
3595         return correct;
3596 }
3597
3598 struct oplock4_state {
3599         struct tevent_context *ev;
3600         struct cli_state *cli;
3601         bool *got_break;
3602         uint16_t *fnum2;
3603 };
3604
3605 static void oplock4_got_break(struct tevent_req *req);
3606 static void oplock4_got_open(struct tevent_req *req);
3607
3608 static bool run_oplock4(int dummy)
3609 {
3610         struct tevent_context *ev;
3611         struct cli_state *cli1, *cli2;
3612         struct tevent_req *oplock_req, *open_req;
3613         const char *fname = "\\lockt4.lck";
3614         const char *fname_ln = "\\lockt4_ln.lck";
3615         uint16_t fnum1, fnum2;
3616         int saved_use_oplocks = use_oplocks;
3617         NTSTATUS status;
3618         bool correct = true;
3619
3620         bool got_break;
3621
3622         struct oplock4_state *state;
3623
3624         printf("starting oplock test 4\n");
3625
3626         if (!torture_open_connection(&cli1, 0)) {
3627                 use_level_II_oplocks = false;
3628                 use_oplocks = saved_use_oplocks;
3629                 return false;
3630         }
3631
3632         if (!torture_open_connection(&cli2, 1)) {
3633                 use_level_II_oplocks = false;
3634                 use_oplocks = saved_use_oplocks;
3635                 return false;
3636         }
3637
3638         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3639         cli_unlink(cli1, fname_ln, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3640
3641         cli_sockopt(cli1, sockops);
3642         cli_sockopt(cli2, sockops);
3643
3644         /* Create the file. */
3645         status = cli_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
3646                           &fnum1);
3647         if (!NT_STATUS_IS_OK(status)) {
3648                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
3649                 return false;
3650         }
3651
3652         status = cli_close(cli1, fnum1);
3653         if (!NT_STATUS_IS_OK(status)) {
3654                 printf("close1 failed (%s)\n", nt_errstr(status));
3655                 return false;
3656         }
3657
3658         /* Now create a hardlink. */
3659         status = cli_nt_hardlink(cli1, fname, fname_ln);
3660         if (!NT_STATUS_IS_OK(status)) {
3661                 printf("nt hardlink failed (%s)\n", nt_errstr(status));
3662                 return false;
3663         }
3664
3665         /* Prove that opening hardlinks cause deny modes to conflict. */
3666         status = cli_open(cli1, fname, O_RDWR, DENY_ALL, &fnum1);
3667         if (!NT_STATUS_IS_OK(status)) {
3668                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
3669                 return false;
3670         }
3671
3672         status = cli_open(cli1, fname_ln, O_RDWR, DENY_NONE, &fnum2);
3673         if (NT_STATUS_IS_OK(status)) {
3674                 printf("open of %s succeeded - should fail with sharing violation.\n",
3675                         fname_ln);
3676                 return false;
3677         }
3678
3679         if (!NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
3680                 printf("open of %s should fail with sharing violation. Got %s\n",
3681                         fname_ln, nt_errstr(status));
3682                 return false;
3683         }
3684
3685         status = cli_close(cli1, fnum1);
3686         if (!NT_STATUS_IS_OK(status)) {
3687                 printf("close1 failed (%s)\n", nt_errstr(status));
3688                 return false;
3689         }
3690
3691         cli1->use_oplocks = true;
3692         cli1->use_level_II_oplocks = true;
3693
3694         cli2->use_oplocks = true;
3695         cli2->use_level_II_oplocks = true;
3696
3697         status = cli_open(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
3698         if (!NT_STATUS_IS_OK(status)) {
3699                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
3700                 return false;
3701         }
3702
3703         ev = tevent_context_init(talloc_tos());
3704         if (ev == NULL) {
3705                 printf("tevent_req_create failed\n");
3706                 return false;
3707         }
3708
3709         state = talloc(ev, struct oplock4_state);
3710         if (state == NULL) {
3711                 printf("talloc failed\n");
3712                 return false;
3713         }
3714         state->ev = ev;
3715         state->cli = cli1;
3716         state->got_break = &got_break;
3717         state->fnum2 = &fnum2;
3718
3719         oplock_req = cli_smb_oplock_break_waiter_send(
3720                 talloc_tos(), ev, cli1);
3721         if (oplock_req == NULL) {
3722                 printf("cli_smb_oplock_break_waiter_send failed\n");
3723                 return false;
3724         }
3725         tevent_req_set_callback(oplock_req, oplock4_got_break, state);
3726
3727         open_req = cli_open_send(
3728                 talloc_tos(), ev, cli2, fname_ln, O_RDWR, DENY_NONE);
3729         if (oplock_req == NULL) {
3730                 printf("cli_open_send failed\n");
3731                 return false;
3732         }
3733         tevent_req_set_callback(open_req, oplock4_got_open, state);
3734
3735         got_break = false;
3736         fnum2 = 0xffff;
3737
3738         while (!got_break || fnum2 == 0xffff) {
3739                 int ret;
3740                 ret = tevent_loop_once(ev);
3741                 if (ret == -1) {
3742                         printf("tevent_loop_once failed: %s\n",
3743                                strerror(errno));
3744                         return false;
3745                 }
3746         }
3747
3748         status = cli_close(cli2, fnum2);
3749         if (!NT_STATUS_IS_OK(status)) {
3750                 printf("close2 failed (%s)\n", nt_errstr(status));
3751                 correct = false;
3752         }
3753
3754         status = cli_close(cli1, fnum1);
3755         if (!NT_STATUS_IS_OK(status)) {
3756                 printf("close1 failed (%s)\n", nt_errstr(status));
3757                 correct = false;
3758         }
3759
3760         status = cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3761         if (!NT_STATUS_IS_OK(status)) {
3762                 printf("unlink failed (%s)\n", nt_errstr(status));
3763                 correct = false;
3764         }
3765
3766         status = cli_unlink(cli1, fname_ln, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3767         if (!NT_STATUS_IS_OK(status)) {
3768                 printf("unlink failed (%s)\n", nt_errstr(status));
3769                 correct = false;
3770         }
3771
3772         if (!torture_close_connection(cli1)) {
3773                 correct = false;
3774         }
3775
3776         if (!got_break) {
3777                 correct = false;
3778         }
3779
3780         printf("finished oplock test 4\n");
3781
3782         return correct;
3783 }
3784
3785 static void oplock4_got_break(struct tevent_req *req)
3786 {
3787         struct oplock4_state *state = tevent_req_callback_data(
3788                 req, struct oplock4_state);
3789         uint16_t fnum;
3790         uint8_t level;
3791         NTSTATUS status;
3792
3793         status = cli_smb_oplock_break_waiter_recv(req, &fnum, &level);
3794         TALLOC_FREE(req);
3795         if (!NT_STATUS_IS_OK(status)) {
3796                 printf("cli_smb_oplock_break_waiter_recv returned %s\n",
3797                        nt_errstr(status));
3798                 return;
3799         }
3800         *state->got_break = true;
3801
3802         req = cli_oplock_ack_send(state, state->ev, state->cli, fnum,
3803                                   NO_OPLOCK);
3804         if (req == NULL) {
3805                 printf("cli_oplock_ack_send failed\n");
3806                 return;
3807         }
3808 }
3809
3810 static void oplock4_got_open(struct tevent_req *req)
3811 {
3812         struct oplock4_state *state = tevent_req_callback_data(
3813                 req, struct oplock4_state);
3814         NTSTATUS status;
3815
3816         status = cli_open_recv(req, state->fnum2);
3817         if (!NT_STATUS_IS_OK(status)) {
3818                 printf("cli_open_recv returned %s\n", nt_errstr(status));
3819                 *state->fnum2 = 0xffff;
3820         }
3821 }
3822
3823 /*
3824   Test delete on close semantics.
3825  */
3826 static bool run_deletetest(int dummy)
3827 {
3828         struct cli_state *cli1 = NULL;
3829         struct cli_state *cli2 = NULL;
3830         const char *fname = "\\delete.file";
3831         uint16_t fnum1 = (uint16_t)-1;
3832         uint16_t fnum2 = (uint16_t)-1;
3833         bool correct = True;
3834         NTSTATUS status;
3835
3836         printf("starting delete test\n");
3837
3838         if (!torture_open_connection(&cli1, 0)) {