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