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