s3: smbtorture: Add new SMB2-DIR-FSYNC test to show behavior of FSYNC on directories.
[nivanova/samba-autobuild/.git] / source3 / torture / torture.c
1 /* 
2    Unix SMB/CIFS implementation.
3    SMB torture tester
4    Copyright (C) Andrew Tridgell 1997-1998
5    Copyright (C) Jeremy Allison 2009
6
7    This program is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 3 of the License, or
10    (at your option) any later version.
11
12    This program is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16
17    You should have received a copy of the GNU General Public License
18    along with this program.  If not, see <http://www.gnu.org/licenses/>.
19 */
20
21 #include "includes.h"
22 #include "system/shmem.h"
23 #include "libsmb/namequery.h"
24 #include "wbc_async.h"
25 #include "torture/proto.h"
26 #include "libcli/security/security.h"
27 #include "tldap.h"
28 #include "tldap_util.h"
29 #include "../librpc/gen_ndr/svcctl.h"
30 #include "../lib/util/memcache.h"
31 #include "nsswitch/winbind_client.h"
32 #include "dbwrap/dbwrap.h"
33 #include "dbwrap/dbwrap_open.h"
34 #include "dbwrap/dbwrap_rbt.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 #include "lib/util/sys_rw_data.h"
45 #include "lib/util/base64.h"
46 #include "lib/util/time.h"
47
48 extern char *optarg;
49 extern int optind;
50
51 fstring host, workgroup, share, password, username, myname;
52 struct cli_credentials *torture_creds;
53 static const char *sockops="TCP_NODELAY";
54 int torture_nprocs=1;
55 static int port_to_use=0;
56 int torture_numops=100;
57 int torture_blocksize=1024*1024;
58 static int procnum; /* records process count number when forking */
59 static struct cli_state *current_cli;
60 static fstring randomfname;
61 static bool use_oplocks;
62 static bool use_level_II_oplocks;
63 static const char *client_txt = "client_oplocks.txt";
64 static bool disable_spnego;
65 static bool use_kerberos;
66 static bool force_dos_errors;
67 static fstring multishare_conn_fname;
68 static bool use_multishare_conn = False;
69 static bool do_encrypt;
70 static const char *local_path = NULL;
71 static enum smb_signing_setting signing_state = SMB_SIGNING_DEFAULT;
72 char *test_filename;
73
74 bool torture_showall = False;
75
76 static double create_procs(bool (*fn)(int), bool *result);
77
78 /********************************************************************
79  Ensure a connection is encrypted.
80 ********************************************************************/
81
82 static bool force_cli_encryption(struct cli_state *c,
83                         const char *sharename)
84 {
85         uint16_t major, minor;
86         uint32_t caplow, caphigh;
87         NTSTATUS status;
88
89         if (!SERVER_HAS_UNIX_CIFS(c)) {
90                 d_printf("Encryption required and "
91                         "server that doesn't support "
92                         "UNIX extensions - failing connect\n");
93                         return false;
94         }
95
96         status = cli_unix_extensions_version(c, &major, &minor, &caplow,
97                                              &caphigh);
98         if (!NT_STATUS_IS_OK(status)) {
99                 d_printf("Encryption required and "
100                         "can't get UNIX CIFS extensions "
101                         "version from server: %s\n", nt_errstr(status));
102                 return false;
103         }
104
105         if (!(caplow & CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP)) {
106                 d_printf("Encryption required and "
107                         "share %s doesn't support "
108                         "encryption.\n", sharename);
109                 return false;
110         }
111
112         status = cli_smb1_setup_encryption(c, torture_creds);
113         if (!NT_STATUS_IS_OK(status)) {
114                 d_printf("Encryption required and "
115                         "setup failed with error %s.\n",
116                         nt_errstr(status));
117                 return false;
118         }
119
120         return true;
121 }
122
123
124 static struct cli_state *open_nbt_connection(void)
125 {
126         struct cli_state *c;
127         NTSTATUS status;
128         int flags = 0;
129
130         if (disable_spnego) {
131                 flags |= CLI_FULL_CONNECTION_DONT_SPNEGO;
132         }
133
134         if (use_oplocks) {
135                 flags |= CLI_FULL_CONNECTION_OPLOCKS;
136         }
137
138         if (use_level_II_oplocks) {
139                 flags |= CLI_FULL_CONNECTION_LEVEL_II_OPLOCKS;
140         }
141
142         if (use_kerberos) {
143                 flags |= CLI_FULL_CONNECTION_USE_KERBEROS;
144         }
145
146         if (force_dos_errors) {
147                 flags |= CLI_FULL_CONNECTION_FORCE_DOS_ERRORS;
148         }
149
150         status = cli_connect_nb(host, NULL, port_to_use, 0x20, myname,
151                                 signing_state, flags, &c);
152         if (!NT_STATUS_IS_OK(status)) {
153                 printf("Failed to connect with %s. Error %s\n", host, nt_errstr(status) );
154                 return NULL;
155         }
156
157         cli_set_timeout(c, 120000); /* set a really long timeout (2 minutes) */
158
159         return c;
160 }
161
162 /****************************************************************************
163  Send a corrupt session request. See rfc1002.txt 4.3 and 4.3.2.
164 ****************************************************************************/
165
166 static bool cli_bad_session_request(int fd,
167                          struct nmb_name *calling, struct nmb_name *called)
168 {
169         TALLOC_CTX *frame;
170         uint8_t len_buf[4];
171         struct iovec iov[3];
172         ssize_t len;
173         uint8_t *inbuf;
174         int err;
175         bool ret = false;
176         uint8_t message_type;
177         uint8_t error;
178         struct tevent_context *ev;
179         struct tevent_req *req;
180
181         frame = talloc_stackframe();
182
183         iov[0].iov_base = len_buf;
184         iov[0].iov_len  = sizeof(len_buf);
185
186         /* put in the destination name */
187
188         iov[1].iov_base = name_mangle(talloc_tos(), called->name,
189                                       called->name_type);
190         if (iov[1].iov_base == NULL) {
191                 goto fail;
192         }
193         iov[1].iov_len = name_len((unsigned char *)iov[1].iov_base,
194                                   talloc_get_size(iov[1].iov_base));
195
196         /* and my name */
197
198         iov[2].iov_base = name_mangle(talloc_tos(), calling->name,
199                                       calling->name_type);
200         if (iov[2].iov_base == NULL) {
201                 goto fail;
202         }
203         iov[2].iov_len = name_len((unsigned char *)iov[2].iov_base,
204                                   talloc_get_size(iov[2].iov_base));
205
206         /* Deliberately corrupt the name len (first byte) */
207         *((uint8_t *)iov[2].iov_base) = 100;
208
209         /* send a session request (RFC 1002) */
210         /* setup the packet length
211          * Remove four bytes from the length count, since the length
212          * field in the NBT Session Service header counts the number
213          * of bytes which follow.  The cli_send_smb() function knows
214          * about this and accounts for those four bytes.
215          * CRH.
216          */
217
218         _smb_setlen(len_buf, iov[1].iov_len + iov[2].iov_len);
219         SCVAL(len_buf,0,0x81);
220
221         len = write_data_iov(fd, iov, 3);
222         if (len == -1) {
223                 goto fail;
224         }
225
226         ev = samba_tevent_context_init(frame);
227         if (ev == NULL) {
228                 goto fail;
229         }
230         req = read_smb_send(frame, ev, fd);
231         if (req == NULL) {
232                 goto fail;
233         }
234         if (!tevent_req_poll(req, ev)) {
235                 goto fail;
236         }
237         len = read_smb_recv(req, talloc_tos(), &inbuf, &err);
238         if (len == -1) {
239                 errno = err;
240                 goto fail;
241         }
242         TALLOC_FREE(ev);
243
244         message_type = CVAL(inbuf, 0);
245         if (message_type != 0x83) {
246                 d_fprintf(stderr, "Expected msg type 0x83, got 0x%2.2x\n",
247                           message_type);
248                 goto fail;
249         }
250
251         if (smb_len(inbuf) != 1) {
252                 d_fprintf(stderr, "Expected smb_len 1, got %d\n",
253                           (int)smb_len(inbuf));
254                 goto fail;
255         }
256
257         error = CVAL(inbuf, 4);
258         if (error !=  0x82) {
259                 d_fprintf(stderr, "Expected error 0x82, got %d\n",
260                           (int)error);
261                 goto fail;
262         }
263
264         ret = true;
265 fail:
266         TALLOC_FREE(frame);
267         return ret;
268 }
269
270 /* Insert a NULL at the first separator of the given path and return a pointer
271  * to the remainder of the string.
272  */
273 static char *
274 terminate_path_at_separator(char * path)
275 {
276         char * p;
277
278         if (!path) {
279                 return NULL;
280         }
281
282         if ((p = strchr_m(path, '/'))) {
283                 *p = '\0';
284                 return p + 1;
285         }
286
287         if ((p = strchr_m(path, '\\'))) {
288                 *p = '\0';
289                 return p + 1;
290         }
291
292         /* No separator. */
293         return NULL;
294 }
295
296 /*
297   parse a //server/share type UNC name
298 */
299 bool smbcli_parse_unc(const char *unc_name, TALLOC_CTX *mem_ctx,
300                       char **hostname, char **sharename)
301 {
302         char *p;
303
304         *hostname = *sharename = NULL;
305
306         if (strncmp(unc_name, "\\\\", 2) &&
307             strncmp(unc_name, "//", 2)) {
308                 return False;
309         }
310
311         *hostname = talloc_strdup(mem_ctx, &unc_name[2]);
312         p = terminate_path_at_separator(*hostname);
313
314         if (p && *p) {
315                 *sharename = talloc_strdup(mem_ctx, p);
316                 terminate_path_at_separator(*sharename);
317         }
318
319         if (*hostname && *sharename) {
320                 return True;
321         }
322
323         TALLOC_FREE(*hostname);
324         TALLOC_FREE(*sharename);
325         return False;
326 }
327
328 static bool torture_open_connection_share(struct cli_state **c,
329                                    const char *hostname, 
330                                    const char *sharename,
331                                    int flags)
332 {
333         NTSTATUS status;
334
335         status = cli_full_connection_creds(c,
336                                            myname,
337                                            hostname,
338                                            NULL, /* dest_ss */
339                                            port_to_use,
340                                            sharename,
341                                            "?????",
342                                            torture_creds,
343                                            flags,
344                                            signing_state);
345         if (!NT_STATUS_IS_OK(status)) {
346                 printf("failed to open share connection: //%s/%s port:%d - %s\n",
347                         hostname, sharename, port_to_use, nt_errstr(status));
348                 return False;
349         }
350
351         cli_set_timeout(*c, 120000); /* set a really long timeout (2 minutes) */
352
353         if (do_encrypt) {
354                 return force_cli_encryption(*c,
355                                         sharename);
356         }
357         return True;
358 }
359
360 bool torture_open_connection_flags(struct cli_state **c, int conn_index, int flags)
361 {
362         char **unc_list = NULL;
363         int num_unc_names = 0;
364         bool result;
365
366         if (use_multishare_conn==True) {
367                 char *h, *s;
368                 unc_list = file_lines_load(multishare_conn_fname, &num_unc_names, 0, NULL);
369                 if (!unc_list || num_unc_names <= 0) {
370                         printf("Failed to load unc names list from '%s'\n", multishare_conn_fname);
371                         exit(1);
372                 }
373
374                 if (!smbcli_parse_unc(unc_list[conn_index % num_unc_names],
375                                       NULL, &h, &s)) {
376                         printf("Failed to parse UNC name %s\n",
377                                unc_list[conn_index % num_unc_names]);
378                         TALLOC_FREE(unc_list);
379                         exit(1);
380                 }
381
382                 result = torture_open_connection_share(c, h, s, flags);
383
384                 /* h, s were copied earlier */
385                 TALLOC_FREE(unc_list);
386                 return result;
387         }
388
389         return torture_open_connection_share(c, host, share, flags);
390 }
391
392 bool torture_open_connection(struct cli_state **c, int conn_index)
393 {
394         int flags = CLI_FULL_CONNECTION_FORCE_SMB1;
395
396         if (use_oplocks) {
397                 flags |= CLI_FULL_CONNECTION_OPLOCKS;
398         }
399         if (use_level_II_oplocks) {
400                 flags |= CLI_FULL_CONNECTION_LEVEL_II_OPLOCKS;
401         }
402
403         return torture_open_connection_flags(c, conn_index, flags);
404 }
405
406 bool torture_init_connection(struct cli_state **pcli)
407 {
408         struct cli_state *cli;
409
410         cli = open_nbt_connection();
411         if (cli == NULL) {
412                 return false;
413         }
414
415         *pcli = cli;
416         return true;
417 }
418
419 bool torture_cli_session_setup2(struct cli_state *cli, uint16_t *new_vuid)
420 {
421         uint16_t old_vuid = cli_state_get_uid(cli);
422         NTSTATUS status;
423         bool ret;
424
425         cli_state_set_uid(cli, 0);
426         status = cli_session_setup_creds(cli, torture_creds);
427         ret = NT_STATUS_IS_OK(status);
428         *new_vuid = cli_state_get_uid(cli);
429         cli_state_set_uid(cli, old_vuid);
430         return ret;
431 }
432
433
434 bool torture_close_connection(struct cli_state *c)
435 {
436         bool ret = True;
437         NTSTATUS status;
438
439         status = cli_tdis(c);
440         if (!NT_STATUS_IS_OK(status)) {
441                 printf("tdis failed (%s)\n", nt_errstr(status));
442                 ret = False;
443         }
444
445         cli_shutdown(c);
446
447         return ret;
448 }
449
450
451 /* check if the server produced the expected dos or nt error code */
452 static bool check_both_error(int line, NTSTATUS status,
453                              uint8_t eclass, uint32_t ecode, NTSTATUS nterr)
454 {
455         if (NT_STATUS_IS_DOS(status)) {
456                 uint8_t cclass;
457                 uint32_t num;
458
459                 /* Check DOS error */
460                 cclass = NT_STATUS_DOS_CLASS(status);
461                 num = NT_STATUS_DOS_CODE(status);
462
463                 if (eclass != cclass || ecode != num) {
464                         printf("unexpected error code class=%d code=%d\n",
465                                (int)cclass, (int)num);
466                         printf(" expected %d/%d %s (line=%d)\n",
467                                (int)eclass, (int)ecode, nt_errstr(nterr), line);
468                         return false;
469                 }
470         } else {
471                 /* Check NT error */
472                 if (!NT_STATUS_EQUAL(nterr, status)) {
473                         printf("unexpected error code %s\n",
474                                 nt_errstr(status));
475                         printf(" expected %s (line=%d)\n",
476                                 nt_errstr(nterr), line);
477                         return false;
478                 }
479         }
480
481         return true;
482 }
483
484
485 /* check if the server produced the expected error code */
486 static bool check_error(int line, NTSTATUS status,
487                         uint8_t eclass, uint32_t ecode, NTSTATUS nterr)
488 {
489         if (NT_STATUS_IS_DOS(status)) {
490                 uint8_t cclass;
491                 uint32_t num;
492
493                 /* Check DOS error */
494
495                 cclass = NT_STATUS_DOS_CLASS(status);
496                 num = NT_STATUS_DOS_CODE(status);
497
498                 if (eclass != cclass || ecode != num) {
499                         printf("unexpected error code class=%d code=%d\n", 
500                                (int)cclass, (int)num);
501                         printf(" expected %d/%d %s (line=%d)\n", 
502                                (int)eclass, (int)ecode, nt_errstr(nterr),
503                                line);
504                         return False;
505                 }
506
507         } else {
508                 /* Check NT error */
509
510                 if (NT_STATUS_V(nterr) != NT_STATUS_V(status)) {
511                         printf("unexpected error code %s\n",
512                                nt_errstr(status));
513                         printf(" expected %s (line=%d)\n", nt_errstr(nterr),
514                                line);
515                         return False;
516                 }
517         }
518
519         return True;
520 }
521
522
523 static bool wait_lock(struct cli_state *c, int fnum, uint32_t offset, uint32_t len)
524 {
525         NTSTATUS status;
526
527         status = cli_lock32(c, fnum, offset, len, -1, WRITE_LOCK);
528
529         while (!NT_STATUS_IS_OK(status)) {
530                 if (!check_both_error(__LINE__, status, ERRDOS,
531                                       ERRlock, NT_STATUS_LOCK_NOT_GRANTED)) {
532                         return false;
533                 }
534
535                 status = cli_lock32(c, fnum, offset, len, -1, WRITE_LOCK);
536         }
537
538         return true;
539 }
540
541
542 static bool rw_torture(struct cli_state *c)
543 {
544         const char *lockfname = "\\torture.lck";
545         fstring fname;
546         uint16_t fnum;
547         uint16_t fnum2;
548         pid_t pid2, pid = getpid();
549         int i, j;
550         char buf[1024];
551         bool correct = True;
552         size_t nread = 0;
553         NTSTATUS status;
554
555         memset(buf, '\0', sizeof(buf));
556
557         status = cli_openx(c, lockfname, O_RDWR | O_CREAT | O_EXCL, 
558                          DENY_NONE, &fnum2);
559         if (!NT_STATUS_IS_OK(status)) {
560                 status = cli_openx(c, lockfname, O_RDWR, DENY_NONE, &fnum2);
561         }
562         if (!NT_STATUS_IS_OK(status)) {
563                 printf("open of %s failed (%s)\n",
564                        lockfname, nt_errstr(status));
565                 return False;
566         }
567
568         for (i=0;i<torture_numops;i++) {
569                 unsigned n = (unsigned)sys_random()%10;
570
571                 if (i % 10 == 0) {
572                         printf("%d\r", i); fflush(stdout);
573                 }
574                 slprintf(fname, sizeof(fstring) - 1, "\\torture.%u", n);
575
576                 if (!wait_lock(c, fnum2, n*sizeof(int), sizeof(int))) {
577                         return False;
578                 }
579
580                 status = cli_openx(c, fname, O_RDWR | O_CREAT | O_TRUNC,
581                                   DENY_ALL, &fnum);
582                 if (!NT_STATUS_IS_OK(status)) {
583                         printf("open failed (%s)\n", nt_errstr(status));
584                         correct = False;
585                         break;
586                 }
587
588                 status = cli_writeall(c, fnum, 0, (uint8_t *)&pid, 0,
589                                       sizeof(pid), NULL);
590                 if (!NT_STATUS_IS_OK(status)) {
591                         printf("write failed (%s)\n", nt_errstr(status));
592                         correct = False;
593                 }
594
595                 for (j=0;j<50;j++) {
596                         status = cli_writeall(c, fnum, 0, (uint8_t *)buf,
597                                               sizeof(pid)+(j*sizeof(buf)),
598                                               sizeof(buf), NULL);
599                         if (!NT_STATUS_IS_OK(status)) {
600                                 printf("write failed (%s)\n",
601                                        nt_errstr(status));
602                                 correct = False;
603                         }
604                 }
605
606                 pid2 = 0;
607
608                 status = cli_read(c, fnum, (char *)&pid2, 0, sizeof(pid),
609                                   &nread);
610                 if (!NT_STATUS_IS_OK(status)) {
611                         printf("read failed (%s)\n", nt_errstr(status));
612                         correct = false;
613                 } else if (nread != sizeof(pid)) {
614                         printf("read/write compare failed: "
615                                "recv %ld req %ld\n", (unsigned long)nread,
616                                (unsigned long)sizeof(pid));
617                         correct = false;
618                 }
619
620                 if (pid2 != pid) {
621                         printf("data corruption!\n");
622                         correct = False;
623                 }
624
625                 status = cli_close(c, fnum);
626                 if (!NT_STATUS_IS_OK(status)) {
627                         printf("close failed (%s)\n", nt_errstr(status));
628                         correct = False;
629                 }
630
631                 status = cli_unlink(c, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
632                 if (!NT_STATUS_IS_OK(status)) {
633                         printf("unlink failed (%s)\n", nt_errstr(status));
634                         correct = False;
635                 }
636
637                 status = cli_unlock(c, fnum2, n*sizeof(int), sizeof(int));
638                 if (!NT_STATUS_IS_OK(status)) {
639                         printf("unlock failed (%s)\n", nt_errstr(status));
640                         correct = False;
641                 }
642         }
643
644         cli_close(c, fnum2);
645         cli_unlink(c, lockfname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
646
647         printf("%d\n", i);
648
649         return correct;
650 }
651
652 static bool run_torture(int dummy)
653 {
654         struct cli_state *cli;
655         bool ret;
656
657         cli = current_cli;
658
659         smbXcli_conn_set_sockopt(cli->conn, sockops);
660
661         ret = rw_torture(cli);
662
663         if (!torture_close_connection(cli)) {
664                 ret = False;
665         }
666
667         return ret;
668 }
669
670 static bool rw_torture3(struct cli_state *c, char *lockfname)
671 {
672         uint16_t fnum = (uint16_t)-1;
673         unsigned int i = 0;
674         char buf[131072];
675         char buf_rd[131072];
676         unsigned count;
677         unsigned countprev = 0;
678         size_t sent = 0;
679         bool correct = True;
680         NTSTATUS status = NT_STATUS_OK;
681
682         srandom(1);
683         for (i = 0; i < sizeof(buf); i += sizeof(uint32_t))
684         {
685                 SIVAL(buf, i, sys_random());
686         }
687
688         if (procnum == 0)
689         {
690                 status = cli_unlink(
691                         c, lockfname,
692                         FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
693                 if (!NT_STATUS_IS_OK(status)) {
694                         printf("unlink failed (%s) (normal, this file should "
695                                "not exist)\n", nt_errstr(status));
696                 }
697
698                 status = cli_openx(c, lockfname, O_RDWR | O_CREAT | O_EXCL,
699                                   DENY_NONE, &fnum);
700                 if (!NT_STATUS_IS_OK(status)) {
701                         printf("first open read/write of %s failed (%s)\n",
702                                         lockfname, nt_errstr(status));
703                         return False;
704                 }
705         }
706         else
707         {
708                 for (i = 0; i < 500 && fnum == (uint16_t)-1; i++)
709                 {
710                         status = cli_openx(c, lockfname, O_RDONLY, 
711                                          DENY_NONE, &fnum);
712                         if (NT_STATUS_IS_OK(status)) {
713                                 break;
714                         }
715                         smb_msleep(10);
716                 }
717                 if (!NT_STATUS_IS_OK(status)) {
718                         printf("second open read-only of %s failed (%s)\n",
719                                         lockfname, nt_errstr(status));
720                         return False;
721                 }
722         }
723
724         i = 0;
725         for (count = 0; count < sizeof(buf); count += sent)
726         {
727                 if (count >= countprev) {
728                         printf("%d %8d\r", i, count);
729                         fflush(stdout);
730                         i++;
731                         countprev += (sizeof(buf) / 20);
732                 }
733
734                 if (procnum == 0)
735                 {
736                         sent = ((unsigned)sys_random()%(20))+ 1;
737                         if (sent > sizeof(buf) - count)
738                         {
739                                 sent = sizeof(buf) - count;
740                         }
741
742                         status = cli_writeall(c, fnum, 0, (uint8_t *)buf+count,
743                                               count, sent, NULL);
744                         if (!NT_STATUS_IS_OK(status)) {
745                                 printf("write failed (%s)\n",
746                                        nt_errstr(status));
747                                 correct = False;
748                         }
749                 }
750                 else
751                 {
752                         status = cli_read(c, fnum, buf_rd+count, count,
753                                           sizeof(buf)-count, &sent);
754                         if(!NT_STATUS_IS_OK(status)) {
755                                 printf("read failed offset:%d size:%ld (%s)\n",
756                                        count, (unsigned long)sizeof(buf)-count,
757                                        nt_errstr(status));
758                                 correct = False;
759                                 sent = 0;
760                         } else if (sent > 0) {
761                                 if (memcmp(buf_rd+count, buf+count, sent) != 0)
762                                 {
763                                         printf("read/write compare failed\n");
764                                         printf("offset: %d req %ld recvd %ld\n", count, (unsigned long)sizeof(buf)-count, (unsigned long)sent);
765                                         correct = False;
766                                         break;
767                                 }
768                         }
769                 }
770
771         }
772
773         status = cli_close(c, fnum);
774         if (!NT_STATUS_IS_OK(status)) {
775                 printf("close failed (%s)\n", nt_errstr(status));
776                 correct = False;
777         }
778
779         return correct;
780 }
781
782 static bool rw_torture2(struct cli_state *c1, struct cli_state *c2)
783 {
784         const char *lockfname = "\\torture2.lck";
785         uint16_t fnum1;
786         uint16_t fnum2;
787         int i;
788         char buf[131072];
789         char buf_rd[131072];
790         bool correct = True;
791         size_t bytes_read;
792         NTSTATUS status;
793
794         status = cli_unlink(c1, lockfname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
795         if (!NT_STATUS_IS_OK(status)) {
796                 printf("unlink failed (%s) (normal, this file should not exist)\n", nt_errstr(status));
797         }
798
799         status = cli_openx(c1, lockfname, O_RDWR | O_CREAT | O_EXCL,
800                           DENY_NONE, &fnum1);
801         if (!NT_STATUS_IS_OK(status)) {
802                 printf("first open read/write of %s failed (%s)\n",
803                                 lockfname, nt_errstr(status));
804                 return False;
805         }
806
807         status = cli_openx(c2, lockfname, O_RDONLY, DENY_NONE, &fnum2);
808         if (!NT_STATUS_IS_OK(status)) {
809                 printf("second open read-only of %s failed (%s)\n",
810                                 lockfname, nt_errstr(status));
811                 cli_close(c1, fnum1);
812                 return False;
813         }
814
815         for (i = 0; i < torture_numops; i++)
816         {
817                 size_t buf_size = ((unsigned)sys_random()%(sizeof(buf)-1))+ 1;
818                 if (i % 10 == 0) {
819                         printf("%d\r", i); fflush(stdout);
820                 }
821
822                 generate_random_buffer((unsigned char *)buf, buf_size);
823
824                 status = cli_writeall(c1, fnum1, 0, (uint8_t *)buf, 0,
825                                       buf_size, NULL);
826                 if (!NT_STATUS_IS_OK(status)) {
827                         printf("write failed (%s)\n", nt_errstr(status));
828                         correct = False;
829                         break;
830                 }
831
832                 status = cli_read(c2, fnum2, buf_rd, 0, buf_size, &bytes_read);
833                 if(!NT_STATUS_IS_OK(status)) {
834                         printf("read failed (%s)\n", nt_errstr(status));
835                         correct = false;
836                         break;
837                 } else if (bytes_read != buf_size) {
838                         printf("read failed\n");
839                         printf("read %ld, expected %ld\n",
840                                (unsigned long)bytes_read,
841                                (unsigned long)buf_size); 
842                         correct = False;
843                         break;
844                 }
845
846                 if (memcmp(buf_rd, buf, buf_size) != 0)
847                 {
848                         printf("read/write compare failed\n");
849                         correct = False;
850                         break;
851                 }
852         }
853
854         status = cli_close(c2, fnum2);
855         if (!NT_STATUS_IS_OK(status)) {
856                 printf("close failed (%s)\n", nt_errstr(status));
857                 correct = False;
858         }
859
860         status = cli_close(c1, fnum1);
861         if (!NT_STATUS_IS_OK(status)) {
862                 printf("close failed (%s)\n", nt_errstr(status));
863                 correct = False;
864         }
865
866         status = cli_unlink(c1, lockfname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
867         if (!NT_STATUS_IS_OK(status)) {
868                 printf("unlink failed (%s)\n", nt_errstr(status));
869                 correct = False;
870         }
871
872         return correct;
873 }
874
875 static bool run_readwritetest(int dummy)
876 {
877         struct cli_state *cli1, *cli2;
878         bool test1, test2 = False;
879
880         if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
881                 return False;
882         }
883         smbXcli_conn_set_sockopt(cli1->conn, sockops);
884         smbXcli_conn_set_sockopt(cli2->conn, sockops);
885
886         printf("starting readwritetest\n");
887
888         test1 = rw_torture2(cli1, cli2);
889         printf("Passed readwritetest v1: %s\n", BOOLSTR(test1));
890
891         if (test1) {
892                 test2 = rw_torture2(cli1, cli1);
893                 printf("Passed readwritetest v2: %s\n", BOOLSTR(test2));
894         }
895
896         if (!torture_close_connection(cli1)) {
897                 test1 = False;
898         }
899
900         if (!torture_close_connection(cli2)) {
901                 test2 = False;
902         }
903
904         return (test1 && test2);
905 }
906
907 static bool run_readwritemulti(int dummy)
908 {
909         struct cli_state *cli;
910         bool test;
911
912         cli = current_cli;
913
914         smbXcli_conn_set_sockopt(cli->conn, sockops);
915
916         printf("run_readwritemulti: fname %s\n", randomfname);
917         test = rw_torture3(cli, randomfname);
918
919         if (!torture_close_connection(cli)) {
920                 test = False;
921         }
922
923         return test;
924 }
925
926 static bool run_readwritelarge_internal(void)
927 {
928         static struct cli_state *cli1;
929         uint16_t fnum1;
930         const char *lockfname = "\\large.dat";
931         off_t fsize;
932         char buf[126*1024];
933         bool correct = True;
934         NTSTATUS status;
935
936         if (!torture_open_connection(&cli1, 0)) {
937                 return False;
938         }
939         smbXcli_conn_set_sockopt(cli1->conn, sockops);
940         memset(buf,'\0',sizeof(buf));
941
942         printf("starting readwritelarge_internal\n");
943
944         cli_unlink(cli1, lockfname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
945
946         status = cli_openx(cli1, lockfname, O_RDWR | O_CREAT | O_EXCL,
947                           DENY_NONE, &fnum1);
948         if (!NT_STATUS_IS_OK(status)) {
949                 printf("open read/write of %s failed (%s)\n", lockfname, nt_errstr(status));
950                 return False;
951         }
952
953         cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 0, sizeof(buf), NULL);
954
955         status = cli_qfileinfo_basic(cli1, fnum1, NULL, &fsize, NULL, NULL,
956                                      NULL, NULL, NULL);
957         if (!NT_STATUS_IS_OK(status)) {
958                 printf("qfileinfo failed (%s)\n", nt_errstr(status));
959                 correct = False;
960         }
961
962         if (fsize == sizeof(buf))
963                 printf("readwritelarge_internal test 1 succeeded (size = %lx)\n",
964                        (unsigned long)fsize);
965         else {
966                 printf("readwritelarge_internal test 1 failed (size = %lx)\n",
967                        (unsigned long)fsize);
968                 correct = False;
969         }
970
971         status = cli_close(cli1, fnum1);
972         if (!NT_STATUS_IS_OK(status)) {
973                 printf("close failed (%s)\n", nt_errstr(status));
974                 correct = False;
975         }
976
977         status = cli_unlink(cli1, lockfname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
978         if (!NT_STATUS_IS_OK(status)) {
979                 printf("unlink failed (%s)\n", nt_errstr(status));
980                 correct = False;
981         }
982
983         status = cli_openx(cli1, lockfname, O_RDWR | O_CREAT | O_EXCL,
984                           DENY_NONE, &fnum1);
985         if (!NT_STATUS_IS_OK(status)) {
986                 printf("open read/write of %s failed (%s)\n", lockfname, nt_errstr(status));
987                 return False;
988         }
989
990         cli_smbwrite(cli1, fnum1, buf, 0, sizeof(buf), NULL);
991
992         status = cli_qfileinfo_basic(cli1, fnum1, NULL, &fsize, NULL, NULL,
993                                      NULL, NULL, NULL);
994         if (!NT_STATUS_IS_OK(status)) {
995                 printf("qfileinfo failed (%s)\n", nt_errstr(status));
996                 correct = False;
997         }
998
999         if (fsize == sizeof(buf))
1000                 printf("readwritelarge_internal test 2 succeeded (size = %lx)\n",
1001                        (unsigned long)fsize);
1002         else {
1003                 printf("readwritelarge_internal test 2 failed (size = %lx)\n",
1004                        (unsigned long)fsize);
1005                 correct = False;
1006         }
1007
1008 #if 0
1009         /* ToDo - set allocation. JRA */
1010         if(!cli_set_allocation_size(cli1, fnum1, 0)) {
1011                 printf("set allocation size to zero failed (%s)\n", cli_errstr(&cli1));
1012                 return False;
1013         }
1014         if (!cli_qfileinfo_basic(cli1, fnum1, NULL, &fsize, NULL, NULL, NULL,
1015                                  NULL, NULL)) {
1016                 printf("qfileinfo failed (%s)\n", cli_errstr(cli1));
1017                 correct = False;
1018         }
1019         if (fsize != 0)
1020                 printf("readwritelarge test 3 (truncate test) succeeded (size = %x)\n", fsize);
1021 #endif
1022
1023         status = cli_close(cli1, fnum1);
1024         if (!NT_STATUS_IS_OK(status)) {
1025                 printf("close failed (%s)\n", nt_errstr(status));
1026                 correct = False;
1027         }
1028
1029         if (!torture_close_connection(cli1)) {
1030                 correct = False;
1031         }
1032         return correct;
1033 }
1034
1035 static bool run_readwritelarge(int dummy)
1036 {
1037         return run_readwritelarge_internal();
1038 }
1039
1040 static bool run_readwritelarge_signtest(int dummy)
1041 {
1042         bool ret;
1043         signing_state = SMB_SIGNING_REQUIRED;
1044         ret = run_readwritelarge_internal();
1045         signing_state = SMB_SIGNING_DEFAULT;
1046         return ret;
1047 }
1048
1049 int line_count = 0;
1050 int nbio_id;
1051
1052 #define ival(s) strtol(s, NULL, 0)
1053
1054 /* run a test that simulates an approximate netbench client load */
1055 static bool run_netbench(int client)
1056 {
1057         struct cli_state *cli;
1058         int i;
1059         char line[1024];
1060         char cname[20];
1061         FILE *f;
1062         const char *params[20];
1063         bool correct = True;
1064
1065         cli = current_cli;
1066
1067         nbio_id = client;
1068
1069         smbXcli_conn_set_sockopt(cli->conn, sockops);
1070
1071         nb_setup(cli);
1072
1073         slprintf(cname,sizeof(cname)-1, "client%d", client);
1074
1075         f = fopen(client_txt, "r");
1076
1077         if (!f) {
1078                 perror(client_txt);
1079                 return False;
1080         }
1081
1082         while (fgets(line, sizeof(line)-1, f)) {
1083                 char *saveptr;
1084                 line_count++;
1085
1086                 line[strlen(line)-1] = 0;
1087
1088                 /* printf("[%d] %s\n", line_count, line); */
1089
1090                 all_string_sub(line,"client1", cname, sizeof(line));
1091
1092                 /* parse the command parameters */
1093                 params[0] = strtok_r(line, " ", &saveptr);
1094                 i = 0;
1095                 while (params[i]) params[++i] = strtok_r(NULL, " ", &saveptr);
1096
1097                 params[i] = "";
1098
1099                 if (i < 2) continue;
1100
1101                 if (!strncmp(params[0],"SMB", 3)) {
1102                         printf("ERROR: You are using a dbench 1 load file\n");
1103                         exit(1);
1104                 }
1105
1106                 if (!strcmp(params[0],"NTCreateX")) {
1107                         nb_createx(params[1], ival(params[2]), ival(params[3]), 
1108                                    ival(params[4]));
1109                 } else if (!strcmp(params[0],"Close")) {
1110                         nb_close(ival(params[1]));
1111                 } else if (!strcmp(params[0],"Rename")) {
1112                         nb_rename(params[1], params[2]);
1113                 } else if (!strcmp(params[0],"Unlink")) {
1114                         nb_unlink(params[1]);
1115                 } else if (!strcmp(params[0],"Deltree")) {
1116                         nb_deltree(params[1]);
1117                 } else if (!strcmp(params[0],"Rmdir")) {
1118                         nb_rmdir(params[1]);
1119                 } else if (!strcmp(params[0],"QUERY_PATH_INFORMATION")) {
1120                         nb_qpathinfo(params[1]);
1121                 } else if (!strcmp(params[0],"QUERY_FILE_INFORMATION")) {
1122                         nb_qfileinfo(ival(params[1]));
1123                 } else if (!strcmp(params[0],"QUERY_FS_INFORMATION")) {
1124                         nb_qfsinfo(ival(params[1]));
1125                 } else if (!strcmp(params[0],"FIND_FIRST")) {
1126                         nb_findfirst(params[1]);
1127                 } else if (!strcmp(params[0],"WriteX")) {
1128                         nb_writex(ival(params[1]), 
1129                                   ival(params[2]), ival(params[3]), ival(params[4]));
1130                 } else if (!strcmp(params[0],"ReadX")) {
1131                         nb_readx(ival(params[1]), 
1132                                   ival(params[2]), ival(params[3]), ival(params[4]));
1133                 } else if (!strcmp(params[0],"Flush")) {
1134                         nb_flush(ival(params[1]));
1135                 } else {
1136                         printf("Unknown operation %s\n", params[0]);
1137                         exit(1);
1138                 }
1139         }
1140         fclose(f);
1141
1142         nb_cleanup();
1143
1144         if (!torture_close_connection(cli)) {
1145                 correct = False;
1146         }
1147
1148         return correct;
1149 }
1150
1151
1152 /* run a test that simulates an approximate netbench client load */
1153 static bool run_nbench(int dummy)
1154 {
1155         double t;
1156         bool correct = True;
1157
1158         nbio_shmem(torture_nprocs);
1159
1160         nbio_id = -1;
1161
1162         signal(SIGALRM, nb_alarm);
1163         alarm(1);
1164         t = create_procs(run_netbench, &correct);
1165         alarm(0);
1166
1167         printf("\nThroughput %g MB/sec\n", 
1168                1.0e-6 * nbio_total() / t);
1169         return correct;
1170 }
1171
1172
1173 /*
1174   This test checks for two things:
1175
1176   1) correct support for retaining locks over a close (ie. the server
1177      must not use posix semantics)
1178   2) support for lock timeouts
1179  */
1180 static bool run_locktest1(int dummy)
1181 {
1182         struct cli_state *cli1, *cli2;
1183         const char *fname = "\\lockt1.lck";
1184         uint16_t fnum1, fnum2, fnum3;
1185         time_t t1, t2;
1186         unsigned lock_timeout;
1187         NTSTATUS status;
1188
1189         if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
1190                 return False;
1191         }
1192         smbXcli_conn_set_sockopt(cli1->conn, sockops);
1193         smbXcli_conn_set_sockopt(cli2->conn, sockops);
1194
1195         printf("starting locktest1\n");
1196
1197         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1198
1199         status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
1200                           &fnum1);
1201         if (!NT_STATUS_IS_OK(status)) {
1202                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
1203                 return False;
1204         }
1205
1206         status = cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum2);
1207         if (!NT_STATUS_IS_OK(status)) {
1208                 printf("open2 of %s failed (%s)\n", fname, nt_errstr(status));
1209                 return False;
1210         }
1211
1212         status = cli_openx(cli2, fname, O_RDWR, DENY_NONE, &fnum3);
1213         if (!NT_STATUS_IS_OK(status)) {
1214                 printf("open3 of %s failed (%s)\n", fname, nt_errstr(status));
1215                 return False;
1216         }
1217
1218         status = cli_lock32(cli1, fnum1, 0, 4, 0, WRITE_LOCK);
1219         if (!NT_STATUS_IS_OK(status)) {
1220                 printf("lock1 failed (%s)\n", nt_errstr(status));
1221                 return false;
1222         }
1223
1224         status = cli_lock32(cli2, fnum3, 0, 4, 0, WRITE_LOCK);
1225         if (NT_STATUS_IS_OK(status)) {
1226                 printf("lock2 succeeded! This is a locking bug\n");
1227                 return false;
1228         } else {
1229                 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1230                                       NT_STATUS_LOCK_NOT_GRANTED)) {
1231                         return false;
1232                 }
1233         }
1234
1235         lock_timeout = (1 + (random() % 20));
1236         printf("Testing lock timeout with timeout=%u\n", lock_timeout);
1237         t1 = time(NULL);
1238         status = cli_lock32(cli2, fnum3, 0, 4, lock_timeout * 1000, WRITE_LOCK);
1239         if (NT_STATUS_IS_OK(status)) {
1240                 printf("lock3 succeeded! This is a locking bug\n");
1241                 return false;
1242         } else {
1243                 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1244                                       NT_STATUS_FILE_LOCK_CONFLICT)) {
1245                         return false;
1246                 }
1247         }
1248         t2 = time(NULL);
1249
1250         if (ABS(t2 - t1) < lock_timeout-1) {
1251                 printf("error: This server appears not to support timed lock requests\n");
1252         }
1253
1254         printf("server slept for %u seconds for a %u second timeout\n",
1255                (unsigned int)(t2-t1), lock_timeout);
1256
1257         status = cli_close(cli1, fnum2);
1258         if (!NT_STATUS_IS_OK(status)) {
1259                 printf("close1 failed (%s)\n", nt_errstr(status));
1260                 return False;
1261         }
1262
1263         status = cli_lock32(cli2, fnum3, 0, 4, 0, WRITE_LOCK);
1264         if (NT_STATUS_IS_OK(status)) {
1265                 printf("lock4 succeeded! This is a locking bug\n");
1266                 return false;
1267         } else {
1268                 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1269                                       NT_STATUS_FILE_LOCK_CONFLICT)) {
1270                         return false;
1271                 }
1272         }
1273
1274         status = cli_close(cli1, fnum1);
1275         if (!NT_STATUS_IS_OK(status)) {
1276                 printf("close2 failed (%s)\n", nt_errstr(status));
1277                 return False;
1278         }
1279
1280         status = cli_close(cli2, fnum3);
1281         if (!NT_STATUS_IS_OK(status)) {
1282                 printf("close3 failed (%s)\n", nt_errstr(status));
1283                 return False;
1284         }
1285
1286         status = cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1287         if (!NT_STATUS_IS_OK(status)) {
1288                 printf("unlink failed (%s)\n", nt_errstr(status));
1289                 return False;
1290         }
1291
1292
1293         if (!torture_close_connection(cli1)) {
1294                 return False;
1295         }
1296
1297         if (!torture_close_connection(cli2)) {
1298                 return False;
1299         }
1300
1301         printf("Passed locktest1\n");
1302         return True;
1303 }
1304
1305 /*
1306   this checks to see if a secondary tconx can use open files from an
1307   earlier tconx
1308  */
1309 static bool run_tcon_test(int dummy)
1310 {
1311         static struct cli_state *cli;
1312         const char *fname = "\\tcontest.tmp";
1313         uint16_t fnum1;
1314         uint32_t cnum1, cnum2, cnum3;
1315         struct smbXcli_tcon *orig_tcon = NULL;
1316         uint16_t vuid1, vuid2;
1317         char buf[4];
1318         bool ret = True;
1319         NTSTATUS status;
1320
1321         memset(buf, '\0', sizeof(buf));
1322
1323         if (!torture_open_connection(&cli, 0)) {
1324                 return False;
1325         }
1326         smbXcli_conn_set_sockopt(cli->conn, sockops);
1327
1328         printf("starting tcontest\n");
1329
1330         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1331
1332         status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
1333         if (!NT_STATUS_IS_OK(status)) {
1334                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
1335                 return False;
1336         }
1337
1338         cnum1 = cli_state_get_tid(cli);
1339         vuid1 = cli_state_get_uid(cli);
1340
1341         status = cli_writeall(cli, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
1342         if (!NT_STATUS_IS_OK(status)) {
1343                 printf("initial write failed (%s)", nt_errstr(status));
1344                 return False;
1345         }
1346
1347         orig_tcon = cli_state_save_tcon(cli);
1348         if (orig_tcon == NULL) {
1349                 return false;
1350         }
1351
1352         status = cli_tree_connect_creds(cli, share, "?????", torture_creds);
1353         if (!NT_STATUS_IS_OK(status)) {
1354                 printf("%s refused 2nd tree connect (%s)\n", host,
1355                        nt_errstr(status));
1356                 cli_shutdown(cli);
1357                 return False;
1358         }
1359
1360         cnum2 = cli_state_get_tid(cli);
1361         cnum3 = MAX(cnum1, cnum2) + 1; /* any invalid number */
1362         vuid2 = cli_state_get_uid(cli) + 1;
1363
1364         /* try a write with the wrong tid */
1365         cli_state_set_tid(cli, cnum2);
1366
1367         status = cli_writeall(cli, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
1368         if (NT_STATUS_IS_OK(status)) {
1369                 printf("* server allows write with wrong TID\n");
1370                 ret = False;
1371         } else {
1372                 printf("server fails write with wrong TID : %s\n",
1373                        nt_errstr(status));
1374         }
1375
1376
1377         /* try a write with an invalid tid */
1378         cli_state_set_tid(cli, cnum3);
1379
1380         status = cli_writeall(cli, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
1381         if (NT_STATUS_IS_OK(status)) {
1382                 printf("* server allows write with invalid TID\n");
1383                 ret = False;
1384         } else {
1385                 printf("server fails write with invalid TID : %s\n",
1386                        nt_errstr(status));
1387         }
1388
1389         /* try a write with an invalid vuid */
1390         cli_state_set_uid(cli, vuid2);
1391         cli_state_set_tid(cli, cnum1);
1392
1393         status = cli_writeall(cli, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
1394         if (NT_STATUS_IS_OK(status)) {
1395                 printf("* server allows write with invalid VUID\n");
1396                 ret = False;
1397         } else {
1398                 printf("server fails write with invalid VUID : %s\n",
1399                        nt_errstr(status));
1400         }
1401
1402         cli_state_set_tid(cli, cnum1);
1403         cli_state_set_uid(cli, vuid1);
1404
1405         status = cli_close(cli, fnum1);
1406         if (!NT_STATUS_IS_OK(status)) {
1407                 printf("close failed (%s)\n", nt_errstr(status));
1408                 return False;
1409         }
1410
1411         cli_state_set_tid(cli, cnum2);
1412
1413         status = cli_tdis(cli);
1414         if (!NT_STATUS_IS_OK(status)) {
1415                 printf("secondary tdis failed (%s)\n", nt_errstr(status));
1416                 return False;
1417         }
1418
1419         cli_state_restore_tcon(cli, orig_tcon);
1420
1421         cli_state_set_tid(cli, cnum1);
1422
1423         if (!torture_close_connection(cli)) {
1424                 return False;
1425         }
1426
1427         return ret;
1428 }
1429
1430
1431 /*
1432  checks for old style tcon support
1433  */
1434 static bool run_tcon2_test(int dummy)
1435 {
1436         static struct cli_state *cli;
1437         uint16_t cnum, max_xmit;
1438         char *service;
1439         NTSTATUS status;
1440
1441         if (!torture_open_connection(&cli, 0)) {
1442                 return False;
1443         }
1444         smbXcli_conn_set_sockopt(cli->conn, sockops);
1445
1446         printf("starting tcon2 test\n");
1447
1448         if (asprintf(&service, "\\\\%s\\%s", host, share) == -1) {
1449                 return false;
1450         }
1451
1452         status = cli_raw_tcon(cli, service, password, "?????", &max_xmit, &cnum);
1453
1454         SAFE_FREE(service);
1455
1456         if (!NT_STATUS_IS_OK(status)) {
1457                 printf("tcon2 failed : %s\n", nt_errstr(status));
1458         } else {
1459                 printf("tcon OK : max_xmit=%d cnum=%d\n",
1460                        (int)max_xmit, (int)cnum);
1461         }
1462
1463         if (!torture_close_connection(cli)) {
1464                 return False;
1465         }
1466
1467         printf("Passed tcon2 test\n");
1468         return True;
1469 }
1470
1471 static bool tcon_devtest(struct cli_state *cli,
1472                          const char *myshare, const char *devtype,
1473                          const char *return_devtype,
1474                          NTSTATUS expected_error)
1475 {
1476         NTSTATUS status;
1477         bool ret;
1478
1479         status = cli_tree_connect_creds(cli, myshare, devtype, torture_creds);
1480
1481         if (NT_STATUS_IS_OK(expected_error)) {
1482                 if (NT_STATUS_IS_OK(status)) {
1483                         if (return_devtype != NULL &&
1484                             strequal(cli->dev, return_devtype)) {
1485                                 ret = True;
1486                         } else { 
1487                                 printf("tconX to share %s with type %s "
1488                                        "succeeded but returned the wrong "
1489                                        "device type (got [%s] but should have got [%s])\n",
1490                                        myshare, devtype, cli->dev, return_devtype);
1491                                 ret = False;
1492                         }
1493                 } else {
1494                         printf("tconX to share %s with type %s "
1495                                "should have succeeded but failed\n",
1496                                myshare, devtype);
1497                         ret = False;
1498                 }
1499                 cli_tdis(cli);
1500         } else {
1501                 if (NT_STATUS_IS_OK(status)) {
1502                         printf("tconx to share %s with type %s "
1503                                "should have failed but succeeded\n",
1504                                myshare, devtype);
1505                         ret = False;
1506                 } else {
1507                         if (NT_STATUS_EQUAL(status, expected_error)) {
1508                                 ret = True;
1509                         } else {
1510                                 printf("Returned unexpected error\n");
1511                                 ret = False;
1512                         }
1513                 }
1514         }
1515         return ret;
1516 }
1517
1518 /*
1519  checks for correct tconX support
1520  */
1521 static bool run_tcon_devtype_test(int dummy)
1522 {
1523         static struct cli_state *cli1 = NULL;
1524         int flags = CLI_FULL_CONNECTION_FORCE_SMB1;
1525         NTSTATUS status;
1526         bool ret = True;
1527
1528         status = cli_full_connection_creds(&cli1,
1529                                            myname,
1530                                            host,
1531                                            NULL, /* dest_ss */
1532                                            port_to_use,
1533                                            NULL, /* service */
1534                                            NULL, /* service_type */
1535                                            torture_creds,
1536                                            flags,
1537                                            signing_state);
1538
1539         if (!NT_STATUS_IS_OK(status)) {
1540                 printf("could not open connection\n");
1541                 return False;
1542         }
1543
1544         if (!tcon_devtest(cli1, "IPC$", "A:", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1545                 ret = False;
1546
1547         if (!tcon_devtest(cli1, "IPC$", "?????", "IPC", NT_STATUS_OK))
1548                 ret = False;
1549
1550         if (!tcon_devtest(cli1, "IPC$", "LPT:", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1551                 ret = False;
1552
1553         if (!tcon_devtest(cli1, "IPC$", "IPC", "IPC", NT_STATUS_OK))
1554                 ret = False;
1555
1556         if (!tcon_devtest(cli1, "IPC$", "FOOBA", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1557                 ret = False;
1558
1559         if (!tcon_devtest(cli1, share, "A:", "A:", NT_STATUS_OK))
1560                 ret = False;
1561
1562         if (!tcon_devtest(cli1, share, "?????", "A:", NT_STATUS_OK))
1563                 ret = False;
1564
1565         if (!tcon_devtest(cli1, share, "LPT:", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1566                 ret = False;
1567
1568         if (!tcon_devtest(cli1, share, "IPC", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1569                 ret = False;
1570
1571         if (!tcon_devtest(cli1, share, "FOOBA", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1572                 ret = False;
1573
1574         cli_shutdown(cli1);
1575
1576         if (ret)
1577                 printf("Passed tcondevtest\n");
1578
1579         return ret;
1580 }
1581
1582
1583 /*
1584   This test checks that 
1585
1586   1) the server supports multiple locking contexts on the one SMB
1587   connection, distinguished by PID.  
1588
1589   2) the server correctly fails overlapping locks made by the same PID (this
1590      goes against POSIX behaviour, which is why it is tricky to implement)
1591
1592   3) the server denies unlock requests by an incorrect client PID
1593 */
1594 static bool run_locktest2(int dummy)
1595 {
1596         static struct cli_state *cli;
1597         const char *fname = "\\lockt2.lck";
1598         uint16_t fnum1, fnum2, fnum3;
1599         bool correct = True;
1600         NTSTATUS status;
1601
1602         if (!torture_open_connection(&cli, 0)) {
1603                 return False;
1604         }
1605
1606         smbXcli_conn_set_sockopt(cli->conn, sockops);
1607
1608         printf("starting locktest2\n");
1609
1610         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1611
1612         cli_setpid(cli, 1);
1613
1614         status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
1615         if (!NT_STATUS_IS_OK(status)) {
1616                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
1617                 return False;
1618         }
1619
1620         status = cli_openx(cli, fname, O_RDWR, DENY_NONE, &fnum2);
1621         if (!NT_STATUS_IS_OK(status)) {
1622                 printf("open2 of %s failed (%s)\n", fname, nt_errstr(status));
1623                 return False;
1624         }
1625
1626         cli_setpid(cli, 2);
1627
1628         status = cli_openx(cli, fname, O_RDWR, DENY_NONE, &fnum3);
1629         if (!NT_STATUS_IS_OK(status)) {
1630                 printf("open3 of %s failed (%s)\n", fname, nt_errstr(status));
1631                 return False;
1632         }
1633
1634         cli_setpid(cli, 1);
1635
1636         status = cli_lock32(cli, fnum1, 0, 4, 0, WRITE_LOCK);
1637         if (!NT_STATUS_IS_OK(status)) {
1638                 printf("lock1 failed (%s)\n", nt_errstr(status));
1639                 return false;
1640         }
1641
1642         status = cli_lock32(cli, fnum1, 0, 4, 0, WRITE_LOCK);
1643         if (NT_STATUS_IS_OK(status)) {
1644                 printf("WRITE lock1 succeeded! This is a locking bug\n");
1645                 correct = false;
1646         } else {
1647                 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1648                                       NT_STATUS_LOCK_NOT_GRANTED)) {
1649                         return false;
1650                 }
1651         }
1652
1653         status = cli_lock32(cli, fnum2, 0, 4, 0, WRITE_LOCK);
1654         if (NT_STATUS_IS_OK(status)) {
1655                 printf("WRITE lock2 succeeded! This is a locking bug\n");
1656                 correct = false;
1657         } else {
1658                 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1659                                       NT_STATUS_LOCK_NOT_GRANTED)) {
1660                         return false;
1661                 }
1662         }
1663
1664         status = cli_lock32(cli, fnum2, 0, 4, 0, READ_LOCK);
1665         if (NT_STATUS_IS_OK(status)) {
1666                 printf("READ lock2 succeeded! This is a locking bug\n");
1667                 correct = false;
1668         } else {
1669                 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1670                                  NT_STATUS_FILE_LOCK_CONFLICT)) {
1671                         return false;
1672                 }
1673         }
1674
1675         status = cli_lock32(cli, fnum1, 100, 4, 0, WRITE_LOCK);
1676         if (!NT_STATUS_IS_OK(status)) {
1677                 printf("lock at 100 failed (%s)\n", nt_errstr(status));
1678         }
1679         cli_setpid(cli, 2);
1680         if (NT_STATUS_IS_OK(cli_unlock(cli, fnum1, 100, 4))) {
1681                 printf("unlock at 100 succeeded! This is a locking bug\n");
1682                 correct = False;
1683         }
1684
1685         status = cli_unlock(cli, fnum1, 0, 4);
1686         if (NT_STATUS_IS_OK(status)) {
1687                 printf("unlock1 succeeded! This is a locking bug\n");
1688                 correct = false;
1689         } else {
1690                 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1691                                       NT_STATUS_RANGE_NOT_LOCKED)) {
1692                         return false;
1693                 }
1694         }
1695
1696         status = cli_unlock(cli, fnum1, 0, 8);
1697         if (NT_STATUS_IS_OK(status)) {
1698                 printf("unlock2 succeeded! This is a locking bug\n");
1699                 correct = false;
1700         } else {
1701                 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1702                                       NT_STATUS_RANGE_NOT_LOCKED)) {
1703                         return false;
1704                 }
1705         }
1706
1707         status = cli_lock32(cli, fnum3, 0, 4, 0, WRITE_LOCK);
1708         if (NT_STATUS_IS_OK(status)) {
1709                 printf("lock3 succeeded! This is a locking bug\n");
1710                 correct = false;
1711         } else {
1712                 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1713                                       NT_STATUS_LOCK_NOT_GRANTED)) {
1714                         return false;
1715                 }
1716         }
1717
1718         cli_setpid(cli, 1);
1719
1720         status = cli_close(cli, fnum1);
1721         if (!NT_STATUS_IS_OK(status)) {
1722                 printf("close1 failed (%s)\n", nt_errstr(status));
1723                 return False;
1724         }
1725
1726         status = cli_close(cli, fnum2);
1727         if (!NT_STATUS_IS_OK(status)) {
1728                 printf("close2 failed (%s)\n", nt_errstr(status));
1729                 return False;
1730         }
1731
1732         status = cli_close(cli, fnum3);
1733         if (!NT_STATUS_IS_OK(status)) {
1734                 printf("close3 failed (%s)\n", nt_errstr(status));
1735                 return False;
1736         }
1737
1738         if (!torture_close_connection(cli)) {
1739                 correct = False;
1740         }
1741
1742         printf("locktest2 finished\n");
1743
1744         return correct;
1745 }
1746
1747
1748 /*
1749   This test checks that 
1750
1751   1) the server supports the full offset range in lock requests
1752 */
1753 static bool run_locktest3(int dummy)
1754 {
1755         static struct cli_state *cli1, *cli2;
1756         const char *fname = "\\lockt3.lck";
1757         uint16_t fnum1, fnum2;
1758         int i;
1759         uint32_t offset;
1760         bool correct = True;
1761         NTSTATUS status;
1762
1763 #define NEXT_OFFSET offset += (~(uint32_t)0) / torture_numops
1764
1765         if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
1766                 return False;
1767         }
1768         smbXcli_conn_set_sockopt(cli1->conn, sockops);
1769         smbXcli_conn_set_sockopt(cli2->conn, sockops);
1770
1771         printf("starting locktest3\n");
1772
1773         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1774
1775         status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
1776                          &fnum1);
1777         if (!NT_STATUS_IS_OK(status)) {
1778                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
1779                 return False;
1780         }
1781
1782         status = cli_openx(cli2, fname, O_RDWR, DENY_NONE, &fnum2);
1783         if (!NT_STATUS_IS_OK(status)) {
1784                 printf("open2 of %s failed (%s)\n", fname, nt_errstr(status));
1785                 return False;
1786         }
1787
1788         for (offset=i=0;i<torture_numops;i++) {
1789                 NEXT_OFFSET;
1790
1791                 status = cli_lock32(cli1, fnum1, offset-1, 1, 0, WRITE_LOCK);
1792                 if (!NT_STATUS_IS_OK(status)) {
1793                         printf("lock1 %d failed (%s)\n", 
1794                                i,
1795                                nt_errstr(status));
1796                         return False;
1797                 }
1798
1799                 status = cli_lock32(cli2, fnum2, offset-2, 1, 0, WRITE_LOCK);
1800                 if (!NT_STATUS_IS_OK(status)) {
1801                         printf("lock2 %d failed (%s)\n", 
1802                                i,
1803                                nt_errstr(status));
1804                         return False;
1805                 }
1806         }
1807
1808         for (offset=i=0;i<torture_numops;i++) {
1809                 NEXT_OFFSET;
1810
1811                 status = cli_lock32(cli1, fnum1, offset-2, 1, 0, WRITE_LOCK);
1812                 if (NT_STATUS_IS_OK(status)) {
1813                         printf("error: lock1 %d succeeded!\n", i);
1814                         return False;
1815                 }
1816
1817                 status = cli_lock32(cli2, fnum2, offset-1, 1, 0, WRITE_LOCK);
1818                 if (NT_STATUS_IS_OK(status)) {
1819                         printf("error: lock2 %d succeeded!\n", i);
1820                         return False;
1821                 }
1822
1823                 status = cli_lock32(cli1, fnum1, offset-1, 1, 0, WRITE_LOCK);
1824                 if (NT_STATUS_IS_OK(status)) {
1825                         printf("error: lock3 %d succeeded!\n", i);
1826                         return False;
1827                 }
1828
1829                 status = cli_lock32(cli2, fnum2, offset-2, 1, 0, WRITE_LOCK);
1830                 if (NT_STATUS_IS_OK(status)) {
1831                         printf("error: lock4 %d succeeded!\n", i);
1832                         return False;
1833                 }
1834         }
1835
1836         for (offset=i=0;i<torture_numops;i++) {
1837                 NEXT_OFFSET;
1838
1839                 status = cli_unlock(cli1, fnum1, offset-1, 1);
1840                 if (!NT_STATUS_IS_OK(status)) {
1841                         printf("unlock1 %d failed (%s)\n", 
1842                                i,
1843                                nt_errstr(status));
1844                         return False;
1845                 }
1846
1847                 status = cli_unlock(cli2, fnum2, offset-2, 1);
1848                 if (!NT_STATUS_IS_OK(status)) {
1849                         printf("unlock2 %d failed (%s)\n", 
1850                                i,
1851                                nt_errstr(status));
1852                         return False;
1853                 }
1854         }
1855
1856         status = cli_close(cli1, fnum1);
1857         if (!NT_STATUS_IS_OK(status)) {
1858                 printf("close1 failed (%s)\n", nt_errstr(status));
1859                 return False;
1860         }
1861
1862         status = cli_close(cli2, fnum2);
1863         if (!NT_STATUS_IS_OK(status)) {
1864                 printf("close2 failed (%s)\n", nt_errstr(status));
1865                 return False;
1866         }
1867
1868         status = cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1869         if (!NT_STATUS_IS_OK(status)) {
1870                 printf("unlink failed (%s)\n", nt_errstr(status));
1871                 return False;
1872         }
1873
1874         if (!torture_close_connection(cli1)) {
1875                 correct = False;
1876         }
1877
1878         if (!torture_close_connection(cli2)) {
1879                 correct = False;
1880         }
1881
1882         printf("finished locktest3\n");
1883
1884         return correct;
1885 }
1886
1887 static bool test_cli_read(struct cli_state *cli, uint16_t fnum,
1888                            char *buf, off_t offset, size_t size,
1889                            size_t *nread, size_t expect)
1890 {
1891         NTSTATUS status;
1892         size_t l_nread;
1893
1894         status = cli_read(cli, fnum, buf, offset, size, &l_nread);
1895
1896         if(!NT_STATUS_IS_OK(status)) {
1897                 return false;
1898         } else if (l_nread != expect) {
1899                 return false;
1900         }
1901
1902         if (nread) {
1903                 *nread = l_nread;
1904         }
1905
1906         return true;
1907 }
1908
1909 #define EXPECTED(ret, v) if ((ret) != (v)) { \
1910         printf("** "); correct = False; \
1911         }
1912
1913 /*
1914   looks at overlapping locks
1915 */
1916 static bool run_locktest4(int dummy)
1917 {
1918         static struct cli_state *cli1, *cli2;
1919         const char *fname = "\\lockt4.lck";
1920         uint16_t fnum1, fnum2, f;
1921         bool ret;
1922         char buf[1000];
1923         bool correct = True;
1924         NTSTATUS status;
1925
1926         if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
1927                 return False;
1928         }
1929
1930         smbXcli_conn_set_sockopt(cli1->conn, sockops);
1931         smbXcli_conn_set_sockopt(cli2->conn, sockops);
1932
1933         printf("starting locktest4\n");
1934
1935         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1936
1937         cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
1938         cli_openx(cli2, fname, O_RDWR, DENY_NONE, &fnum2);
1939
1940         memset(buf, 0, sizeof(buf));
1941
1942         status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 0, sizeof(buf),
1943                               NULL);
1944         if (!NT_STATUS_IS_OK(status)) {
1945                 printf("Failed to create file: %s\n", nt_errstr(status));
1946                 correct = False;
1947                 goto fail;
1948         }
1949
1950         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 4, 0, WRITE_LOCK)) &&
1951               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 2, 4, 0, WRITE_LOCK));
1952         EXPECTED(ret, False);
1953         printf("the same process %s set overlapping write locks\n", ret?"can":"cannot");
1954
1955         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 10, 4, 0, READ_LOCK)) &&
1956               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 12, 4, 0, READ_LOCK));
1957         EXPECTED(ret, True);
1958         printf("the same process %s set overlapping read locks\n", ret?"can":"cannot");
1959
1960         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 20, 4, 0, WRITE_LOCK)) &&
1961               NT_STATUS_IS_OK(cli_lock32(cli2, fnum2, 22, 4, 0, WRITE_LOCK));
1962         EXPECTED(ret, False);
1963         printf("a different connection %s set overlapping write locks\n", ret?"can":"cannot");
1964
1965         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 30, 4, 0, READ_LOCK)) &&
1966               NT_STATUS_IS_OK(cli_lock32(cli2, fnum2, 32, 4, 0, READ_LOCK));
1967         EXPECTED(ret, True);
1968         printf("a different connection %s set overlapping read locks\n", ret?"can":"cannot");
1969
1970         ret = (cli_setpid(cli1, 1),
1971               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 40, 4, 0, WRITE_LOCK))) &&
1972               (cli_setpid(cli1, 2),
1973               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 42, 4, 0, WRITE_LOCK)));
1974         EXPECTED(ret, False);
1975         printf("a different pid %s set overlapping write locks\n", ret?"can":"cannot");
1976
1977         ret = (cli_setpid(cli1, 1),
1978               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 50, 4, 0, READ_LOCK))) &&
1979               (cli_setpid(cli1, 2),
1980               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 52, 4, 0, READ_LOCK)));
1981         EXPECTED(ret, True);
1982         printf("a different pid %s set overlapping read locks\n", ret?"can":"cannot");
1983
1984         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 60, 4, 0, READ_LOCK)) &&
1985               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 60, 4, 0, READ_LOCK));
1986         EXPECTED(ret, True);
1987         printf("the same process %s set the same read lock twice\n", ret?"can":"cannot");
1988
1989         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 70, 4, 0, WRITE_LOCK)) &&
1990               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 70, 4, 0, WRITE_LOCK));
1991         EXPECTED(ret, False);
1992         printf("the same process %s set the same write lock twice\n", ret?"can":"cannot");
1993
1994         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 80, 4, 0, READ_LOCK)) &&
1995               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 80, 4, 0, WRITE_LOCK));
1996         EXPECTED(ret, False);
1997         printf("the same process %s overlay a read lock with a write lock\n", ret?"can":"cannot");
1998
1999         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 90, 4, 0, WRITE_LOCK)) &&
2000               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 90, 4, 0, READ_LOCK));
2001         EXPECTED(ret, True);
2002         printf("the same process %s overlay a write lock with a read lock\n", ret?"can":"cannot");
2003
2004         ret = (cli_setpid(cli1, 1),
2005              NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 100, 4, 0, WRITE_LOCK))) &&
2006              (cli_setpid(cli1, 2),
2007              NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 100, 4, 0, READ_LOCK)));
2008         EXPECTED(ret, False);
2009         printf("a different pid %s overlay a write lock with a read lock\n", ret?"can":"cannot");
2010
2011         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 110, 4, 0, READ_LOCK)) &&
2012               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 112, 4, 0, READ_LOCK)) &&
2013               NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 110, 6));
2014         EXPECTED(ret, False);
2015         printf("the same process %s coalesce read locks\n", ret?"can":"cannot");
2016
2017
2018         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 120, 4, 0, WRITE_LOCK)) &&
2019               test_cli_read(cli2, fnum2, buf, 120, 4, NULL, 4);
2020         EXPECTED(ret, False);
2021         printf("this server %s strict write locking\n", ret?"doesn't do":"does");
2022
2023         status = cli_lock32(cli1, fnum1, 130, 4, 0, READ_LOCK);
2024         ret = NT_STATUS_IS_OK(status);
2025         if (ret) {
2026                 status = cli_writeall(cli2, fnum2, 0, (uint8_t *)buf, 130, 4,
2027                                       NULL);
2028                 ret = NT_STATUS_IS_OK(status);
2029         }
2030         EXPECTED(ret, False);
2031         printf("this server %s strict read locking\n", ret?"doesn't do":"does");
2032
2033
2034         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 140, 4, 0, READ_LOCK)) &&
2035               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 140, 4, 0, READ_LOCK)) &&
2036               NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 140, 4)) &&
2037               NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 140, 4));
2038         EXPECTED(ret, True);
2039         printf("this server %s do recursive read locking\n", ret?"does":"doesn't");
2040
2041
2042         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 150, 4, 0, WRITE_LOCK)) &&
2043               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 150, 4, 0, READ_LOCK)) &&
2044               NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 150, 4)) &&
2045               test_cli_read(cli2, fnum2, buf, 150, 4, NULL, 4) &&
2046               !(NT_STATUS_IS_OK(cli_writeall(cli2, fnum2, 0, (uint8_t *)buf,
2047                                              150, 4, NULL))) &&
2048               NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 150, 4));
2049         EXPECTED(ret, True);
2050         printf("this server %s do recursive lock overlays\n", ret?"does":"doesn't");
2051
2052         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 160, 4, 0, READ_LOCK)) &&
2053               NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 160, 4)) &&
2054               NT_STATUS_IS_OK(cli_writeall(cli2, fnum2, 0, (uint8_t *)buf,
2055                                            160, 4, NULL)) &&
2056               test_cli_read(cli2, fnum2, buf, 160, 4, NULL, 4);
2057         EXPECTED(ret, True);
2058         printf("the same process %s remove a read lock using write locking\n", ret?"can":"cannot");
2059
2060         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 170, 4, 0, WRITE_LOCK)) &&
2061               NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 170, 4)) &&
2062               NT_STATUS_IS_OK(cli_writeall(cli2, fnum2, 0, (uint8_t *)buf,
2063                                            170, 4, NULL)) &&
2064               test_cli_read(cli2, fnum2, buf, 170, 4, NULL, 4);
2065         EXPECTED(ret, True);
2066         printf("the same process %s remove a write lock using read locking\n", ret?"can":"cannot");
2067
2068         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 190, 4, 0, WRITE_LOCK)) &&
2069               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 190, 4, 0, READ_LOCK)) &&
2070               NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 190, 4)) &&
2071               !NT_STATUS_IS_OK(cli_writeall(cli2, fnum2, 0, (uint8_t *)buf,
2072                                             190, 4, NULL)) &&
2073               test_cli_read(cli2, fnum2, buf, 190, 4, NULL, 4);
2074         EXPECTED(ret, True);
2075         printf("the same process %s remove the first lock first\n", ret?"does":"doesn't");
2076
2077         cli_close(cli1, fnum1);
2078         cli_close(cli2, fnum2);
2079         cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
2080         cli_openx(cli1, fname, O_RDWR, DENY_NONE, &f);
2081         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 8, 0, READ_LOCK)) &&
2082               NT_STATUS_IS_OK(cli_lock32(cli1, f, 0, 1, 0, READ_LOCK)) &&
2083               NT_STATUS_IS_OK(cli_close(cli1, fnum1)) &&
2084               NT_STATUS_IS_OK(cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1)) &&
2085               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 7, 1, 0, WRITE_LOCK));
2086         cli_close(cli1, f);
2087         cli_close(cli1, fnum1);
2088         EXPECTED(ret, True);
2089         printf("the server %s have the NT byte range lock bug\n", !ret?"does":"doesn't");
2090
2091  fail:
2092         cli_close(cli1, fnum1);
2093         cli_close(cli2, fnum2);
2094         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2095         torture_close_connection(cli1);
2096         torture_close_connection(cli2);
2097
2098         printf("finished locktest4\n");
2099         return correct;
2100 }
2101
2102 /*
2103   looks at lock upgrade/downgrade.
2104 */
2105 static bool run_locktest5(int dummy)
2106 {
2107         static struct cli_state *cli1, *cli2;
2108         const char *fname = "\\lockt5.lck";
2109         uint16_t fnum1, fnum2, fnum3;
2110         bool ret;
2111         char buf[1000];
2112         bool correct = True;
2113         NTSTATUS status;
2114
2115         if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
2116                 return False;
2117         }
2118
2119         smbXcli_conn_set_sockopt(cli1->conn, sockops);
2120         smbXcli_conn_set_sockopt(cli2->conn, sockops);
2121
2122         printf("starting locktest5\n");
2123
2124         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2125
2126         cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
2127         cli_openx(cli2, fname, O_RDWR, DENY_NONE, &fnum2);
2128         cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum3);
2129
2130         memset(buf, 0, sizeof(buf));
2131
2132         status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 0, sizeof(buf),
2133                               NULL);
2134         if (!NT_STATUS_IS_OK(status)) {
2135                 printf("Failed to create file: %s\n", nt_errstr(status));
2136                 correct = False;
2137                 goto fail;
2138         }
2139
2140         /* Check for NT bug... */
2141         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 8, 0, READ_LOCK)) &&
2142               NT_STATUS_IS_OK(cli_lock32(cli1, fnum3, 0, 1, 0, READ_LOCK));
2143         cli_close(cli1, fnum1);
2144         cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
2145         status = cli_lock32(cli1, fnum1, 7, 1, 0, WRITE_LOCK);
2146         ret = NT_STATUS_IS_OK(status);
2147         EXPECTED(ret, True);
2148         printf("this server %s the NT locking bug\n", ret ? "doesn't have" : "has");
2149         cli_close(cli1, fnum1);
2150         cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
2151         cli_unlock(cli1, fnum3, 0, 1);
2152
2153         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 4, 0, WRITE_LOCK)) &&
2154               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 1, 1, 0, READ_LOCK));
2155         EXPECTED(ret, True);
2156         printf("the same process %s overlay a write with a read lock\n", ret?"can":"cannot");
2157
2158         status = cli_lock32(cli2, fnum2, 0, 4, 0, READ_LOCK);
2159         ret = NT_STATUS_IS_OK(status);
2160         EXPECTED(ret, False);
2161
2162         printf("a different process %s get a read lock on the first process lock stack\n", ret?"can":"cannot");
2163
2164         /* Unlock the process 2 lock. */
2165         cli_unlock(cli2, fnum2, 0, 4);
2166
2167         status = cli_lock32(cli1, fnum3, 0, 4, 0, READ_LOCK);
2168         ret = NT_STATUS_IS_OK(status);
2169         EXPECTED(ret, False);
2170
2171         printf("the same process on a different fnum %s get a read lock\n", ret?"can":"cannot");
2172
2173         /* Unlock the process 1 fnum3 lock. */
2174         cli_unlock(cli1, fnum3, 0, 4);
2175
2176         /* Stack 2 more locks here. */
2177         ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 4, 0, READ_LOCK)) &&
2178               NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 4, 0, READ_LOCK));
2179
2180         EXPECTED(ret, True);
2181         printf("the same process %s stack read locks\n", ret?"can":"cannot");
2182
2183         /* Unlock the first process lock, then check this was the WRITE lock that was
2184                 removed. */
2185
2186         ret = NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 0, 4)) &&
2187               NT_STATUS_IS_OK(cli_lock32(cli2, fnum2, 0, 4, 0, READ_LOCK));
2188
2189         EXPECTED(ret, True);
2190         printf("the first unlock removes the %s lock\n", ret?"WRITE":"READ");
2191
2192         /* Unlock the process 2 lock. */
2193         cli_unlock(cli2, fnum2, 0, 4);
2194
2195         /* We should have 3 stacked locks here. Ensure we need to do 3 unlocks. */
2196
2197         ret = NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 1, 1)) &&
2198                   NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 0, 4)) &&
2199                   NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 0, 4));
2200
2201         EXPECTED(ret, True);
2202         printf("the same process %s unlock the stack of 4 locks\n", ret?"can":"cannot"); 
2203
2204         /* Ensure the next unlock fails. */
2205         ret = NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 0, 4));
2206         EXPECTED(ret, False);
2207         printf("the same process %s count the lock stack\n", !ret?"can":"cannot"); 
2208
2209         /* Ensure connection 2 can get a write lock. */
2210         status = cli_lock32(cli2, fnum2, 0, 4, 0, WRITE_LOCK);
2211         ret = NT_STATUS_IS_OK(status);
2212         EXPECTED(ret, True);
2213
2214         printf("a different process %s get a write lock on the unlocked stack\n", ret?"can":"cannot");
2215
2216
2217  fail:
2218         cli_close(cli1, fnum1);
2219         cli_close(cli2, fnum2);
2220         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2221         if (!torture_close_connection(cli1)) {
2222                 correct = False;
2223         }
2224         if (!torture_close_connection(cli2)) {
2225                 correct = False;
2226         }
2227
2228         printf("finished locktest5\n");
2229
2230         return correct;
2231 }
2232
2233 /*
2234   tries the unusual lockingX locktype bits
2235 */
2236 static bool run_locktest6(int dummy)
2237 {
2238         static struct cli_state *cli;
2239         const char *fname[1] = { "\\lock6.txt" };
2240         int i;
2241         uint16_t fnum;
2242         NTSTATUS status;
2243
2244         if (!torture_open_connection(&cli, 0)) {
2245                 return False;
2246         }
2247
2248         smbXcli_conn_set_sockopt(cli->conn, sockops);
2249
2250         printf("starting locktest6\n");
2251
2252         for (i=0;i<1;i++) {
2253                 printf("Testing %s\n", fname[i]);
2254
2255                 cli_unlink(cli, fname[i], FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2256
2257                 cli_openx(cli, fname[i], O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
2258                 status = cli_locktype(cli, fnum, 0, 8, 0, LOCKING_ANDX_CHANGE_LOCKTYPE);
2259                 cli_close(cli, fnum);
2260                 printf("CHANGE_LOCKTYPE gave %s\n", nt_errstr(status));
2261
2262                 cli_openx(cli, fname[i], O_RDWR, DENY_NONE, &fnum);
2263                 status = cli_locktype(cli, fnum, 0, 8, 0, LOCKING_ANDX_CANCEL_LOCK);
2264                 cli_close(cli, fnum);
2265                 printf("CANCEL_LOCK gave %s\n", nt_errstr(status));
2266
2267                 cli_unlink(cli, fname[i], FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2268         }
2269
2270         torture_close_connection(cli);
2271
2272         printf("finished locktest6\n");
2273         return True;
2274 }
2275
2276 static bool run_locktest7(int dummy)
2277 {
2278         struct cli_state *cli1;
2279         const char *fname = "\\lockt7.lck";
2280         uint16_t fnum1;
2281         char buf[200];
2282         bool correct = False;
2283         size_t nread;
2284         NTSTATUS status;
2285
2286         if (!torture_open_connection(&cli1, 0)) {
2287                 return False;
2288         }
2289
2290         smbXcli_conn_set_sockopt(cli1->conn, sockops);
2291
2292         printf("starting locktest7\n");
2293
2294         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2295
2296         cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
2297
2298         memset(buf, 0, sizeof(buf));
2299
2300         status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 0, sizeof(buf),
2301                               NULL);
2302         if (!NT_STATUS_IS_OK(status)) {
2303                 printf("Failed to create file: %s\n", nt_errstr(status));
2304                 goto fail;
2305         }
2306
2307         cli_setpid(cli1, 1);
2308
2309         status = cli_lock32(cli1, fnum1, 130, 4, 0, READ_LOCK);
2310         if (!NT_STATUS_IS_OK(status)) {
2311                 printf("Unable to apply read lock on range 130:4, "
2312                        "error was %s\n", nt_errstr(status));
2313                 goto fail;
2314         } else {
2315                 printf("pid1 successfully locked range 130:4 for READ\n");
2316         }
2317
2318         status = cli_read(cli1, fnum1, buf, 130, 4, &nread);
2319         if (!NT_STATUS_IS_OK(status)) {
2320                 printf("pid1 unable to read the range 130:4, error was %s\n",
2321                       nt_errstr(status));
2322                 goto fail;
2323         } else if (nread != 4) {
2324                 printf("pid1 unable to read the range 130:4, "
2325                        "recv %ld req %d\n", (unsigned long)nread, 4);
2326                 goto fail;
2327         } else {
2328                 printf("pid1 successfully read the range 130:4\n");
2329         }
2330
2331         status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
2332         if (!NT_STATUS_IS_OK(status)) {
2333                 printf("pid1 unable to write to the range 130:4, error was "
2334                        "%s\n", nt_errstr(status));
2335                 if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
2336                         printf("Incorrect error (should be NT_STATUS_FILE_LOCK_CONFLICT)\n");
2337                         goto fail;
2338                 }
2339         } else {
2340                 printf("pid1 successfully wrote to the range 130:4 (should be denied)\n");
2341                 goto fail;
2342         }
2343
2344         cli_setpid(cli1, 2);
2345
2346         status = cli_read(cli1, fnum1, buf, 130, 4, &nread);
2347         if (!NT_STATUS_IS_OK(status)) {
2348                 printf("pid2 unable to read the range 130:4, error was %s\n",
2349                       nt_errstr(status));
2350                 goto fail;
2351         } else if (nread != 4) {
2352                 printf("pid2 unable to read the range 130:4, "
2353                        "recv %ld req %d\n", (unsigned long)nread, 4);
2354                 goto fail;
2355         } else {
2356                 printf("pid2 successfully read the range 130:4\n");
2357         }
2358
2359         status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
2360         if (!NT_STATUS_IS_OK(status)) {
2361                 printf("pid2 unable to write to the range 130:4, error was "
2362                        "%s\n", nt_errstr(status));
2363                 if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
2364                         printf("Incorrect error (should be NT_STATUS_FILE_LOCK_CONFLICT)\n");
2365                         goto fail;
2366                 }
2367         } else {
2368                 printf("pid2 successfully wrote to the range 130:4 (should be denied)\n");
2369                 goto fail;
2370         }
2371
2372         cli_setpid(cli1, 1);
2373         cli_unlock(cli1, fnum1, 130, 4);
2374
2375         status = cli_lock32(cli1, fnum1, 130, 4, 0, WRITE_LOCK);
2376         if (!NT_STATUS_IS_OK(status)) {
2377                 printf("Unable to apply write lock on range 130:4, error was %s\n", nt_errstr(status));
2378                 goto fail;
2379         } else {
2380                 printf("pid1 successfully locked range 130:4 for WRITE\n");
2381         }
2382
2383         status = cli_read(cli1, fnum1, buf, 130, 4, &nread);
2384         if (!NT_STATUS_IS_OK(status)) {
2385                 printf("pid1 unable to read the range 130:4, error was %s\n",
2386                       nt_errstr(status));
2387                 goto fail;
2388         } else if (nread != 4) {
2389                 printf("pid1 unable to read the range 130:4, "
2390                        "recv %ld req %d\n", (unsigned long)nread, 4);
2391                 goto fail;
2392         } else {
2393                 printf("pid1 successfully read the range 130:4\n");
2394         }
2395
2396         status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
2397         if (!NT_STATUS_IS_OK(status)) {
2398                 printf("pid1 unable to write to the range 130:4, error was "
2399                        "%s\n", nt_errstr(status));
2400                 goto fail;
2401         } else {
2402                 printf("pid1 successfully wrote to the range 130:4\n");
2403         }
2404
2405         cli_setpid(cli1, 2);
2406
2407         status = cli_read(cli1, fnum1, buf, 130, 4, &nread);
2408         if (!NT_STATUS_IS_OK(status)) {
2409                 printf("pid2 unable to read the range 130:4, error was "
2410                        "%s\n", nt_errstr(status));
2411                 if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
2412                         printf("Incorrect error (should be NT_STATUS_FILE_LOCK_CONFLICT)\n");
2413                         goto fail;
2414                 }
2415         } else {
2416                 printf("pid2 successfully read the range 130:4 (should be denied) recv %ld\n",
2417                        (unsigned long)nread);
2418                 goto fail;
2419         }
2420
2421         status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
2422         if (!NT_STATUS_IS_OK(status)) {
2423                 printf("pid2 unable to write to the range 130:4, error was "
2424                        "%s\n", nt_errstr(status));
2425                 if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
2426                         printf("Incorrect error (should be NT_STATUS_FILE_LOCK_CONFLICT)\n");
2427                         goto fail;
2428                 }
2429         } else {
2430                 printf("pid2 successfully wrote to the range 130:4 (should be denied)\n");
2431                 goto fail;
2432         }
2433
2434         cli_unlock(cli1, fnum1, 130, 0);
2435         correct = True;
2436
2437 fail:
2438         cli_close(cli1, fnum1);
2439         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2440         torture_close_connection(cli1);
2441
2442         printf("finished locktest7\n");
2443         return correct;
2444 }
2445
2446 /*
2447  * This demonstrates a problem with our use of GPFS share modes: A file
2448  * descriptor sitting in the pending close queue holding a GPFS share mode
2449  * blocks opening a file another time. Happens with Word 2007 temp files.
2450  * With "posix locking = yes" and "gpfs:sharemodes = yes" enabled, the third
2451  * open is denied with NT_STATUS_SHARING_VIOLATION.
2452  */
2453
2454 static bool run_locktest8(int dummy)
2455 {
2456         struct cli_state *cli1;
2457         const char *fname = "\\lockt8.lck";
2458         uint16_t fnum1, fnum2;
2459         char buf[200];
2460         bool correct = False;
2461         NTSTATUS status;
2462
2463         if (!torture_open_connection(&cli1, 0)) {
2464                 return False;
2465         }
2466
2467         smbXcli_conn_set_sockopt(cli1->conn, sockops);
2468
2469         printf("starting locktest8\n");
2470
2471         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2472
2473         status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_WRITE,
2474                           &fnum1);
2475         if (!NT_STATUS_IS_OK(status)) {
2476                 d_fprintf(stderr, "cli_openx returned %s\n", nt_errstr(status));
2477                 return false;
2478         }
2479
2480         memset(buf, 0, sizeof(buf));
2481
2482         status = cli_openx(cli1, fname, O_RDONLY, DENY_NONE, &fnum2);
2483         if (!NT_STATUS_IS_OK(status)) {
2484                 d_fprintf(stderr, "cli_openx second time returned %s\n",
2485                           nt_errstr(status));
2486                 goto fail;
2487         }
2488
2489         status = cli_lock32(cli1, fnum2, 1, 1, 0, READ_LOCK);
2490         if (!NT_STATUS_IS_OK(status)) {
2491                 printf("Unable to apply read lock on range 1:1, error was "
2492                        "%s\n", nt_errstr(status));
2493                 goto fail;
2494         }
2495
2496         status = cli_close(cli1, fnum1);
2497         if (!NT_STATUS_IS_OK(status)) {
2498                 d_fprintf(stderr, "cli_close(fnum1) %s\n", nt_errstr(status));
2499                 goto fail;
2500         }
2501
2502         status = cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
2503         if (!NT_STATUS_IS_OK(status)) {
2504                 d_fprintf(stderr, "cli_openx third time returned %s\n",
2505                           nt_errstr(status));
2506                 goto fail;
2507         }
2508
2509         correct = true;
2510
2511 fail:
2512         cli_close(cli1, fnum1);
2513         cli_close(cli1, fnum2);
2514         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2515         torture_close_connection(cli1);
2516
2517         printf("finished locktest8\n");
2518         return correct;
2519 }
2520
2521 /*
2522  * This test is designed to be run in conjunction with
2523  * external NFS or POSIX locks taken in the filesystem.
2524  * It checks that the smbd server will block until the
2525  * lock is released and then acquire it. JRA.
2526  */
2527
2528 static bool got_alarm;
2529 static struct cli_state *alarm_cli;
2530
2531 static void alarm_handler(int dummy)
2532 {
2533         got_alarm = True;
2534 }
2535
2536 static void alarm_handler_parent(int dummy)
2537 {
2538         smbXcli_conn_disconnect(alarm_cli->conn, NT_STATUS_OK);
2539 }
2540
2541 static void do_local_lock(int read_fd, int write_fd)
2542 {
2543         int fd;
2544         char c = '\0';
2545         struct flock lock;
2546         const char *local_pathname = NULL;
2547         int ret;
2548
2549         local_pathname = talloc_asprintf(talloc_tos(),
2550                         "%s/lockt9.lck", local_path);
2551         if (!local_pathname) {
2552                 printf("child: alloc fail\n");
2553                 exit(1);
2554         }
2555
2556         unlink(local_pathname);
2557         fd = open(local_pathname, O_RDWR|O_CREAT, 0666);
2558         if (fd == -1) {
2559                 printf("child: open of %s failed %s.\n",
2560                         local_pathname, strerror(errno));
2561                 exit(1);
2562         }
2563
2564         /* Now take a fcntl lock. */
2565         lock.l_type = F_WRLCK;
2566         lock.l_whence = SEEK_SET;
2567         lock.l_start = 0;
2568         lock.l_len = 4;
2569         lock.l_pid = getpid();
2570
2571         ret = fcntl(fd,F_SETLK,&lock);
2572         if (ret == -1) {
2573                 printf("child: failed to get lock 0:4 on file %s. Error %s\n",
2574                         local_pathname, strerror(errno));
2575                 exit(1);
2576         } else {
2577                 printf("child: got lock 0:4 on file %s.\n",
2578                         local_pathname );
2579                 fflush(stdout);
2580         }
2581
2582         CatchSignal(SIGALRM, alarm_handler);
2583         alarm(5);
2584         /* Signal the parent. */
2585         if (write(write_fd, &c, 1) != 1) {
2586                 printf("child: start signal fail %s.\n",
2587                         strerror(errno));
2588                 exit(1);
2589         }
2590         alarm(0);
2591
2592         alarm(10);
2593         /* Wait for the parent to be ready. */
2594         if (read(read_fd, &c, 1) != 1) {
2595                 printf("child: reply signal fail %s.\n",
2596                         strerror(errno));
2597                 exit(1);
2598         }
2599         alarm(0);
2600
2601         sleep(5);
2602         close(fd);
2603         printf("child: released lock 0:4 on file %s.\n",
2604                 local_pathname );
2605         fflush(stdout);
2606         exit(0);
2607 }
2608
2609 static bool run_locktest9(int dummy)
2610 {
2611         struct cli_state *cli1;
2612         const char *fname = "\\lockt9.lck";
2613         uint16_t fnum;
2614         bool correct = False;
2615         int pipe_in[2], pipe_out[2];
2616         pid_t child_pid;
2617         char c = '\0';
2618         int ret;
2619         struct timeval start;
2620         double seconds;
2621         NTSTATUS status;
2622
2623         printf("starting locktest9\n");
2624
2625         if (local_path == NULL) {
2626                 d_fprintf(stderr, "locktest9 must be given a local path via -l <localpath>\n");
2627                 return false;
2628         }
2629
2630         if (pipe(pipe_in) == -1 || pipe(pipe_out) == -1) {
2631                 return false;
2632         }
2633
2634         child_pid = fork();
2635         if (child_pid == -1) {
2636                 return false;
2637         }
2638
2639         if (child_pid == 0) {
2640                 /* Child. */
2641                 do_local_lock(pipe_out[0], pipe_in[1]);
2642                 exit(0);
2643         }
2644
2645         close(pipe_out[0]);
2646         close(pipe_in[1]);
2647         pipe_out[0] = -1;
2648         pipe_in[1] = -1;
2649
2650         /* Parent. */
2651         ret = read(pipe_in[0], &c, 1);
2652         if (ret != 1) {
2653                 d_fprintf(stderr, "failed to read start signal from child. %s\n",
2654                         strerror(errno));
2655                 return false;
2656         }
2657
2658         if (!torture_open_connection(&cli1, 0)) {
2659                 return false;
2660         }
2661
2662         smbXcli_conn_set_sockopt(cli1->conn, sockops);
2663
2664         status = cli_openx(cli1, fname, O_RDWR, DENY_NONE,
2665                           &fnum);
2666         if (!NT_STATUS_IS_OK(status)) {
2667                 d_fprintf(stderr, "cli_openx returned %s\n", nt_errstr(status));
2668                 return false;
2669         }
2670
2671         /* Ensure the child has the lock. */
2672         status = cli_lock32(cli1, fnum, 0, 4, 0, WRITE_LOCK);
2673         if (NT_STATUS_IS_OK(status)) {
2674                 d_fprintf(stderr, "Got the lock on range 0:4 - this should not happen !\n");
2675                 goto fail;
2676         } else {
2677                 d_printf("Child has the lock.\n");
2678         }
2679
2680         /* Tell the child to wait 5 seconds then exit. */
2681         ret = write(pipe_out[1], &c, 1);
2682         if (ret != 1) {
2683                 d_fprintf(stderr, "failed to send exit signal to child. %s\n",
2684                         strerror(errno));
2685                 goto fail;
2686         }
2687
2688         /* Wait 20 seconds for the lock. */
2689         alarm_cli = cli1;
2690         CatchSignal(SIGALRM, alarm_handler_parent);
2691         alarm(20);
2692
2693         start = timeval_current();
2694
2695         status = cli_lock32(cli1, fnum, 0, 4, -1, WRITE_LOCK);
2696         if (!NT_STATUS_IS_OK(status)) {
2697                 d_fprintf(stderr, "Unable to apply write lock on range 0:4, error was "
2698                        "%s\n", nt_errstr(status));
2699                 goto fail_nofd;
2700         }
2701         alarm(0);
2702
2703         seconds = timeval_elapsed(&start);
2704
2705         printf("Parent got the lock after %.2f seconds.\n",
2706                 seconds);
2707
2708         status = cli_close(cli1, fnum);
2709         if (!NT_STATUS_IS_OK(status)) {
2710                 d_fprintf(stderr, "cli_close(fnum1) %s\n", nt_errstr(status));
2711                 goto fail;
2712         }
2713
2714         correct = true;
2715
2716 fail:
2717         cli_close(cli1, fnum);
2718         torture_close_connection(cli1);
2719
2720 fail_nofd:
2721
2722         printf("finished locktest9\n");
2723         return correct;
2724 }
2725
2726 /*
2727 test whether fnums and tids open on one VC are available on another (a major
2728 security hole)
2729 */
2730 static bool run_fdpasstest(int dummy)
2731 {
2732         struct cli_state *cli1, *cli2;
2733         const char *fname = "\\fdpass.tst";
2734         uint16_t fnum1;
2735         char buf[1024];
2736         NTSTATUS status;
2737
2738         if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
2739                 return False;
2740         }
2741         smbXcli_conn_set_sockopt(cli1->conn, sockops);
2742         smbXcli_conn_set_sockopt(cli2->conn, sockops);
2743
2744         printf("starting fdpasstest\n");
2745
2746         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2747
2748         status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
2749                           &fnum1);
2750         if (!NT_STATUS_IS_OK(status)) {
2751                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
2752                 return False;
2753         }
2754
2755         status = cli_writeall(cli1, fnum1, 0, (const uint8_t *)"hello world\n", 0,
2756                               13, NULL);
2757         if (!NT_STATUS_IS_OK(status)) {
2758                 printf("write failed (%s)\n", nt_errstr(status));
2759                 return False;
2760         }
2761
2762         cli_state_set_uid(cli2, cli_state_get_uid(cli1));
2763         cli_state_set_tid(cli2, cli_state_get_tid(cli1));
2764         cli_setpid(cli2, cli_getpid(cli1));
2765
2766         if (test_cli_read(cli2, fnum1, buf, 0, 13, NULL, 13)) {
2767                 printf("read succeeded! nasty security hole [%s]\n", buf);
2768                 return false;
2769         }
2770
2771         cli_close(cli1, fnum1);
2772         cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2773
2774         torture_close_connection(cli1);
2775         torture_close_connection(cli2);
2776
2777         printf("finished fdpasstest\n");
2778         return True;
2779 }
2780
2781 static bool run_fdsesstest(int dummy)
2782 {
2783         struct cli_state *cli;
2784         uint16_t new_vuid;
2785         uint16_t saved_vuid;
2786         uint32_t new_cnum;
2787         uint32_t saved_cnum;
2788         const char *fname = "\\fdsess.tst";
2789         const char *fname1 = "\\fdsess1.tst";
2790         uint16_t fnum1;
2791         uint16_t fnum2;
2792         char buf[1024];
2793         bool ret = True;
2794         NTSTATUS status;
2795
2796         if (!torture_open_connection(&cli, 0))
2797                 return False;
2798         smbXcli_conn_set_sockopt(cli->conn, sockops);
2799
2800         if (!torture_cli_session_setup2(cli, &new_vuid))
2801                 return False;
2802
2803         saved_cnum = cli_state_get_tid(cli);
2804         if (!NT_STATUS_IS_OK(cli_tree_connect(cli, share, "?????", NULL)))
2805                 return False;
2806         new_cnum = cli_state_get_tid(cli);
2807         cli_state_set_tid(cli, saved_cnum);
2808
2809         printf("starting fdsesstest\n");
2810
2811         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2812         cli_unlink(cli, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2813
2814         status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
2815         if (!NT_STATUS_IS_OK(status)) {
2816                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
2817                 return False;
2818         }
2819
2820         status = cli_writeall(cli, fnum1, 0, (const uint8_t *)"hello world\n", 0, 13,
2821                               NULL);
2822         if (!NT_STATUS_IS_OK(status)) {
2823                 printf("write failed (%s)\n", nt_errstr(status));
2824                 return False;
2825         }
2826
2827         saved_vuid = cli_state_get_uid(cli);
2828         cli_state_set_uid(cli, new_vuid);
2829
2830         if (test_cli_read(cli, fnum1, buf, 0, 13, NULL, 13)) {
2831                 printf("read succeeded with different vuid! "
2832                        "nasty security hole [%s]\n", buf);
2833                 ret = false;
2834         }
2835         /* Try to open a file with different vuid, samba cnum. */
2836         if (NT_STATUS_IS_OK(cli_openx(cli, fname1, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum2))) {
2837                 printf("create with different vuid, same cnum succeeded.\n");
2838                 cli_close(cli, fnum2);
2839                 cli_unlink(cli, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2840         } else {
2841                 printf("create with different vuid, same cnum failed.\n");
2842                 printf("This will cause problems with service clients.\n");
2843                 ret = False;
2844         }
2845
2846         cli_state_set_uid(cli, saved_vuid);
2847
2848         /* Try with same vuid, different cnum. */
2849         cli_state_set_tid(cli, new_cnum);
2850
2851         if (test_cli_read(cli, fnum1, buf, 0, 13, NULL, 13)) {
2852                 printf("read succeeded with different cnum![%s]\n", buf);
2853                 ret = false;
2854         }
2855
2856         cli_state_set_tid(cli, saved_cnum);
2857         cli_close(cli, fnum1);
2858         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2859
2860         torture_close_connection(cli);
2861
2862         printf("finished fdsesstest\n");
2863         return ret;
2864 }
2865
2866 /*
2867   This test checks that 
2868
2869   1) the server does not allow an unlink on a file that is open
2870 */
2871 static bool run_unlinktest(int dummy)
2872 {
2873         struct cli_state *cli;
2874         const char *fname = "\\unlink.tst";
2875         uint16_t fnum;
2876         bool correct = True;
2877         NTSTATUS status;
2878
2879         if (!torture_open_connection(&cli, 0)) {
2880                 return False;
2881         }
2882
2883         smbXcli_conn_set_sockopt(cli->conn, sockops);
2884
2885         printf("starting unlink test\n");
2886
2887         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2888
2889         cli_setpid(cli, 1);
2890
2891         status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
2892         if (!NT_STATUS_IS_OK(status)) {
2893                 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
2894                 return False;
2895         }
2896
2897         status = cli_unlink(cli, fname,
2898                             FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2899         if (NT_STATUS_IS_OK(status)) {
2900                 printf("error: server allowed unlink on an open file\n");
2901                 correct = False;
2902         } else {
2903                 correct = check_error(__LINE__, status, ERRDOS, ERRbadshare,
2904                                       NT_STATUS_SHARING_VIOLATION);
2905         }
2906
2907         cli_close(cli, fnum);
2908         cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2909
2910         if (!torture_close_connection(cli)) {
2911                 correct = False;
2912         }
2913
2914         printf("unlink test finished\n");
2915
2916         return correct;
2917 }
2918
2919
2920 /*
2921 test how many open files this server supports on the one socket
2922 */
2923 static bool run_maxfidtest(int dummy)
2924 {
2925         struct cli_state *cli;
2926         fstring fname;
2927         uint16_t fnums[0x11000];
2928         int i;
2929         int retries=4;
2930         bool correct = True;
2931         NTSTATUS status;
2932
2933         cli = current_cli;
2934
2935         if (retries <= 0) {
2936                 printf("failed to connect\n");
2937                 return False;
2938         }
2939
2940         smbXcli_conn_set_sockopt(cli->conn, sockops);
2941
2942         for (i=0; i<0x11000; i++) {
2943                 slprintf(fname,sizeof(fname)-1,"\\maxfid.%d.%d", i,(int)getpid());
2944                 status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_TRUNC, DENY_NONE,
2945                                   &fnums[i]);
2946                 if (!NT_STATUS_IS_OK(status)) {
2947                         printf("open of %s failed (%s)\n", 
2948                                fname, nt_errstr(status));
2949                         printf("maximum fnum is %d\n", i);
2950                         break;
2951                 }
2952                 printf("%6d\r", i);
2953         }
2954         printf("%6d\n", i);
2955         i--;
2956
2957         printf("cleaning up\n");
2958         for (;i>=0;i--) {
2959                 slprintf(fname,sizeof(fname)-1,"\\maxfid.%d.%d", i,(int)getpid());
2960                 cli_close(cli, fnums[i]);
2961
2962                 status = cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2963                 if (!NT_STATUS_IS_OK(status)) {
2964                         printf("unlink of %s failed (%s)\n", 
2965                                fname, nt_errstr(status));
2966                         correct = False;
2967                 }
2968                 printf("%6d\r", i);
2969         }
2970         printf("%6d\n", 0);
2971
2972         printf("maxfid test finished\n");
2973         if (!torture_close_connection(cli)) {
2974                 correct = False;
2975         }
2976         return correct;
2977 }
2978
2979 /* generate a random buffer */
2980 static void rand_buf(char *buf, int len)
2981 {
2982         while (len--) {
2983                 *buf = (char)sys_random();
2984                 buf++;
2985         }
2986 }
2987
2988 /* send smb negprot commands, not reading the response */
2989 static bool run_negprot_nowait(int dummy)
2990 {
2991         struct tevent_context *ev;
2992         int i;
2993         struct cli_state *cli;
2994         bool correct = True;
2995
2996         printf("starting negprot nowait test\n");
2997
2998         ev = samba_tevent_context_init(talloc_tos());
2999         if (ev == NULL) {
3000                 return false;
3001         }
3002
3003         if (!(cli = open_nbt_connection())) {
3004                 TALLOC_FREE(ev);
3005                 return False;
3006         }
3007
3008         for (i=0;i<50000;i++) {
3009                 struct tevent_req *req;
3010
3011                 req = smbXcli_negprot_send(ev, ev, cli->conn, cli->timeout,
3012                                            PROTOCOL_CORE, PROTOCOL_NT1, 0);
3013                 if (req == NULL) {
3014                         TALLOC_FREE(ev);
3015                         return false;
3016                 }
3017                 if (!tevent_req_poll(req, ev)) {
3018                         d_fprintf(stderr, "tevent_req_poll failed: %s\n",
3019                                   strerror(errno));
3020                         TALLOC_FREE(ev);
3021                         return false;
3022                 }
3023                 TALLOC_FREE(req);
3024         }
3025
3026         if (torture_close_connection(cli)) {
3027                 correct = False;
3028         }
3029
3030         printf("finished negprot nowait test\n");
3031
3032         return correct;
3033 }
3034
3035 /* send smb negprot commands, not reading the response */
3036 static bool run_bad_nbt_session(int dummy)
3037 {
3038         struct nmb_name called, calling;
3039         struct sockaddr_storage ss;
3040         NTSTATUS status;
3041         int fd;
3042         bool ret;
3043
3044         printf("starting bad nbt session test\n");
3045
3046         make_nmb_name(&calling, myname, 0x0);
3047         make_nmb_name(&called , host, 0x20);
3048
3049         if (!resolve_name(host, &ss, 0x20, true)) {
3050                 d_fprintf(stderr, "Could not resolve name %s\n", host);
3051                 return false;
3052         }
3053
3054         status = open_socket_out(&ss, NBT_SMB_PORT, 10000, &fd);
3055         if (!NT_STATUS_IS_OK(status)) {
3056                 d_fprintf(stderr, "open_socket_out failed: %s\n",
3057                           nt_errstr(status));
3058                 return false;
3059         }
3060
3061         ret = cli_bad_session_request(fd, &calling, &called);
3062         close(fd);
3063         if (!ret) {
3064                 d_fprintf(stderr, "open_socket_out failed: %s\n",
3065                           nt_errstr(status));
3066                 return false;
3067         }
3068
3069         printf("finished bad nbt session test\n");
3070         return true;
3071 }
3072
3073 /* send random IPC commands */
3074 static bool run_randomipc(int dummy)
3075 {
3076         char *rparam = NULL;
3077         char *rdata = NULL;
3078         unsigned int rdrcnt,rprcnt;
3079         char param[1024];
3080         int api, param_len, i;
3081         struct cli_state *cli;
3082         bool correct = True;
3083         int count = 50000;
3084
3085         printf("starting random ipc test\n");
3086
3087         if (!torture_open_connection(&cli, 0)) {
3088                 return False;
3089         }
3090
3091         for (i=0;i<count;i++) {
3092                 api = sys_random() % 500;
3093                 param_len = (sys_random() % 64);
3094
3095                 rand_buf(param, param_len);
3096
3097                 SSVAL(param,0,api); 
3098
3099                 cli_api(cli, 
3100                         param, param_len, 8,  
3101                         NULL, 0, CLI_BUFFER_SIZE,
3102                         &rparam, &rprcnt,     
3103                         &rdata, &rdrcnt);
3104                 if (i % 100 == 0) {
3105                         printf("%d/%d\r", i,count);
3106                 }
3107         }
3108         printf("%d/%d\n", i, count);
3109
3110         if (!torture_close_connection(cli)) {
3111                 correct = False;
3112         }
3113
3114         SAFE_FREE(rparam);
3115         SAFE_FREE(rdata);
3116
3117         printf("finished random ipc test\n");
3118
3119         return correct;
3120 }
3121
3122
3123
3124 static void browse_callback(const char *sname, uint32_t stype,
3125                             const char *comment, void *state)
3126 {
3127         printf("\t%20.20s %08x %s\n", sname, stype, comment);
3128 }
3129
3130
3131