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