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