s3-torture: rw_torture3(): replace cli_read_old() with cli_read()
[Samba/gebeck_regimport.git] / source3 / torture / torture.c
blobb17171138fbc91cf1ee7dc7f8d0108c8009f07fe
1 /*
2 Unix SMB/CIFS implementation.
3 SMB torture tester
4 Copyright (C) Andrew Tridgell 1997-1998
5 Copyright (C) Jeremy Allison 2009
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.
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.
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/>.
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.h"
32 #include "talloc_dict.h"
33 #include "async_smb.h"
34 #include "libsmb/libsmb.h"
35 #include "libsmb/clirap.h"
36 #include "trans2.h"
37 #include "libsmb/nmblib.h"
38 #include "../lib/util/tevent_ntstatus.h"
39 #include "util_tdb.h"
40 #include "libsmb/read_smb.h"
42 extern char *optarg;
43 extern int optind;
45 fstring host, workgroup, share, password, username, myname;
46 static int max_protocol = PROTOCOL_NT1;
47 static const char *sockops="TCP_NODELAY";
48 static int nprocs=1;
49 static int port_to_use=0;
50 int torture_numops=100;
51 int torture_blocksize=1024*1024;
52 static int procnum; /* records process count number when forking */
53 static struct cli_state *current_cli;
54 static fstring randomfname;
55 static bool use_oplocks;
56 static bool use_level_II_oplocks;
57 static const char *client_txt = "client_oplocks.txt";
58 static bool use_kerberos;
59 static fstring multishare_conn_fname;
60 static bool use_multishare_conn = False;
61 static bool do_encrypt;
62 static const char *local_path = NULL;
63 static int signing_state = Undefined;
64 char *test_filename;
66 bool torture_showall = False;
68 static double create_procs(bool (*fn)(int), bool *result);
71 /* return a pointer to a anonymous shared memory segment of size "size"
72 which will persist across fork() but will disappear when all processes
73 exit
75 The memory is not zeroed
77 This function uses system5 shared memory. It takes advantage of a property
78 that the memory is not destroyed if it is attached when the id is removed
80 void *shm_setup(int size)
82 int shmid;
83 void *ret;
85 #ifdef __QNXNTO__
86 shmid = shm_open("private", O_RDWR | O_CREAT | O_EXCL, S_IRUSR | S_IWUSR);
87 if (shmid == -1) {
88 printf("can't get shared memory\n");
89 exit(1);
91 shm_unlink("private");
92 if (ftruncate(shmid, size) == -1) {
93 printf("can't set shared memory size\n");
94 exit(1);
96 ret = mmap(0, size, PROT_READ | PROT_WRITE, MAP_SHARED, shmid, 0);
97 if (ret == MAP_FAILED) {
98 printf("can't map shared memory\n");
99 exit(1);
101 #else
102 shmid = shmget(IPC_PRIVATE, size, S_IRUSR | S_IWUSR);
103 if (shmid == -1) {
104 printf("can't get shared memory\n");
105 exit(1);
107 ret = (void *)shmat(shmid, 0, 0);
108 if (!ret || ret == (void *)-1) {
109 printf("can't attach to shared memory\n");
110 return NULL;
112 /* the following releases the ipc, but note that this process
113 and all its children will still have access to the memory, its
114 just that the shmid is no longer valid for other shm calls. This
115 means we don't leave behind lots of shm segments after we exit
117 See Stevens "advanced programming in unix env" for details
119 shmctl(shmid, IPC_RMID, 0);
120 #endif
122 return ret;
125 /********************************************************************
126 Ensure a connection is encrypted.
127 ********************************************************************/
129 static bool force_cli_encryption(struct cli_state *c,
130 const char *sharename)
132 uint16 major, minor;
133 uint32 caplow, caphigh;
134 NTSTATUS status;
136 if (!SERVER_HAS_UNIX_CIFS(c)) {
137 d_printf("Encryption required and "
138 "server that doesn't support "
139 "UNIX extensions - failing connect\n");
140 return false;
143 status = cli_unix_extensions_version(c, &major, &minor, &caplow,
144 &caphigh);
145 if (!NT_STATUS_IS_OK(status)) {
146 d_printf("Encryption required and "
147 "can't get UNIX CIFS extensions "
148 "version from server: %s\n", nt_errstr(status));
149 return false;
152 if (!(caplow & CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP)) {
153 d_printf("Encryption required and "
154 "share %s doesn't support "
155 "encryption.\n", sharename);
156 return false;
159 if (c->use_kerberos) {
160 status = cli_gss_smb_encryption_start(c);
161 } else {
162 status = cli_raw_ntlm_smb_encryption_start(c,
163 username,
164 password,
165 workgroup);
168 if (!NT_STATUS_IS_OK(status)) {
169 d_printf("Encryption required and "
170 "setup failed with error %s.\n",
171 nt_errstr(status));
172 return false;
175 return true;
179 static struct cli_state *open_nbt_connection(void)
181 struct cli_state *c;
182 NTSTATUS status;
184 status = cli_connect_nb(host, NULL, port_to_use, 0x20, myname,
185 signing_state, &c);
186 if (!NT_STATUS_IS_OK(status)) {
187 printf("Failed to connect with %s. Error %s\n", host, nt_errstr(status) );
188 return NULL;
191 c->use_kerberos = use_kerberos;
193 c->timeout = 120000; /* set a really long timeout (2 minutes) */
194 if (use_oplocks) c->use_oplocks = True;
195 if (use_level_II_oplocks) c->use_level_II_oplocks = True;
197 return c;
200 /****************************************************************************
201 Send a corrupt session request. See rfc1002.txt 4.3 and 4.3.2.
202 ****************************************************************************/
204 static bool cli_bad_session_request(int fd,
205 struct nmb_name *calling, struct nmb_name *called)
207 TALLOC_CTX *frame;
208 uint8_t len_buf[4];
209 struct iovec iov[3];
210 ssize_t len;
211 uint8_t *inbuf;
212 int err;
213 bool ret = false;
214 uint8_t message_type;
215 uint8_t error;
217 frame = talloc_stackframe();
219 iov[0].iov_base = len_buf;
220 iov[0].iov_len = sizeof(len_buf);
222 /* put in the destination name */
224 iov[1].iov_base = name_mangle(talloc_tos(), called->name,
225 called->name_type);
226 if (iov[1].iov_base == NULL) {
227 goto fail;
229 iov[1].iov_len = name_len((unsigned char *)iov[1].iov_base,
230 talloc_get_size(iov[1].iov_base));
232 /* and my name */
234 iov[2].iov_base = name_mangle(talloc_tos(), calling->name,
235 calling->name_type);
236 if (iov[2].iov_base == NULL) {
237 goto fail;
239 iov[2].iov_len = name_len((unsigned char *)iov[2].iov_base,
240 talloc_get_size(iov[2].iov_base));
242 /* Deliberately corrupt the name len (first byte) */
243 *((uint8_t *)iov[2].iov_base) = 100;
245 /* send a session request (RFC 1002) */
246 /* setup the packet length
247 * Remove four bytes from the length count, since the length
248 * field in the NBT Session Service header counts the number
249 * of bytes which follow. The cli_send_smb() function knows
250 * about this and accounts for those four bytes.
251 * CRH.
254 _smb_setlen(len_buf, iov[1].iov_len + iov[2].iov_len);
255 SCVAL(len_buf,0,0x81);
257 len = write_data_iov(fd, iov, 3);
258 if (len == -1) {
259 goto fail;
261 len = read_smb(fd, talloc_tos(), &inbuf, &err);
262 if (len == -1) {
263 errno = err;
264 goto fail;
267 message_type = CVAL(inbuf, 0);
268 if (message_type != 0x83) {
269 d_fprintf(stderr, "Expected msg type 0x83, got 0x%2.2x\n",
270 message_type);
271 goto fail;
274 if (smb_len(inbuf) != 1) {
275 d_fprintf(stderr, "Expected smb_len 1, got %d\n",
276 (int)smb_len(inbuf));
277 goto fail;
280 error = CVAL(inbuf, 4);
281 if (error != 0x82) {
282 d_fprintf(stderr, "Expected error 0x82, got %d\n",
283 (int)error);
284 goto fail;
287 ret = true;
288 fail:
289 TALLOC_FREE(frame);
290 return ret;
293 /* Insert a NULL at the first separator of the given path and return a pointer
294 * to the remainder of the string.
296 static char *
297 terminate_path_at_separator(char * path)
299 char * p;
301 if (!path) {
302 return NULL;
305 if ((p = strchr_m(path, '/'))) {
306 *p = '\0';
307 return p + 1;
310 if ((p = strchr_m(path, '\\'))) {
311 *p = '\0';
312 return p + 1;
315 /* No separator. */
316 return NULL;
320 parse a //server/share type UNC name
322 bool smbcli_parse_unc(const char *unc_name, TALLOC_CTX *mem_ctx,
323 char **hostname, char **sharename)
325 char *p;
327 *hostname = *sharename = NULL;
329 if (strncmp(unc_name, "\\\\", 2) &&
330 strncmp(unc_name, "//", 2)) {
331 return False;
334 *hostname = talloc_strdup(mem_ctx, &unc_name[2]);
335 p = terminate_path_at_separator(*hostname);
337 if (p && *p) {
338 *sharename = talloc_strdup(mem_ctx, p);
339 terminate_path_at_separator(*sharename);
342 if (*hostname && *sharename) {
343 return True;
346 TALLOC_FREE(*hostname);
347 TALLOC_FREE(*sharename);
348 return False;
351 static bool torture_open_connection_share(struct cli_state **c,
352 const char *hostname,
353 const char *sharename)
355 int flags = 0;
356 NTSTATUS status;
358 if (use_kerberos)
359 flags |= CLI_FULL_CONNECTION_USE_KERBEROS;
360 if (use_oplocks)
361 flags |= CLI_FULL_CONNECTION_OPLOCKS;
362 if (use_level_II_oplocks)
363 flags |= CLI_FULL_CONNECTION_LEVEL_II_OPLOCKS;
365 status = cli_full_connection(c, myname,
366 hostname, NULL, port_to_use,
367 sharename, "?????",
368 username, workgroup,
369 password, flags, signing_state);
370 if (!NT_STATUS_IS_OK(status)) {
371 printf("failed to open share connection: //%s/%s port:%d - %s\n",
372 hostname, sharename, port_to_use, nt_errstr(status));
373 return False;
376 (*c)->timeout = 120000; /* set a really long timeout (2 minutes) */
378 if (do_encrypt) {
379 return force_cli_encryption(*c,
380 sharename);
382 return True;
385 bool torture_open_connection(struct cli_state **c, int conn_index)
387 char **unc_list = NULL;
388 int num_unc_names = 0;
389 bool result;
391 if (use_multishare_conn==True) {
392 char *h, *s;
393 unc_list = file_lines_load(multishare_conn_fname, &num_unc_names, 0, NULL);
394 if (!unc_list || num_unc_names <= 0) {
395 printf("Failed to load unc names list from '%s'\n", multishare_conn_fname);
396 exit(1);
399 if (!smbcli_parse_unc(unc_list[conn_index % num_unc_names],
400 NULL, &h, &s)) {
401 printf("Failed to parse UNC name %s\n",
402 unc_list[conn_index % num_unc_names]);
403 TALLOC_FREE(unc_list);
404 exit(1);
407 result = torture_open_connection_share(c, h, s);
409 /* h, s were copied earlier */
410 TALLOC_FREE(unc_list);
411 return result;
414 return torture_open_connection_share(c, host, share);
417 bool torture_init_connection(struct cli_state **pcli)
419 struct cli_state *cli;
421 cli = open_nbt_connection();
422 if (cli == NULL) {
423 return false;
426 *pcli = cli;
427 return true;
430 bool torture_cli_session_setup2(struct cli_state *cli, uint16 *new_vuid)
432 uint16 old_vuid = cli->vuid;
433 fstring old_user_name;
434 size_t passlen = strlen(password);
435 NTSTATUS status;
436 bool ret;
438 fstrcpy(old_user_name, cli->user_name);
439 cli->vuid = 0;
440 ret = NT_STATUS_IS_OK(cli_session_setup(cli, username,
441 password, passlen,
442 password, passlen,
443 workgroup));
444 *new_vuid = cli->vuid;
445 cli->vuid = old_vuid;
446 status = cli_set_username(cli, old_user_name);
447 if (!NT_STATUS_IS_OK(status)) {
448 return false;
450 return ret;
454 bool torture_close_connection(struct cli_state *c)
456 bool ret = True;
457 NTSTATUS status;
459 status = cli_tdis(c);
460 if (!NT_STATUS_IS_OK(status)) {
461 printf("tdis failed (%s)\n", nt_errstr(status));
462 ret = False;
465 cli_shutdown(c);
467 return ret;
471 /* check if the server produced the expected dos or nt error code */
472 static bool check_both_error(int line, NTSTATUS status,
473 uint8 eclass, uint32 ecode, NTSTATUS nterr)
475 if (NT_STATUS_IS_DOS(status)) {
476 uint8 cclass;
477 uint32 num;
479 /* Check DOS error */
480 cclass = NT_STATUS_DOS_CLASS(status);
481 num = NT_STATUS_DOS_CODE(status);
483 if (eclass != cclass || ecode != num) {
484 printf("unexpected error code class=%d code=%d\n",
485 (int)cclass, (int)num);
486 printf(" expected %d/%d %s (line=%d)\n",
487 (int)eclass, (int)ecode, nt_errstr(nterr), line);
488 return false;
490 } else {
491 /* Check NT error */
492 if (!NT_STATUS_EQUAL(nterr, status)) {
493 printf("unexpected error code %s\n",
494 nt_errstr(status));
495 printf(" expected %s (line=%d)\n",
496 nt_errstr(nterr), line);
497 return false;
501 return true;
505 /* check if the server produced the expected error code */
506 static bool check_error(int line, struct cli_state *c,
507 uint8 eclass, uint32 ecode, NTSTATUS nterr)
509 if (cli_is_dos_error(c)) {
510 uint8 cclass;
511 uint32 num;
513 /* Check DOS error */
515 cli_dos_error(c, &cclass, &num);
517 if (eclass != cclass || ecode != num) {
518 printf("unexpected error code class=%d code=%d\n",
519 (int)cclass, (int)num);
520 printf(" expected %d/%d %s (line=%d)\n",
521 (int)eclass, (int)ecode, nt_errstr(nterr), line);
522 return False;
525 } else {
526 NTSTATUS status;
528 /* Check NT error */
530 status = cli_nt_error(c);
532 if (NT_STATUS_V(nterr) != NT_STATUS_V(status)) {
533 printf("unexpected error code %s\n", nt_errstr(status));
534 printf(" expected %s (line=%d)\n", nt_errstr(nterr), line);
535 return False;
539 return True;
543 static bool wait_lock(struct cli_state *c, int fnum, uint32 offset, uint32 len)
545 NTSTATUS status;
547 status = cli_lock32(c, fnum, offset, len, -1, WRITE_LOCK);
549 while (!NT_STATUS_IS_OK(status)) {
550 if (!check_both_error(__LINE__, status, ERRDOS,
551 ERRlock, NT_STATUS_LOCK_NOT_GRANTED)) {
552 return false;
555 status = cli_lock32(c, fnum, offset, len, -1, WRITE_LOCK);
558 return true;
562 static bool rw_torture(struct cli_state *c)
564 const char *lockfname = "\\torture.lck";
565 fstring fname;
566 uint16_t fnum;
567 uint16_t fnum2;
568 pid_t pid2, pid = getpid();
569 int i, j;
570 char buf[1024];
571 bool correct = True;
572 size_t nread = 0;
573 NTSTATUS status;
575 memset(buf, '\0', sizeof(buf));
577 status = cli_open(c, lockfname, O_RDWR | O_CREAT | O_EXCL,
578 DENY_NONE, &fnum2);
579 if (!NT_STATUS_IS_OK(status)) {
580 status = cli_open(c, lockfname, O_RDWR, DENY_NONE, &fnum2);
582 if (!NT_STATUS_IS_OK(status)) {
583 printf("open of %s failed (%s)\n",
584 lockfname, nt_errstr(status));
585 return False;
588 for (i=0;i<torture_numops;i++) {
589 unsigned n = (unsigned)sys_random()%10;
591 if (i % 10 == 0) {
592 printf("%d\r", i); fflush(stdout);
594 slprintf(fname, sizeof(fstring) - 1, "\\torture.%u", n);
596 if (!wait_lock(c, fnum2, n*sizeof(int), sizeof(int))) {
597 return False;
600 status = cli_open(c, fname, O_RDWR | O_CREAT | O_TRUNC,
601 DENY_ALL, &fnum);
602 if (!NT_STATUS_IS_OK(status)) {
603 printf("open failed (%s)\n", nt_errstr(status));
604 correct = False;
605 break;
608 status = cli_writeall(c, fnum, 0, (uint8_t *)&pid, 0,
609 sizeof(pid), NULL);
610 if (!NT_STATUS_IS_OK(status)) {
611 printf("write failed (%s)\n", nt_errstr(status));
612 correct = False;
615 for (j=0;j<50;j++) {
616 status = cli_writeall(c, fnum, 0, (uint8_t *)buf,
617 sizeof(pid)+(j*sizeof(buf)),
618 sizeof(buf), NULL);
619 if (!NT_STATUS_IS_OK(status)) {
620 printf("write failed (%s)\n",
621 nt_errstr(status));
622 correct = False;
626 pid2 = 0;
628 status = cli_read(c, fnum, (char *)&pid2, 0, sizeof(pid),
629 &nread);
630 if (!NT_STATUS_IS_OK(status)) {
631 printf("read failed (%s)\n", nt_errstr(status));
632 correct = false;
633 } else if (nread != sizeof(pid)) {
634 printf("read/write compare failed: "
635 "recv %ld req %ld\n", (unsigned long)nread,
636 (unsigned long)sizeof(pid));
637 correct = false;
640 if (pid2 != pid) {
641 printf("data corruption!\n");
642 correct = False;
645 status = cli_close(c, fnum);
646 if (!NT_STATUS_IS_OK(status)) {
647 printf("close failed (%s)\n", nt_errstr(status));
648 correct = False;
651 status = cli_unlink(c, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
652 if (!NT_STATUS_IS_OK(status)) {
653 printf("unlink failed (%s)\n", nt_errstr(status));
654 correct = False;
657 status = cli_unlock(c, fnum2, n*sizeof(int), sizeof(int));
658 if (!NT_STATUS_IS_OK(status)) {
659 printf("unlock failed (%s)\n", nt_errstr(status));
660 correct = False;
664 cli_close(c, fnum2);
665 cli_unlink(c, lockfname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
667 printf("%d\n", i);
669 return correct;
672 static bool run_torture(int dummy)
674 struct cli_state *cli;
675 bool ret;
677 cli = current_cli;
679 cli_sockopt(cli, sockops);
681 ret = rw_torture(cli);
683 if (!torture_close_connection(cli)) {
684 ret = False;
687 return ret;
690 static bool rw_torture3(struct cli_state *c, char *lockfname)
692 uint16_t fnum = (uint16_t)-1;
693 unsigned int i = 0;
694 char buf[131072];
695 char buf_rd[131072];
696 unsigned count;
697 unsigned countprev = 0;
698 size_t sent = 0;
699 bool correct = True;
700 NTSTATUS status = NT_STATUS_OK;
702 srandom(1);
703 for (i = 0; i < sizeof(buf); i += sizeof(uint32))
705 SIVAL(buf, i, sys_random());
708 if (procnum == 0)
710 status = cli_unlink(
711 c, lockfname,
712 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
713 if (!NT_STATUS_IS_OK(status)) {
714 printf("unlink failed (%s) (normal, this file should "
715 "not exist)\n", nt_errstr(status));
718 status = cli_open(c, lockfname, O_RDWR | O_CREAT | O_EXCL,
719 DENY_NONE, &fnum);
720 if (!NT_STATUS_IS_OK(status)) {
721 printf("first open read/write of %s failed (%s)\n",
722 lockfname, nt_errstr(status));
723 return False;
726 else
728 for (i = 0; i < 500 && fnum == (uint16_t)-1; i++)
730 status = cli_open(c, lockfname, O_RDONLY,
731 DENY_NONE, &fnum);
732 if (!NT_STATUS_IS_OK(status)) {
733 break;
735 smb_msleep(10);
737 if (!NT_STATUS_IS_OK(status)) {
738 printf("second open read-only of %s failed (%s)\n",
739 lockfname, nt_errstr(status));
740 return False;
744 i = 0;
745 for (count = 0; count < sizeof(buf); count += sent)
747 if (count >= countprev) {
748 printf("%d %8d\r", i, count);
749 fflush(stdout);
750 i++;
751 countprev += (sizeof(buf) / 20);
754 if (procnum == 0)
756 sent = ((unsigned)sys_random()%(20))+ 1;
757 if (sent > sizeof(buf) - count)
759 sent = sizeof(buf) - count;
762 status = cli_writeall(c, fnum, 0, (uint8_t *)buf+count,
763 count, sent, NULL);
764 if (!NT_STATUS_IS_OK(status)) {
765 printf("write failed (%s)\n",
766 nt_errstr(status));
767 correct = False;
770 else
772 status = cli_read(c, fnum, buf_rd+count, count,
773 sizeof(buf)-count, &sent);
774 if(!NT_STATUS_IS_OK(status)) {
775 printf("read failed offset:%d size:%ld (%s)\n",
776 count, (unsigned long)sizeof(buf)-count,
777 nt_errstr(status));
778 correct = False;
779 sent = 0;
780 } else if (sent > 0) {
781 if (memcmp(buf_rd+count, buf+count, sent) != 0)
783 printf("read/write compare failed\n");
784 printf("offset: %d req %ld recvd %ld\n", count, (unsigned long)sizeof(buf)-count, (unsigned long)sent);
785 correct = False;
786 break;
793 status = cli_close(c, fnum);
794 if (!NT_STATUS_IS_OK(status)) {
795 printf("close failed (%s)\n", nt_errstr(status));
796 correct = False;
799 return correct;
802 static bool rw_torture2(struct cli_state *c1, struct cli_state *c2)
804 const char *lockfname = "\\torture2.lck";
805 uint16_t fnum1;
806 uint16_t fnum2;
807 int i;
808 char buf[131072];
809 char buf_rd[131072];
810 bool correct = True;
811 ssize_t bytes_read;
812 NTSTATUS status;
814 status = cli_unlink(c1, lockfname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
815 if (!NT_STATUS_IS_OK(status)) {
816 printf("unlink failed (%s) (normal, this file should not exist)\n", nt_errstr(status));
819 status = cli_open(c1, lockfname, O_RDWR | O_CREAT | O_EXCL,
820 DENY_NONE, &fnum1);
821 if (!NT_STATUS_IS_OK(status)) {
822 printf("first open read/write of %s failed (%s)\n",
823 lockfname, nt_errstr(status));
824 return False;
827 status = cli_open(c2, lockfname, O_RDONLY, DENY_NONE, &fnum2);
828 if (!NT_STATUS_IS_OK(status)) {
829 printf("second open read-only of %s failed (%s)\n",
830 lockfname, nt_errstr(status));
831 cli_close(c1, fnum1);
832 return False;
835 for (i = 0; i < torture_numops; i++)
837 size_t buf_size = ((unsigned)sys_random()%(sizeof(buf)-1))+ 1;
838 if (i % 10 == 0) {
839 printf("%d\r", i); fflush(stdout);
842 generate_random_buffer((unsigned char *)buf, buf_size);
844 status = cli_writeall(c1, fnum1, 0, (uint8_t *)buf, 0,
845 buf_size, NULL);
846 if (!NT_STATUS_IS_OK(status)) {
847 printf("write failed (%s)\n", nt_errstr(status));
848 correct = False;
849 break;
852 if ((bytes_read = cli_read_old(c2, fnum2, buf_rd, 0, buf_size)) != buf_size) {
853 printf("read failed (%s)\n", cli_errstr(c2));
854 printf("read %d, expected %ld\n", (int)bytes_read,
855 (unsigned long)buf_size);
856 correct = False;
857 break;
860 if (memcmp(buf_rd, buf, buf_size) != 0)
862 printf("read/write compare failed\n");
863 correct = False;
864 break;
868 status = cli_close(c2, fnum2);
869 if (!NT_STATUS_IS_OK(status)) {
870 printf("close failed (%s)\n", nt_errstr(status));
871 correct = False;
874 status = cli_close(c1, fnum1);
875 if (!NT_STATUS_IS_OK(status)) {
876 printf("close failed (%s)\n", nt_errstr(status));
877 correct = False;
880 status = cli_unlink(c1, lockfname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
881 if (!NT_STATUS_IS_OK(status)) {
882 printf("unlink failed (%s)\n", nt_errstr(status));
883 correct = False;
886 return correct;
889 static bool run_readwritetest(int dummy)
891 struct cli_state *cli1, *cli2;
892 bool test1, test2 = False;
894 if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
895 return False;
897 cli_sockopt(cli1, sockops);
898 cli_sockopt(cli2, sockops);
900 printf("starting readwritetest\n");
902 test1 = rw_torture2(cli1, cli2);
903 printf("Passed readwritetest v1: %s\n", BOOLSTR(test1));
905 if (test1) {
906 test2 = rw_torture2(cli1, cli1);
907 printf("Passed readwritetest v2: %s\n", BOOLSTR(test2));
910 if (!torture_close_connection(cli1)) {
911 test1 = False;
914 if (!torture_close_connection(cli2)) {
915 test2 = False;
918 return (test1 && test2);
921 static bool run_readwritemulti(int dummy)
923 struct cli_state *cli;
924 bool test;
926 cli = current_cli;
928 cli_sockopt(cli, sockops);
930 printf("run_readwritemulti: fname %s\n", randomfname);
931 test = rw_torture3(cli, randomfname);
933 if (!torture_close_connection(cli)) {
934 test = False;
937 return test;
940 static bool run_readwritelarge_internal(int max_xmit_k)
942 static struct cli_state *cli1;
943 uint16_t fnum1;
944 const char *lockfname = "\\large.dat";
945 SMB_OFF_T fsize;
946 char buf[126*1024];
947 bool correct = True;
948 NTSTATUS status;
950 if (!torture_open_connection(&cli1, 0)) {
951 return False;
953 cli_sockopt(cli1, sockops);
954 memset(buf,'\0',sizeof(buf));
956 cli1->max_xmit = max_xmit_k*1024;
958 if (signing_state == Required) {
959 /* Horrible cheat to force
960 multiple signed outstanding
961 packets against a Samba server.
963 cli1->is_samba = false;
966 printf("starting readwritelarge_internal\n");
968 cli_unlink(cli1, lockfname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
970 status = cli_open(cli1, lockfname, O_RDWR | O_CREAT | O_EXCL,
971 DENY_NONE, &fnum1);
972 if (!NT_STATUS_IS_OK(status)) {
973 printf("open read/write of %s failed (%s)\n", lockfname, nt_errstr(status));
974 return False;
977 cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 0, sizeof(buf), NULL);
979 status = cli_qfileinfo_basic(cli1, fnum1, NULL, &fsize, NULL, NULL,
980 NULL, NULL, NULL);
981 if (!NT_STATUS_IS_OK(status)) {
982 printf("qfileinfo failed (%s)\n", nt_errstr(status));
983 correct = False;
986 if (fsize == sizeof(buf))
987 printf("readwritelarge_internal test 1 succeeded (size = %lx)\n",
988 (unsigned long)fsize);
989 else {
990 printf("readwritelarge_internal test 1 failed (size = %lx)\n",
991 (unsigned long)fsize);
992 correct = False;
995 status = cli_close(cli1, fnum1);
996 if (!NT_STATUS_IS_OK(status)) {
997 printf("close failed (%s)\n", nt_errstr(status));
998 correct = False;
1001 status = cli_unlink(cli1, lockfname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1002 if (!NT_STATUS_IS_OK(status)) {
1003 printf("unlink failed (%s)\n", nt_errstr(status));
1004 correct = False;
1007 status = cli_open(cli1, lockfname, O_RDWR | O_CREAT | O_EXCL,
1008 DENY_NONE, &fnum1);
1009 if (!NT_STATUS_IS_OK(status)) {
1010 printf("open read/write of %s failed (%s)\n", lockfname, nt_errstr(status));
1011 return False;
1014 cli1->max_xmit = 4*1024;
1016 cli_smbwrite(cli1, fnum1, buf, 0, sizeof(buf), NULL);
1018 status = cli_qfileinfo_basic(cli1, fnum1, NULL, &fsize, NULL, NULL,
1019 NULL, NULL, NULL);
1020 if (!NT_STATUS_IS_OK(status)) {
1021 printf("qfileinfo failed (%s)\n", nt_errstr(status));
1022 correct = False;
1025 if (fsize == sizeof(buf))
1026 printf("readwritelarge_internal test 2 succeeded (size = %lx)\n",
1027 (unsigned long)fsize);
1028 else {
1029 printf("readwritelarge_internal test 2 failed (size = %lx)\n",
1030 (unsigned long)fsize);
1031 correct = False;
1034 #if 0
1035 /* ToDo - set allocation. JRA */
1036 if(!cli_set_allocation_size(cli1, fnum1, 0)) {
1037 printf("set allocation size to zero failed (%s)\n", cli_errstr(&cli1));
1038 return False;
1040 if (!cli_qfileinfo_basic(cli1, fnum1, NULL, &fsize, NULL, NULL, NULL,
1041 NULL, NULL)) {
1042 printf("qfileinfo failed (%s)\n", cli_errstr(cli1));
1043 correct = False;
1045 if (fsize != 0)
1046 printf("readwritelarge test 3 (truncate test) succeeded (size = %x)\n", fsize);
1047 #endif
1049 status = cli_close(cli1, fnum1);
1050 if (!NT_STATUS_IS_OK(status)) {
1051 printf("close failed (%s)\n", nt_errstr(status));
1052 correct = False;
1055 if (!torture_close_connection(cli1)) {
1056 correct = False;
1058 return correct;
1061 static bool run_readwritelarge(int dummy)
1063 return run_readwritelarge_internal(128);
1066 static bool run_readwritelarge_signtest(int dummy)
1068 bool ret;
1069 signing_state = Required;
1070 ret = run_readwritelarge_internal(2);
1071 signing_state = Undefined;
1072 return ret;
1075 int line_count = 0;
1076 int nbio_id;
1078 #define ival(s) strtol(s, NULL, 0)
1080 /* run a test that simulates an approximate netbench client load */
1081 static bool run_netbench(int client)
1083 struct cli_state *cli;
1084 int i;
1085 char line[1024];
1086 char cname[20];
1087 FILE *f;
1088 const char *params[20];
1089 bool correct = True;
1091 cli = current_cli;
1093 nbio_id = client;
1095 cli_sockopt(cli, sockops);
1097 nb_setup(cli);
1099 slprintf(cname,sizeof(cname)-1, "client%d", client);
1101 f = fopen(client_txt, "r");
1103 if (!f) {
1104 perror(client_txt);
1105 return False;
1108 while (fgets(line, sizeof(line)-1, f)) {
1109 char *saveptr;
1110 line_count++;
1112 line[strlen(line)-1] = 0;
1114 /* printf("[%d] %s\n", line_count, line); */
1116 all_string_sub(line,"client1", cname, sizeof(line));
1118 /* parse the command parameters */
1119 params[0] = strtok_r(line, " ", &saveptr);
1120 i = 0;
1121 while (params[i]) params[++i] = strtok_r(NULL, " ", &saveptr);
1123 params[i] = "";
1125 if (i < 2) continue;
1127 if (!strncmp(params[0],"SMB", 3)) {
1128 printf("ERROR: You are using a dbench 1 load file\n");
1129 exit(1);
1132 if (!strcmp(params[0],"NTCreateX")) {
1133 nb_createx(params[1], ival(params[2]), ival(params[3]),
1134 ival(params[4]));
1135 } else if (!strcmp(params[0],"Close")) {
1136 nb_close(ival(params[1]));
1137 } else if (!strcmp(params[0],"Rename")) {
1138 nb_rename(params[1], params[2]);
1139 } else if (!strcmp(params[0],"Unlink")) {
1140 nb_unlink(params[1]);
1141 } else if (!strcmp(params[0],"Deltree")) {
1142 nb_deltree(params[1]);
1143 } else if (!strcmp(params[0],"Rmdir")) {
1144 nb_rmdir(params[1]);
1145 } else if (!strcmp(params[0],"QUERY_PATH_INFORMATION")) {
1146 nb_qpathinfo(params[1]);
1147 } else if (!strcmp(params[0],"QUERY_FILE_INFORMATION")) {
1148 nb_qfileinfo(ival(params[1]));
1149 } else if (!strcmp(params[0],"QUERY_FS_INFORMATION")) {
1150 nb_qfsinfo(ival(params[1]));
1151 } else if (!strcmp(params[0],"FIND_FIRST")) {
1152 nb_findfirst(params[1]);
1153 } else if (!strcmp(params[0],"WriteX")) {
1154 nb_writex(ival(params[1]),
1155 ival(params[2]), ival(params[3]), ival(params[4]));
1156 } else if (!strcmp(params[0],"ReadX")) {
1157 nb_readx(ival(params[1]),
1158 ival(params[2]), ival(params[3]), ival(params[4]));
1159 } else if (!strcmp(params[0],"Flush")) {
1160 nb_flush(ival(params[1]));
1161 } else {
1162 printf("Unknown operation %s\n", params[0]);
1163 exit(1);
1166 fclose(f);
1168 nb_cleanup();
1170 if (!torture_close_connection(cli)) {
1171 correct = False;
1174 return correct;
1178 /* run a test that simulates an approximate netbench client load */
1179 static bool run_nbench(int dummy)
1181 double t;
1182 bool correct = True;
1184 nbio_shmem(nprocs);
1186 nbio_id = -1;
1188 signal(SIGALRM, nb_alarm);
1189 alarm(1);
1190 t = create_procs(run_netbench, &correct);
1191 alarm(0);
1193 printf("\nThroughput %g MB/sec\n",
1194 1.0e-6 * nbio_total() / t);
1195 return correct;
1200 This test checks for two things:
1202 1) correct support for retaining locks over a close (ie. the server
1203 must not use posix semantics)
1204 2) support for lock timeouts
1206 static bool run_locktest1(int dummy)
1208 struct cli_state *cli1, *cli2;
1209 const char *fname = "\\lockt1.lck";
1210 uint16_t fnum1, fnum2, fnum3;
1211 time_t t1, t2;
1212 unsigned lock_timeout;
1213 NTSTATUS status;
1215 if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
1216 return False;
1218 cli_sockopt(cli1, sockops);
1219 cli_sockopt(cli2, sockops);
1221 printf("starting locktest1\n");
1223 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1225 status = cli_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
1226 &fnum1);
1227 if (!NT_STATUS_IS_OK(status)) {
1228 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
1229 return False;
1232 status = cli_open(cli1, fname, O_RDWR, DENY_NONE, &fnum2);
1233 if (!NT_STATUS_IS_OK(status)) {
1234 printf("open2 of %s failed (%s)\n", fname, nt_errstr(status));
1235 return False;
1238 status = cli_open(cli2, fname, O_RDWR, DENY_NONE, &fnum3);
1239 if (!NT_STATUS_IS_OK(status)) {
1240 printf("open3 of %s failed (%s)\n", fname, nt_errstr(status));
1241 return False;
1244 status = cli_lock32(cli1, fnum1, 0, 4, 0, WRITE_LOCK);
1245 if (!NT_STATUS_IS_OK(status)) {
1246 printf("lock1 failed (%s)\n", nt_errstr(status));
1247 return false;
1250 status = cli_lock32(cli2, fnum3, 0, 4, 0, WRITE_LOCK);
1251 if (NT_STATUS_IS_OK(status)) {
1252 printf("lock2 succeeded! This is a locking bug\n");
1253 return false;
1254 } else {
1255 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1256 NT_STATUS_LOCK_NOT_GRANTED)) {
1257 return false;
1261 lock_timeout = (1 + (random() % 20));
1262 printf("Testing lock timeout with timeout=%u\n", lock_timeout);
1263 t1 = time(NULL);
1264 status = cli_lock32(cli2, fnum3, 0, 4, lock_timeout * 1000, WRITE_LOCK);
1265 if (NT_STATUS_IS_OK(status)) {
1266 printf("lock3 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;
1274 t2 = time(NULL);
1276 if (ABS(t2 - t1) < lock_timeout-1) {
1277 printf("error: This server appears not to support timed lock requests\n");
1280 printf("server slept for %u seconds for a %u second timeout\n",
1281 (unsigned int)(t2-t1), lock_timeout);
1283 status = cli_close(cli1, fnum2);
1284 if (!NT_STATUS_IS_OK(status)) {
1285 printf("close1 failed (%s)\n", nt_errstr(status));
1286 return False;
1289 status = cli_lock32(cli2, fnum3, 0, 4, 0, WRITE_LOCK);
1290 if (NT_STATUS_IS_OK(status)) {
1291 printf("lock4 succeeded! This is a locking bug\n");
1292 return false;
1293 } else {
1294 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1295 NT_STATUS_FILE_LOCK_CONFLICT)) {
1296 return false;
1300 status = cli_close(cli1, fnum1);
1301 if (!NT_STATUS_IS_OK(status)) {
1302 printf("close2 failed (%s)\n", nt_errstr(status));
1303 return False;
1306 status = cli_close(cli2, fnum3);
1307 if (!NT_STATUS_IS_OK(status)) {
1308 printf("close3 failed (%s)\n", nt_errstr(status));
1309 return False;
1312 status = cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1313 if (!NT_STATUS_IS_OK(status)) {
1314 printf("unlink failed (%s)\n", nt_errstr(status));
1315 return False;
1319 if (!torture_close_connection(cli1)) {
1320 return False;
1323 if (!torture_close_connection(cli2)) {
1324 return False;
1327 printf("Passed locktest1\n");
1328 return True;
1332 this checks to see if a secondary tconx can use open files from an
1333 earlier tconx
1335 static bool run_tcon_test(int dummy)
1337 static struct cli_state *cli;
1338 const char *fname = "\\tcontest.tmp";
1339 uint16 fnum1;
1340 uint16 cnum1, cnum2, cnum3;
1341 uint16 vuid1, vuid2;
1342 char buf[4];
1343 bool ret = True;
1344 NTSTATUS status;
1346 memset(buf, '\0', sizeof(buf));
1348 if (!torture_open_connection(&cli, 0)) {
1349 return False;
1351 cli_sockopt(cli, sockops);
1353 printf("starting tcontest\n");
1355 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1357 status = cli_open(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
1358 if (!NT_STATUS_IS_OK(status)) {
1359 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
1360 return False;
1363 cnum1 = cli_state_get_tid(cli);
1364 vuid1 = cli->vuid;
1366 status = cli_writeall(cli, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
1367 if (!NT_STATUS_IS_OK(status)) {
1368 printf("initial write failed (%s)", nt_errstr(status));
1369 return False;
1372 status = cli_tcon_andx(cli, share, "?????",
1373 password, strlen(password)+1);
1374 if (!NT_STATUS_IS_OK(status)) {
1375 printf("%s refused 2nd tree connect (%s)\n", host,
1376 nt_errstr(status));
1377 cli_shutdown(cli);
1378 return False;
1381 cnum2 = cli_state_get_tid(cli);
1382 cnum3 = MAX(cnum1, cnum2) + 1; /* any invalid number */
1383 vuid2 = cli->vuid + 1;
1385 /* try a write with the wrong tid */
1386 cli_state_set_tid(cli, cnum2);
1388 status = cli_writeall(cli, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
1389 if (NT_STATUS_IS_OK(status)) {
1390 printf("* server allows write with wrong TID\n");
1391 ret = False;
1392 } else {
1393 printf("server fails write with wrong TID : %s\n",
1394 nt_errstr(status));
1398 /* try a write with an invalid tid */
1399 cli_state_set_tid(cli, cnum3);
1401 status = cli_writeall(cli, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
1402 if (NT_STATUS_IS_OK(status)) {
1403 printf("* server allows write with invalid TID\n");
1404 ret = False;
1405 } else {
1406 printf("server fails write with invalid TID : %s\n",
1407 nt_errstr(status));
1410 /* try a write with an invalid vuid */
1411 cli->vuid = vuid2;
1412 cli_state_set_tid(cli, cnum1);
1414 status = cli_writeall(cli, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
1415 if (NT_STATUS_IS_OK(status)) {
1416 printf("* server allows write with invalid VUID\n");
1417 ret = False;
1418 } else {
1419 printf("server fails write with invalid VUID : %s\n",
1420 nt_errstr(status));
1423 cli_state_set_tid(cli, cnum1);
1424 cli->vuid = vuid1;
1426 status = cli_close(cli, fnum1);
1427 if (!NT_STATUS_IS_OK(status)) {
1428 printf("close failed (%s)\n", nt_errstr(status));
1429 return False;
1432 cli_state_set_tid(cli, cnum2);
1434 status = cli_tdis(cli);
1435 if (!NT_STATUS_IS_OK(status)) {
1436 printf("secondary tdis failed (%s)\n", nt_errstr(status));
1437 return False;
1440 cli_state_set_tid(cli, cnum1);
1442 if (!torture_close_connection(cli)) {
1443 return False;
1446 return ret;
1451 checks for old style tcon support
1453 static bool run_tcon2_test(int dummy)
1455 static struct cli_state *cli;
1456 uint16 cnum, max_xmit;
1457 char *service;
1458 NTSTATUS status;
1460 if (!torture_open_connection(&cli, 0)) {
1461 return False;
1463 cli_sockopt(cli, sockops);
1465 printf("starting tcon2 test\n");
1467 if (asprintf(&service, "\\\\%s\\%s", host, share) == -1) {
1468 return false;
1471 status = cli_raw_tcon(cli, service, password, "?????", &max_xmit, &cnum);
1473 SAFE_FREE(service);
1475 if (!NT_STATUS_IS_OK(status)) {
1476 printf("tcon2 failed : %s\n", nt_errstr(status));
1477 } else {
1478 printf("tcon OK : max_xmit=%d cnum=%d\n",
1479 (int)max_xmit, (int)cnum);
1482 if (!torture_close_connection(cli)) {
1483 return False;
1486 printf("Passed tcon2 test\n");
1487 return True;
1490 static bool tcon_devtest(struct cli_state *cli,
1491 const char *myshare, const char *devtype,
1492 const char *return_devtype,
1493 NTSTATUS expected_error)
1495 NTSTATUS status;
1496 bool ret;
1498 status = cli_tcon_andx(cli, myshare, devtype,
1499 password, strlen(password)+1);
1501 if (NT_STATUS_IS_OK(expected_error)) {
1502 if (NT_STATUS_IS_OK(status)) {
1503 if (strcmp(cli->dev, return_devtype) == 0) {
1504 ret = True;
1505 } else {
1506 printf("tconX to share %s with type %s "
1507 "succeeded but returned the wrong "
1508 "device type (got [%s] but should have got [%s])\n",
1509 myshare, devtype, cli->dev, return_devtype);
1510 ret = False;
1512 } else {
1513 printf("tconX to share %s with type %s "
1514 "should have succeeded but failed\n",
1515 myshare, devtype);
1516 ret = False;
1518 cli_tdis(cli);
1519 } else {
1520 if (NT_STATUS_IS_OK(status)) {
1521 printf("tconx to share %s with type %s "
1522 "should have failed but succeeded\n",
1523 myshare, devtype);
1524 ret = False;
1525 } else {
1526 if (NT_STATUS_EQUAL(cli_nt_error(cli),
1527 expected_error)) {
1528 ret = True;
1529 } else {
1530 printf("Returned unexpected error\n");
1531 ret = False;
1535 return ret;
1539 checks for correct tconX support
1541 static bool run_tcon_devtype_test(int dummy)
1543 static struct cli_state *cli1 = NULL;
1544 int flags = 0;
1545 NTSTATUS status;
1546 bool ret = True;
1548 status = cli_full_connection(&cli1, myname,
1549 host, NULL, port_to_use,
1550 NULL, NULL,
1551 username, workgroup,
1552 password, flags, signing_state);
1554 if (!NT_STATUS_IS_OK(status)) {
1555 printf("could not open connection\n");
1556 return False;
1559 if (!tcon_devtest(cli1, "IPC$", "A:", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1560 ret = False;
1562 if (!tcon_devtest(cli1, "IPC$", "?????", "IPC", NT_STATUS_OK))
1563 ret = False;
1565 if (!tcon_devtest(cli1, "IPC$", "LPT:", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1566 ret = False;
1568 if (!tcon_devtest(cli1, "IPC$", "IPC", "IPC", NT_STATUS_OK))
1569 ret = False;
1571 if (!tcon_devtest(cli1, "IPC$", "FOOBA", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1572 ret = False;
1574 if (!tcon_devtest(cli1, share, "A:", "A:", NT_STATUS_OK))
1575 ret = False;
1577 if (!tcon_devtest(cli1, share, "?????", "A:", NT_STATUS_OK))
1578 ret = False;
1580 if (!tcon_devtest(cli1, share, "LPT:", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1581 ret = False;
1583 if (!tcon_devtest(cli1, share, "IPC", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1584 ret = False;
1586 if (!tcon_devtest(cli1, share, "FOOBA", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1587 ret = False;
1589 cli_shutdown(cli1);
1591 if (ret)
1592 printf("Passed tcondevtest\n");
1594 return ret;
1599 This test checks that
1601 1) the server supports multiple locking contexts on the one SMB
1602 connection, distinguished by PID.
1604 2) the server correctly fails overlapping locks made by the same PID (this
1605 goes against POSIX behaviour, which is why it is tricky to implement)
1607 3) the server denies unlock requests by an incorrect client PID
1609 static bool run_locktest2(int dummy)
1611 static struct cli_state *cli;
1612 const char *fname = "\\lockt2.lck";
1613 uint16_t fnum1, fnum2, fnum3;
1614 bool correct = True;
1615 NTSTATUS status;
1617 if (!torture_open_connection(&cli, 0)) {
1618 return False;
1621 cli_sockopt(cli, sockops);
1623 printf("starting locktest2\n");
1625 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1627 cli_setpid(cli, 1);
1629 status = cli_open(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
1630 if (!NT_STATUS_IS_OK(status)) {
1631 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
1632 return False;
1635 status = cli_open(cli, fname, O_RDWR, DENY_NONE, &fnum2);
1636 if (!NT_STATUS_IS_OK(status)) {
1637 printf("open2 of %s failed (%s)\n", fname, nt_errstr(status));
1638 return False;
1641 cli_setpid(cli, 2);
1643 status = cli_open(cli, fname, O_RDWR, DENY_NONE, &fnum3);
1644 if (!NT_STATUS_IS_OK(status)) {
1645 printf("open3 of %s failed (%s)\n", fname, nt_errstr(status));
1646 return False;
1649 cli_setpid(cli, 1);
1651 status = cli_lock32(cli, fnum1, 0, 4, 0, WRITE_LOCK);
1652 if (!NT_STATUS_IS_OK(status)) {
1653 printf("lock1 failed (%s)\n", nt_errstr(status));
1654 return false;
1657 status = cli_lock32(cli, fnum1, 0, 4, 0, WRITE_LOCK);
1658 if (NT_STATUS_IS_OK(status)) {
1659 printf("WRITE lock1 succeeded! This is a locking bug\n");
1660 correct = false;
1661 } else {
1662 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1663 NT_STATUS_LOCK_NOT_GRANTED)) {
1664 return false;
1668 status = cli_lock32(cli, fnum2, 0, 4, 0, WRITE_LOCK);
1669 if (NT_STATUS_IS_OK(status)) {
1670 printf("WRITE lock2 succeeded! This is a locking bug\n");
1671 correct = false;
1672 } else {
1673 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1674 NT_STATUS_LOCK_NOT_GRANTED)) {
1675 return false;
1679 status = cli_lock32(cli, fnum2, 0, 4, 0, READ_LOCK);
1680 if (NT_STATUS_IS_OK(status)) {
1681 printf("READ lock2 succeeded! This is a locking bug\n");
1682 correct = false;
1683 } else {
1684 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1685 NT_STATUS_FILE_LOCK_CONFLICT)) {
1686 return false;
1690 status = cli_lock32(cli, fnum1, 100, 4, 0, WRITE_LOCK);
1691 if (!NT_STATUS_IS_OK(status)) {
1692 printf("lock at 100 failed (%s)\n", nt_errstr(status));
1694 cli_setpid(cli, 2);
1695 if (NT_STATUS_IS_OK(cli_unlock(cli, fnum1, 100, 4))) {
1696 printf("unlock at 100 succeeded! This is a locking bug\n");
1697 correct = False;
1700 status = cli_unlock(cli, fnum1, 0, 4);
1701 if (NT_STATUS_IS_OK(status)) {
1702 printf("unlock1 succeeded! This is a locking bug\n");
1703 correct = false;
1704 } else {
1705 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1706 NT_STATUS_RANGE_NOT_LOCKED)) {
1707 return false;
1711 status = cli_unlock(cli, fnum1, 0, 8);
1712 if (NT_STATUS_IS_OK(status)) {
1713 printf("unlock2 succeeded! This is a locking bug\n");
1714 correct = false;
1715 } else {
1716 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1717 NT_STATUS_RANGE_NOT_LOCKED)) {
1718 return false;
1722 status = cli_lock32(cli, fnum3, 0, 4, 0, WRITE_LOCK);
1723 if (NT_STATUS_IS_OK(status)) {
1724 printf("lock3 succeeded! This is a locking bug\n");
1725 correct = false;
1726 } else {
1727 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1728 NT_STATUS_LOCK_NOT_GRANTED)) {
1729 return false;
1733 cli_setpid(cli, 1);
1735 status = cli_close(cli, fnum1);
1736 if (!NT_STATUS_IS_OK(status)) {
1737 printf("close1 failed (%s)\n", nt_errstr(status));
1738 return False;
1741 status = cli_close(cli, fnum2);
1742 if (!NT_STATUS_IS_OK(status)) {
1743 printf("close2 failed (%s)\n", nt_errstr(status));
1744 return False;
1747 status = cli_close(cli, fnum3);
1748 if (!NT_STATUS_IS_OK(status)) {
1749 printf("close3 failed (%s)\n", nt_errstr(status));
1750 return False;
1753 if (!torture_close_connection(cli)) {
1754 correct = False;
1757 printf("locktest2 finished\n");
1759 return correct;
1764 This test checks that
1766 1) the server supports the full offset range in lock requests
1768 static bool run_locktest3(int dummy)
1770 static struct cli_state *cli1, *cli2;
1771 const char *fname = "\\lockt3.lck";
1772 uint16_t fnum1, fnum2;
1773 int i;
1774 uint32 offset;
1775 bool correct = True;
1776 NTSTATUS status;
1778 #define NEXT_OFFSET offset += (~(uint32)0) / torture_numops
1780 if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
1781 return False;
1783 cli_sockopt(cli1, sockops);
1784 cli_sockopt(cli2, sockops);
1786 printf("starting locktest3\n");
1788 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1790 status = cli_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
1791 &fnum1);
1792 if (!NT_STATUS_IS_OK(status)) {
1793 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
1794 return False;
1797 status = cli_open(cli2, fname, O_RDWR, DENY_NONE, &fnum2);
1798 if (!NT_STATUS_IS_OK(status)) {
1799 printf("open2 of %s failed (%s)\n", fname, nt_errstr(status));
1800 return False;
1803 for (offset=i=0;i<torture_numops;i++) {
1804 NEXT_OFFSET;
1806 status = cli_lock32(cli1, fnum1, offset-1, 1, 0, WRITE_LOCK);
1807 if (!NT_STATUS_IS_OK(status)) {
1808 printf("lock1 %d failed (%s)\n",
1810 nt_errstr(status));
1811 return False;
1814 status = cli_lock32(cli2, fnum2, offset-2, 1, 0, WRITE_LOCK);
1815 if (!NT_STATUS_IS_OK(status)) {
1816 printf("lock2 %d failed (%s)\n",
1818 nt_errstr(status));
1819 return False;
1823 for (offset=i=0;i<torture_numops;i++) {
1824 NEXT_OFFSET;
1826 status = cli_lock32(cli1, fnum1, offset-2, 1, 0, WRITE_LOCK);
1827 if (NT_STATUS_IS_OK(status)) {
1828 printf("error: lock1 %d succeeded!\n", i);
1829 return False;
1832 status = cli_lock32(cli2, fnum2, offset-1, 1, 0, WRITE_LOCK);
1833 if (NT_STATUS_IS_OK(status)) {
1834 printf("error: lock2 %d succeeded!\n", i);
1835 return False;
1838 status = cli_lock32(cli1, fnum1, offset-1, 1, 0, WRITE_LOCK);
1839 if (NT_STATUS_IS_OK(status)) {
1840 printf("error: lock3 %d succeeded!\n", i);
1841 return False;
1844 status = cli_lock32(cli2, fnum2, offset-2, 1, 0, WRITE_LOCK);
1845 if (NT_STATUS_IS_OK(status)) {
1846 printf("error: lock4 %d succeeded!\n", i);
1847 return False;
1851 for (offset=i=0;i<torture_numops;i++) {
1852 NEXT_OFFSET;
1854 status = cli_unlock(cli1, fnum1, offset-1, 1);
1855 if (!NT_STATUS_IS_OK(status)) {
1856 printf("unlock1 %d failed (%s)\n",
1858 nt_errstr(status));
1859 return False;
1862 status = cli_unlock(cli2, fnum2, offset-2, 1);
1863 if (!NT_STATUS_IS_OK(status)) {
1864 printf("unlock2 %d failed (%s)\n",
1866 nt_errstr(status));
1867 return False;
1871 status = cli_close(cli1, fnum1);
1872 if (!NT_STATUS_IS_OK(status)) {
1873 printf("close1 failed (%s)\n", nt_errstr(status));
1874 return False;
1877 status = cli_close(cli2, fnum2);
1878 if (!NT_STATUS_IS_OK(status)) {
1879 printf("close2 failed (%s)\n", nt_errstr(status));
1880 return False;
1883 status = cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1884 if (!NT_STATUS_IS_OK(status)) {
1885 printf("unlink failed (%s)\n", nt_errstr(status));
1886 return False;
1889 if (!torture_close_connection(cli1)) {
1890 correct = False;
1893 if (!torture_close_connection(cli2)) {
1894 correct = False;
1897 printf("finished locktest3\n");
1899 return correct;
1902 #define EXPECTED(ret, v) if ((ret) != (v)) { \
1903 printf("** "); correct = False; \
1907 looks at overlapping locks
1909 static bool run_locktest4(int dummy)
1911 static struct cli_state *cli1, *cli2;
1912 const char *fname = "\\lockt4.lck";
1913 uint16_t fnum1, fnum2, f;
1914 bool ret;
1915 char buf[1000];
1916 bool correct = True;
1917 NTSTATUS status;
1919 if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
1920 return False;
1923 cli_sockopt(cli1, sockops);
1924 cli_sockopt(cli2, sockops);
1926 printf("starting locktest4\n");
1928 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1930 cli_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
1931 cli_open(cli2, fname, O_RDWR, DENY_NONE, &fnum2);
1933 memset(buf, 0, sizeof(buf));
1935 status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 0, sizeof(buf),
1936 NULL);
1937 if (!NT_STATUS_IS_OK(status)) {
1938 printf("Failed to create file: %s\n", nt_errstr(status));
1939 correct = False;
1940 goto fail;
1943 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 4, 0, WRITE_LOCK)) &&
1944 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 2, 4, 0, WRITE_LOCK));
1945 EXPECTED(ret, False);
1946 printf("the same process %s set overlapping write locks\n", ret?"can":"cannot");
1948 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 10, 4, 0, READ_LOCK)) &&
1949 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 12, 4, 0, READ_LOCK));
1950 EXPECTED(ret, True);
1951 printf("the same process %s set overlapping read locks\n", ret?"can":"cannot");
1953 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 20, 4, 0, WRITE_LOCK)) &&
1954 NT_STATUS_IS_OK(cli_lock32(cli2, fnum2, 22, 4, 0, WRITE_LOCK));
1955 EXPECTED(ret, False);
1956 printf("a different connection %s set overlapping write locks\n", ret?"can":"cannot");
1958 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 30, 4, 0, READ_LOCK)) &&
1959 NT_STATUS_IS_OK(cli_lock32(cli2, fnum2, 32, 4, 0, READ_LOCK));
1960 EXPECTED(ret, True);
1961 printf("a different connection %s set overlapping read locks\n", ret?"can":"cannot");
1963 ret = (cli_setpid(cli1, 1),
1964 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 40, 4, 0, WRITE_LOCK))) &&
1965 (cli_setpid(cli1, 2),
1966 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 42, 4, 0, WRITE_LOCK)));
1967 EXPECTED(ret, False);
1968 printf("a different pid %s set overlapping write locks\n", ret?"can":"cannot");
1970 ret = (cli_setpid(cli1, 1),
1971 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 50, 4, 0, READ_LOCK))) &&
1972 (cli_setpid(cli1, 2),
1973 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 52, 4, 0, READ_LOCK)));
1974 EXPECTED(ret, True);
1975 printf("a different pid %s set overlapping read locks\n", ret?"can":"cannot");
1977 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 60, 4, 0, READ_LOCK)) &&
1978 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 60, 4, 0, READ_LOCK));
1979 EXPECTED(ret, True);
1980 printf("the same process %s set the same read lock twice\n", ret?"can":"cannot");
1982 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 70, 4, 0, WRITE_LOCK)) &&
1983 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 70, 4, 0, WRITE_LOCK));
1984 EXPECTED(ret, False);
1985 printf("the same process %s set the same write lock twice\n", ret?"can":"cannot");
1987 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 80, 4, 0, READ_LOCK)) &&
1988 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 80, 4, 0, WRITE_LOCK));
1989 EXPECTED(ret, False);
1990 printf("the same process %s overlay a read lock with a write lock\n", ret?"can":"cannot");
1992 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 90, 4, 0, WRITE_LOCK)) &&
1993 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 90, 4, 0, READ_LOCK));
1994 EXPECTED(ret, True);
1995 printf("the same process %s overlay a write lock with a read lock\n", ret?"can":"cannot");
1997 ret = (cli_setpid(cli1, 1),
1998 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 100, 4, 0, WRITE_LOCK))) &&
1999 (cli_setpid(cli1, 2),
2000 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 100, 4, 0, READ_LOCK)));
2001 EXPECTED(ret, False);
2002 printf("a different pid %s overlay a write lock with a read lock\n", ret?"can":"cannot");
2004 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 110, 4, 0, READ_LOCK)) &&
2005 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 112, 4, 0, READ_LOCK)) &&
2006 NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 110, 6));
2007 EXPECTED(ret, False);
2008 printf("the same process %s coalesce read locks\n", ret?"can":"cannot");
2011 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 120, 4, 0, WRITE_LOCK)) &&
2012 (cli_read_old(cli2, fnum2, buf, 120, 4) == 4);
2013 EXPECTED(ret, False);
2014 printf("this server %s strict write locking\n", ret?"doesn't do":"does");
2016 status = cli_lock32(cli1, fnum1, 130, 4, 0, READ_LOCK);
2017 ret = NT_STATUS_IS_OK(status);
2018 if (ret) {
2019 status = cli_writeall(cli2, fnum2, 0, (uint8_t *)buf, 130, 4,
2020 NULL);
2021 ret = NT_STATUS_IS_OK(status);
2023 EXPECTED(ret, False);
2024 printf("this server %s strict read locking\n", ret?"doesn't do":"does");
2027 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 140, 4, 0, READ_LOCK)) &&
2028 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 140, 4, 0, READ_LOCK)) &&
2029 NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 140, 4)) &&
2030 NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 140, 4));
2031 EXPECTED(ret, True);
2032 printf("this server %s do recursive read locking\n", ret?"does":"doesn't");
2035 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 150, 4, 0, WRITE_LOCK)) &&
2036 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 150, 4, 0, READ_LOCK)) &&
2037 NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 150, 4)) &&
2038 (cli_read_old(cli2, fnum2, buf, 150, 4) == 4) &&
2039 !(NT_STATUS_IS_OK(cli_writeall(cli2, fnum2, 0, (uint8_t *)buf,
2040 150, 4, NULL))) &&
2041 NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 150, 4));
2042 EXPECTED(ret, True);
2043 printf("this server %s do recursive lock overlays\n", ret?"does":"doesn't");
2045 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 160, 4, 0, READ_LOCK)) &&
2046 NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 160, 4)) &&
2047 NT_STATUS_IS_OK(cli_writeall(cli2, fnum2, 0, (uint8_t *)buf,
2048 160, 4, NULL)) &&
2049 (cli_read_old(cli2, fnum2, buf, 160, 4) == 4);
2050 EXPECTED(ret, True);
2051 printf("the same process %s remove a read lock using write locking\n", ret?"can":"cannot");
2053 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 170, 4, 0, WRITE_LOCK)) &&
2054 NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 170, 4)) &&
2055 NT_STATUS_IS_OK(cli_writeall(cli2, fnum2, 0, (uint8_t *)buf,
2056 170, 4, NULL)) &&
2057 (cli_read_old(cli2, fnum2, buf, 170, 4) == 4);
2058 EXPECTED(ret, True);
2059 printf("the same process %s remove a write lock using read locking\n", ret?"can":"cannot");
2061 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 190, 4, 0, WRITE_LOCK)) &&
2062 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 190, 4, 0, READ_LOCK)) &&
2063 NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 190, 4)) &&
2064 !NT_STATUS_IS_OK(cli_writeall(cli2, fnum2, 0, (uint8_t *)buf,
2065 190, 4, NULL)) &&
2066 (cli_read_old(cli2, fnum2, buf, 190, 4) == 4);
2067 EXPECTED(ret, True);
2068 printf("the same process %s remove the first lock first\n", ret?"does":"doesn't");
2070 cli_close(cli1, fnum1);
2071 cli_close(cli2, fnum2);
2072 cli_open(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
2073 cli_open(cli1, fname, O_RDWR, DENY_NONE, &f);
2074 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 8, 0, READ_LOCK)) &&
2075 NT_STATUS_IS_OK(cli_lock32(cli1, f, 0, 1, 0, READ_LOCK)) &&
2076 NT_STATUS_IS_OK(cli_close(cli1, fnum1)) &&
2077 NT_STATUS_IS_OK(cli_open(cli1, fname, O_RDWR, DENY_NONE, &fnum1)) &&
2078 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 7, 1, 0, WRITE_LOCK));
2079 cli_close(cli1, f);
2080 cli_close(cli1, fnum1);
2081 EXPECTED(ret, True);
2082 printf("the server %s have the NT byte range lock bug\n", !ret?"does":"doesn't");
2084 fail:
2085 cli_close(cli1, fnum1);
2086 cli_close(cli2, fnum2);
2087 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2088 torture_close_connection(cli1);
2089 torture_close_connection(cli2);
2091 printf("finished locktest4\n");
2092 return correct;
2096 looks at lock upgrade/downgrade.
2098 static bool run_locktest5(int dummy)
2100 static struct cli_state *cli1, *cli2;
2101 const char *fname = "\\lockt5.lck";
2102 uint16_t fnum1, fnum2, fnum3;
2103 bool ret;
2104 char buf[1000];
2105 bool correct = True;
2106 NTSTATUS status;
2108 if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
2109 return False;
2112 cli_sockopt(cli1, sockops);
2113 cli_sockopt(cli2, sockops);
2115 printf("starting locktest5\n");
2117 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2119 cli_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
2120 cli_open(cli2, fname, O_RDWR, DENY_NONE, &fnum2);
2121 cli_open(cli1, fname, O_RDWR, DENY_NONE, &fnum3);
2123 memset(buf, 0, sizeof(buf));
2125 status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 0, sizeof(buf),
2126 NULL);
2127 if (!NT_STATUS_IS_OK(status)) {
2128 printf("Failed to create file: %s\n", nt_errstr(status));
2129 correct = False;
2130 goto fail;
2133 /* Check for NT bug... */
2134 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 8, 0, READ_LOCK)) &&
2135 NT_STATUS_IS_OK(cli_lock32(cli1, fnum3, 0, 1, 0, READ_LOCK));
2136 cli_close(cli1, fnum1);
2137 cli_open(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
2138 status = cli_lock32(cli1, fnum1, 7, 1, 0, WRITE_LOCK);
2139 ret = NT_STATUS_IS_OK(status);
2140 EXPECTED(ret, True);
2141 printf("this server %s the NT locking bug\n", ret ? "doesn't have" : "has");
2142 cli_close(cli1, fnum1);
2143 cli_open(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
2144 cli_unlock(cli1, fnum3, 0, 1);
2146 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 4, 0, WRITE_LOCK)) &&
2147 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 1, 1, 0, READ_LOCK));
2148 EXPECTED(ret, True);
2149 printf("the same process %s overlay a write with a read lock\n", ret?"can":"cannot");
2151 status = cli_lock32(cli2, fnum2, 0, 4, 0, READ_LOCK);
2152 ret = NT_STATUS_IS_OK(status);
2153 EXPECTED(ret, False);
2155 printf("a different processs %s get a read lock on the first process lock stack\n", ret?"can":"cannot");
2157 /* Unlock the process 2 lock. */
2158 cli_unlock(cli2, fnum2, 0, 4);
2160 status = cli_lock32(cli1, fnum3, 0, 4, 0, READ_LOCK);
2161 ret = NT_STATUS_IS_OK(status);
2162 EXPECTED(ret, False);
2164 printf("the same processs on a different fnum %s get a read lock\n", ret?"can":"cannot");
2166 /* Unlock the process 1 fnum3 lock. */
2167 cli_unlock(cli1, fnum3, 0, 4);
2169 /* Stack 2 more locks here. */
2170 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 4, 0, READ_LOCK)) &&
2171 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 4, 0, READ_LOCK));
2173 EXPECTED(ret, True);
2174 printf("the same process %s stack read locks\n", ret?"can":"cannot");
2176 /* Unlock the first process lock, then check this was the WRITE lock that was
2177 removed. */
2179 ret = NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 0, 4)) &&
2180 NT_STATUS_IS_OK(cli_lock32(cli2, fnum2, 0, 4, 0, READ_LOCK));
2182 EXPECTED(ret, True);
2183 printf("the first unlock removes the %s lock\n", ret?"WRITE":"READ");
2185 /* Unlock the process 2 lock. */
2186 cli_unlock(cli2, fnum2, 0, 4);
2188 /* We should have 3 stacked locks here. Ensure we need to do 3 unlocks. */
2190 ret = NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 1, 1)) &&
2191 NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 0, 4)) &&
2192 NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 0, 4));
2194 EXPECTED(ret, True);
2195 printf("the same process %s unlock the stack of 4 locks\n", ret?"can":"cannot");
2197 /* Ensure the next unlock fails. */
2198 ret = NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 0, 4));
2199 EXPECTED(ret, False);
2200 printf("the same process %s count the lock stack\n", !ret?"can":"cannot");
2202 /* Ensure connection 2 can get a write lock. */
2203 status = cli_lock32(cli2, fnum2, 0, 4, 0, WRITE_LOCK);
2204 ret = NT_STATUS_IS_OK(status);
2205 EXPECTED(ret, True);
2207 printf("a different processs %s get a write lock on the unlocked stack\n", ret?"can":"cannot");
2210 fail:
2211 cli_close(cli1, fnum1);
2212 cli_close(cli2, fnum2);
2213 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2214 if (!torture_close_connection(cli1)) {
2215 correct = False;
2217 if (!torture_close_connection(cli2)) {
2218 correct = False;
2221 printf("finished locktest5\n");
2223 return correct;
2227 tries the unusual lockingX locktype bits
2229 static bool run_locktest6(int dummy)
2231 static struct cli_state *cli;
2232 const char *fname[1] = { "\\lock6.txt" };
2233 int i;
2234 uint16_t fnum;
2235 NTSTATUS status;
2237 if (!torture_open_connection(&cli, 0)) {
2238 return False;
2241 cli_sockopt(cli, sockops);
2243 printf("starting locktest6\n");
2245 for (i=0;i<1;i++) {
2246 printf("Testing %s\n", fname[i]);
2248 cli_unlink(cli, fname[i], FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2250 cli_open(cli, fname[i], O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
2251 status = cli_locktype(cli, fnum, 0, 8, 0, LOCKING_ANDX_CHANGE_LOCKTYPE);
2252 cli_close(cli, fnum);
2253 printf("CHANGE_LOCKTYPE gave %s\n", nt_errstr(status));
2255 cli_open(cli, fname[i], O_RDWR, DENY_NONE, &fnum);
2256 status = cli_locktype(cli, fnum, 0, 8, 0, LOCKING_ANDX_CANCEL_LOCK);
2257 cli_close(cli, fnum);
2258 printf("CANCEL_LOCK gave %s\n", nt_errstr(status));
2260 cli_unlink(cli, fname[i], FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2263 torture_close_connection(cli);
2265 printf("finished locktest6\n");
2266 return True;
2269 static bool run_locktest7(int dummy)
2271 struct cli_state *cli1;
2272 const char *fname = "\\lockt7.lck";
2273 uint16_t fnum1;
2274 char buf[200];
2275 bool correct = False;
2276 NTSTATUS status;
2278 if (!torture_open_connection(&cli1, 0)) {
2279 return False;
2282 cli_sockopt(cli1, sockops);
2284 printf("starting locktest7\n");
2286 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2288 cli_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
2290 memset(buf, 0, sizeof(buf));
2292 status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 0, sizeof(buf),
2293 NULL);
2294 if (!NT_STATUS_IS_OK(status)) {
2295 printf("Failed to create file: %s\n", nt_errstr(status));
2296 goto fail;
2299 cli_setpid(cli1, 1);
2301 status = cli_lock32(cli1, fnum1, 130, 4, 0, READ_LOCK);
2302 if (!NT_STATUS_IS_OK(status)) {
2303 printf("Unable to apply read lock on range 130:4, error was %s\n", nt_errstr(status));
2304 goto fail;
2305 } else {
2306 printf("pid1 successfully locked range 130:4 for READ\n");
2309 if (cli_read_old(cli1, fnum1, buf, 130, 4) != 4) {
2310 printf("pid1 unable to read the range 130:4, error was %s\n", cli_errstr(cli1));
2311 goto fail;
2312 } else {
2313 printf("pid1 successfully read the range 130:4\n");
2316 status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
2317 if (!NT_STATUS_IS_OK(status)) {
2318 printf("pid1 unable to write to the range 130:4, error was "
2319 "%s\n", nt_errstr(status));
2320 if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
2321 printf("Incorrect error (should be NT_STATUS_FILE_LOCK_CONFLICT)\n");
2322 goto fail;
2324 } else {
2325 printf("pid1 successfully wrote to the range 130:4 (should be denied)\n");
2326 goto fail;
2329 cli_setpid(cli1, 2);
2331 if (cli_read_old(cli1, fnum1, buf, 130, 4) != 4) {
2332 printf("pid2 unable to read the range 130:4, error was %s\n", cli_errstr(cli1));
2333 } else {
2334 printf("pid2 successfully read the range 130:4\n");
2337 status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
2338 if (!NT_STATUS_IS_OK(status)) {
2339 printf("pid2 unable to write to the range 130:4, error was "
2340 "%s\n", nt_errstr(status));
2341 if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
2342 printf("Incorrect error (should be NT_STATUS_FILE_LOCK_CONFLICT)\n");
2343 goto fail;
2345 } else {
2346 printf("pid2 successfully wrote to the range 130:4 (should be denied)\n");
2347 goto fail;
2350 cli_setpid(cli1, 1);
2351 cli_unlock(cli1, fnum1, 130, 4);
2353 status = cli_lock32(cli1, fnum1, 130, 4, 0, WRITE_LOCK);
2354 if (!NT_STATUS_IS_OK(status)) {
2355 printf("Unable to apply write lock on range 130:4, error was %s\n", nt_errstr(status));
2356 goto fail;
2357 } else {
2358 printf("pid1 successfully locked range 130:4 for WRITE\n");
2361 if (cli_read_old(cli1, fnum1, buf, 130, 4) != 4) {
2362 printf("pid1 unable to read the range 130:4, error was %s\n", cli_errstr(cli1));
2363 goto fail;
2364 } else {
2365 printf("pid1 successfully read the range 130:4\n");
2368 status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
2369 if (!NT_STATUS_IS_OK(status)) {
2370 printf("pid1 unable to write to the range 130:4, error was "
2371 "%s\n", nt_errstr(status));
2372 goto fail;
2373 } else {
2374 printf("pid1 successfully wrote to the range 130:4\n");
2377 cli_setpid(cli1, 2);
2379 if (cli_read_old(cli1, fnum1, buf, 130, 4) != 4) {
2380 printf("pid2 unable to read the range 130:4, error was %s\n", cli_errstr(cli1));
2381 if (NT_STATUS_V(cli_nt_error(cli1)) != NT_STATUS_V(NT_STATUS_FILE_LOCK_CONFLICT)) {
2382 printf("Incorrect error (should be NT_STATUS_FILE_LOCK_CONFLICT)\n");
2383 goto fail;
2385 } else {
2386 printf("pid2 successfully read the range 130:4 (should be denied)\n");
2387 goto fail;
2390 status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
2391 if (!NT_STATUS_IS_OK(status)) {
2392 printf("pid2 unable to write to the range 130:4, error was "
2393 "%s\n", nt_errstr(status));
2394 if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
2395 printf("Incorrect error (should be NT_STATUS_FILE_LOCK_CONFLICT)\n");
2396 goto fail;
2398 } else {
2399 printf("pid2 successfully wrote to the range 130:4 (should be denied)\n");
2400 goto fail;
2403 cli_unlock(cli1, fnum1, 130, 0);
2404 correct = True;
2406 fail:
2407 cli_close(cli1, fnum1);
2408 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2409 torture_close_connection(cli1);
2411 printf("finished locktest7\n");
2412 return correct;
2416 * This demonstrates a problem with our use of GPFS share modes: A file
2417 * descriptor sitting in the pending close queue holding a GPFS share mode
2418 * blocks opening a file another time. Happens with Word 2007 temp files.
2419 * With "posix locking = yes" and "gpfs:sharemodes = yes" enabled, the third
2420 * open is denied with NT_STATUS_SHARING_VIOLATION.
2423 static bool run_locktest8(int dummy)
2425 struct cli_state *cli1;
2426 const char *fname = "\\lockt8.lck";
2427 uint16_t fnum1, fnum2;
2428 char buf[200];
2429 bool correct = False;
2430 NTSTATUS status;
2432 if (!torture_open_connection(&cli1, 0)) {
2433 return False;
2436 cli_sockopt(cli1, sockops);
2438 printf("starting locktest8\n");
2440 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2442 status = cli_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_WRITE,
2443 &fnum1);
2444 if (!NT_STATUS_IS_OK(status)) {
2445 d_fprintf(stderr, "cli_open returned %s\n", nt_errstr(status));
2446 return false;
2449 memset(buf, 0, sizeof(buf));
2451 status = cli_open(cli1, fname, O_RDONLY, DENY_NONE, &fnum2);
2452 if (!NT_STATUS_IS_OK(status)) {
2453 d_fprintf(stderr, "cli_open second time returned %s\n",
2454 nt_errstr(status));
2455 goto fail;
2458 status = cli_lock32(cli1, fnum2, 1, 1, 0, READ_LOCK);
2459 if (!NT_STATUS_IS_OK(status)) {
2460 printf("Unable to apply read lock on range 1:1, error was "
2461 "%s\n", nt_errstr(status));
2462 goto fail;
2465 status = cli_close(cli1, fnum1);
2466 if (!NT_STATUS_IS_OK(status)) {
2467 d_fprintf(stderr, "cli_close(fnum1) %s\n", nt_errstr(status));
2468 goto fail;
2471 status = cli_open(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
2472 if (!NT_STATUS_IS_OK(status)) {
2473 d_fprintf(stderr, "cli_open third time returned %s\n",
2474 nt_errstr(status));
2475 goto fail;
2478 correct = true;
2480 fail:
2481 cli_close(cli1, fnum1);
2482 cli_close(cli1, fnum2);
2483 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2484 torture_close_connection(cli1);
2486 printf("finished locktest8\n");
2487 return correct;
2491 * This test is designed to be run in conjunction with
2492 * external NFS or POSIX locks taken in the filesystem.
2493 * It checks that the smbd server will block until the
2494 * lock is released and then acquire it. JRA.
2497 static bool got_alarm;
2498 static int alarm_fd;
2500 static void alarm_handler(int dummy)
2502 got_alarm = True;
2505 static void alarm_handler_parent(int dummy)
2507 close(alarm_fd);
2510 static void do_local_lock(int read_fd, int write_fd)
2512 int fd;
2513 char c = '\0';
2514 struct flock lock;
2515 const char *local_pathname = NULL;
2516 int ret;
2518 local_pathname = talloc_asprintf(talloc_tos(),
2519 "%s/lockt9.lck", local_path);
2520 if (!local_pathname) {
2521 printf("child: alloc fail\n");
2522 exit(1);
2525 unlink(local_pathname);
2526 fd = open(local_pathname, O_RDWR|O_CREAT, 0666);
2527 if (fd == -1) {
2528 printf("child: open of %s failed %s.\n",
2529 local_pathname, strerror(errno));
2530 exit(1);
2533 /* Now take a fcntl lock. */
2534 lock.l_type = F_WRLCK;
2535 lock.l_whence = SEEK_SET;
2536 lock.l_start = 0;
2537 lock.l_len = 4;
2538 lock.l_pid = getpid();
2540 ret = fcntl(fd,F_SETLK,&lock);
2541 if (ret == -1) {
2542 printf("child: failed to get lock 0:4 on file %s. Error %s\n",
2543 local_pathname, strerror(errno));
2544 exit(1);
2545 } else {
2546 printf("child: got lock 0:4 on file %s.\n",
2547 local_pathname );
2548 fflush(stdout);
2551 CatchSignal(SIGALRM, alarm_handler);
2552 alarm(5);
2553 /* Signal the parent. */
2554 if (write(write_fd, &c, 1) != 1) {
2555 printf("child: start signal fail %s.\n",
2556 strerror(errno));
2557 exit(1);
2559 alarm(0);
2561 alarm(10);
2562 /* Wait for the parent to be ready. */
2563 if (read(read_fd, &c, 1) != 1) {
2564 printf("child: reply signal fail %s.\n",
2565 strerror(errno));
2566 exit(1);
2568 alarm(0);
2570 sleep(5);
2571 close(fd);
2572 printf("child: released lock 0:4 on file %s.\n",
2573 local_pathname );
2574 fflush(stdout);
2575 exit(0);
2578 static bool run_locktest9(int dummy)
2580 struct cli_state *cli1;
2581 const char *fname = "\\lockt9.lck";
2582 uint16_t fnum;
2583 bool correct = False;
2584 int pipe_in[2], pipe_out[2];
2585 pid_t child_pid;
2586 char c = '\0';
2587 int ret;
2588 struct timeval start;
2589 double seconds;
2590 NTSTATUS status;
2592 printf("starting locktest9\n");
2594 if (local_path == NULL) {
2595 d_fprintf(stderr, "locktest9 must be given a local path via -l <localpath>\n");
2596 return false;
2599 if (pipe(pipe_in) == -1 || pipe(pipe_out) == -1) {
2600 return false;
2603 child_pid = fork();
2604 if (child_pid == -1) {
2605 return false;
2608 if (child_pid == 0) {
2609 /* Child. */
2610 do_local_lock(pipe_out[0], pipe_in[1]);
2611 exit(0);
2614 close(pipe_out[0]);
2615 close(pipe_in[1]);
2616 pipe_out[0] = -1;
2617 pipe_in[1] = -1;
2619 /* Parent. */
2620 ret = read(pipe_in[0], &c, 1);
2621 if (ret != 1) {
2622 d_fprintf(stderr, "failed to read start signal from child. %s\n",
2623 strerror(errno));
2624 return false;
2627 if (!torture_open_connection(&cli1, 0)) {
2628 return false;
2631 cli_sockopt(cli1, sockops);
2633 status = cli_open(cli1, fname, O_RDWR, DENY_NONE,
2634 &fnum);
2635 if (!NT_STATUS_IS_OK(status)) {
2636 d_fprintf(stderr, "cli_open returned %s\n", nt_errstr(status));
2637 return false;
2640 /* Ensure the child has the lock. */
2641 status = cli_lock32(cli1, fnum, 0, 4, 0, WRITE_LOCK);
2642 if (NT_STATUS_IS_OK(status)) {
2643 d_fprintf(stderr, "Got the lock on range 0:4 - this should not happen !\n");
2644 goto fail;
2645 } else {
2646 d_printf("Child has the lock.\n");
2649 /* Tell the child to wait 5 seconds then exit. */
2650 ret = write(pipe_out[1], &c, 1);
2651 if (ret != 1) {
2652 d_fprintf(stderr, "failed to send exit signal to child. %s\n",
2653 strerror(errno));
2654 goto fail;
2657 /* Wait 20 seconds for the lock. */
2658 alarm_fd = cli1->fd;
2659 CatchSignal(SIGALRM, alarm_handler_parent);
2660 alarm(20);
2662 start = timeval_current();
2664 status = cli_lock32(cli1, fnum, 0, 4, -1, WRITE_LOCK);
2665 if (!NT_STATUS_IS_OK(status)) {
2666 d_fprintf(stderr, "Unable to apply write lock on range 0:4, error was "
2667 "%s\n", nt_errstr(status));
2668 goto fail_nofd;
2670 alarm(0);
2672 seconds = timeval_elapsed(&start);
2674 printf("Parent got the lock after %.2f seconds.\n",
2675 seconds);
2677 status = cli_close(cli1, fnum);
2678 if (!NT_STATUS_IS_OK(status)) {
2679 d_fprintf(stderr, "cli_close(fnum1) %s\n", nt_errstr(status));
2680 goto fail;
2683 correct = true;
2685 fail:
2686 cli_close(cli1, fnum);
2687 torture_close_connection(cli1);
2689 fail_nofd:
2691 printf("finished locktest9\n");
2692 return correct;
2696 test whether fnums and tids open on one VC are available on another (a major
2697 security hole)
2699 static bool run_fdpasstest(int dummy)
2701 struct cli_state *cli1, *cli2;
2702 const char *fname = "\\fdpass.tst";
2703 uint16_t fnum1;
2704 char buf[1024];
2705 NTSTATUS status;
2707 if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
2708 return False;
2710 cli_sockopt(cli1, sockops);
2711 cli_sockopt(cli2, sockops);
2713 printf("starting fdpasstest\n");
2715 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2717 status = cli_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
2718 &fnum1);
2719 if (!NT_STATUS_IS_OK(status)) {
2720 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
2721 return False;
2724 status = cli_writeall(cli1, fnum1, 0, (const uint8_t *)"hello world\n", 0,
2725 13, NULL);
2726 if (!NT_STATUS_IS_OK(status)) {
2727 printf("write failed (%s)\n", nt_errstr(status));
2728 return False;
2731 cli2->vuid = cli1->vuid;
2732 cli_state_set_tid(cli2, cli_state_get_tid(cli1));
2733 cli_setpid(cli2, cli_getpid(cli1));
2735 if (cli_read_old(cli2, fnum1, buf, 0, 13) == 13) {
2736 printf("read succeeded! nasty security hole [%s]\n",
2737 buf);
2738 return False;
2741 cli_close(cli1, fnum1);
2742 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2744 torture_close_connection(cli1);
2745 torture_close_connection(cli2);
2747 printf("finished fdpasstest\n");
2748 return True;
2751 static bool run_fdsesstest(int dummy)
2753 struct cli_state *cli;
2754 uint16 new_vuid;
2755 uint16 saved_vuid;
2756 uint16 new_cnum;
2757 uint16 saved_cnum;
2758 const char *fname = "\\fdsess.tst";
2759 const char *fname1 = "\\fdsess1.tst";
2760 uint16_t fnum1;
2761 uint16_t fnum2;
2762 char buf[1024];
2763 bool ret = True;
2764 NTSTATUS status;
2766 if (!torture_open_connection(&cli, 0))
2767 return False;
2768 cli_sockopt(cli, sockops);
2770 if (!torture_cli_session_setup2(cli, &new_vuid))
2771 return False;
2773 saved_cnum = cli_state_get_tid(cli);
2774 if (!NT_STATUS_IS_OK(cli_tcon_andx(cli, share, "?????", "", 1)))
2775 return False;
2776 new_cnum = cli_state_get_tid(cli);
2777 cli_state_set_tid(cli, saved_cnum);
2779 printf("starting fdsesstest\n");
2781 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2782 cli_unlink(cli, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2784 status = cli_open(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
2785 if (!NT_STATUS_IS_OK(status)) {
2786 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
2787 return False;
2790 status = cli_writeall(cli, fnum1, 0, (const uint8_t *)"hello world\n", 0, 13,
2791 NULL);
2792 if (!NT_STATUS_IS_OK(status)) {
2793 printf("write failed (%s)\n", nt_errstr(status));
2794 return False;
2797 saved_vuid = cli->vuid;
2798 cli->vuid = new_vuid;
2800 if (cli_read_old(cli, fnum1, buf, 0, 13) == 13) {
2801 printf("read succeeded with different vuid! nasty security hole [%s]\n",
2802 buf);
2803 ret = False;
2805 /* Try to open a file with different vuid, samba cnum. */
2806 if (NT_STATUS_IS_OK(cli_open(cli, fname1, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum2))) {
2807 printf("create with different vuid, same cnum succeeded.\n");
2808 cli_close(cli, fnum2);
2809 cli_unlink(cli, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2810 } else {
2811 printf("create with different vuid, same cnum failed.\n");
2812 printf("This will cause problems with service clients.\n");
2813 ret = False;
2816 cli->vuid = saved_vuid;
2818 /* Try with same vuid, different cnum. */
2819 cli_state_set_tid(cli, new_cnum);
2821 if (cli_read_old(cli, fnum1, buf, 0, 13) == 13) {
2822 printf("read succeeded with different cnum![%s]\n",
2823 buf);
2824 ret = False;
2827 cli_state_set_tid(cli, saved_cnum);
2828 cli_close(cli, fnum1);
2829 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2831 torture_close_connection(cli);
2833 printf("finished fdsesstest\n");
2834 return ret;
2838 This test checks that
2840 1) the server does not allow an unlink on a file that is open
2842 static bool run_unlinktest(int dummy)
2844 struct cli_state *cli;
2845 const char *fname = "\\unlink.tst";
2846 uint16_t fnum;
2847 bool correct = True;
2848 NTSTATUS status;
2850 if (!torture_open_connection(&cli, 0)) {
2851 return False;
2854 cli_sockopt(cli, sockops);
2856 printf("starting unlink test\n");
2858 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2860 cli_setpid(cli, 1);
2862 status = cli_open(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
2863 if (!NT_STATUS_IS_OK(status)) {
2864 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
2865 return False;
2868 status = cli_unlink(cli, fname,
2869 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2870 if (NT_STATUS_IS_OK(status)) {
2871 printf("error: server allowed unlink on an open file\n");
2872 correct = False;
2873 } else {
2874 correct = check_error(__LINE__, cli, ERRDOS, ERRbadshare,
2875 NT_STATUS_SHARING_VIOLATION);
2878 cli_close(cli, fnum);
2879 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2881 if (!torture_close_connection(cli)) {
2882 correct = False;
2885 printf("unlink test finished\n");
2887 return correct;
2892 test how many open files this server supports on the one socket
2894 static bool run_maxfidtest(int dummy)
2896 struct cli_state *cli;
2897 fstring fname;
2898 uint16_t fnums[0x11000];
2899 int i;
2900 int retries=4;
2901 bool correct = True;
2902 NTSTATUS status;
2904 cli = current_cli;
2906 if (retries <= 0) {
2907 printf("failed to connect\n");
2908 return False;
2911 cli_sockopt(cli, sockops);
2913 for (i=0; i<0x11000; i++) {
2914 slprintf(fname,sizeof(fname)-1,"\\maxfid.%d.%d", i,(int)getpid());
2915 status = cli_open(cli, fname, O_RDWR|O_CREAT|O_TRUNC, DENY_NONE,
2916 &fnums[i]);
2917 if (!NT_STATUS_IS_OK(status)) {
2918 printf("open of %s failed (%s)\n",
2919 fname, nt_errstr(status));
2920 printf("maximum fnum is %d\n", i);
2921 break;
2923 printf("%6d\r", i);
2925 printf("%6d\n", i);
2926 i--;
2928 printf("cleaning up\n");
2929 for (;i>=0;i--) {
2930 slprintf(fname,sizeof(fname)-1,"\\maxfid.%d.%d", i,(int)getpid());
2931 cli_close(cli, fnums[i]);
2933 status = cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2934 if (!NT_STATUS_IS_OK(status)) {
2935 printf("unlink of %s failed (%s)\n",
2936 fname, nt_errstr(status));
2937 correct = False;
2939 printf("%6d\r", i);
2941 printf("%6d\n", 0);
2943 printf("maxfid test finished\n");
2944 if (!torture_close_connection(cli)) {
2945 correct = False;
2947 return correct;
2950 /* generate a random buffer */
2951 static void rand_buf(char *buf, int len)
2953 while (len--) {
2954 *buf = (char)sys_random();
2955 buf++;
2959 /* send smb negprot commands, not reading the response */
2960 static bool run_negprot_nowait(int dummy)
2962 struct tevent_context *ev;
2963 int i;
2964 struct cli_state *cli;
2965 bool correct = True;
2967 printf("starting negprot nowait test\n");
2969 ev = tevent_context_init(talloc_tos());
2970 if (ev == NULL) {
2971 return false;
2974 if (!(cli = open_nbt_connection())) {
2975 TALLOC_FREE(ev);
2976 return False;
2979 for (i=0;i<50000;i++) {
2980 struct tevent_req *req;
2982 req = cli_negprot_send(ev, ev, cli);
2983 if (req == NULL) {
2984 TALLOC_FREE(ev);
2985 return false;
2987 if (!tevent_req_poll(req, ev)) {
2988 d_fprintf(stderr, "tevent_req_poll failed: %s\n",
2989 strerror(errno));
2990 TALLOC_FREE(ev);
2991 return false;
2993 TALLOC_FREE(req);
2996 if (torture_close_connection(cli)) {
2997 correct = False;
3000 printf("finished negprot nowait test\n");
3002 return correct;
3005 /* send smb negprot commands, not reading the response */
3006 static bool run_bad_nbt_session(int dummy)
3008 struct nmb_name called, calling;
3009 struct sockaddr_storage ss;
3010 NTSTATUS status;
3011 int fd;
3012 bool ret;
3014 printf("starting bad nbt session test\n");
3016 make_nmb_name(&calling, myname, 0x0);
3017 make_nmb_name(&called , host, 0x20);
3019 if (!resolve_name(host, &ss, 0x20, true)) {
3020 d_fprintf(stderr, "Could not resolve name %s\n", host);
3021 return false;
3024 status = open_socket_out(&ss, 139, 10000, &fd);
3025 if (!NT_STATUS_IS_OK(status)) {
3026 d_fprintf(stderr, "open_socket_out failed: %s\n",
3027 nt_errstr(status));
3028 return false;
3031 ret = cli_bad_session_request(fd, &calling, &called);
3032 close(fd);
3033 if (!ret) {
3034 d_fprintf(stderr, "open_socket_out failed: %s\n",
3035 nt_errstr(status));
3036 return false;
3039 printf("finished bad nbt session test\n");
3040 return true;
3043 /* send random IPC commands */
3044 static bool run_randomipc(int dummy)
3046 char *rparam = NULL;
3047 char *rdata = NULL;
3048 unsigned int rdrcnt,rprcnt;
3049 char param[1024];
3050 int api, param_len, i;
3051 struct cli_state *cli;
3052 bool correct = True;
3053 int count = 50000;
3055 printf("starting random ipc test\n");
3057 if (!torture_open_connection(&cli, 0)) {
3058 return False;
3061 for (i=0;i<count;i++) {
3062 api = sys_random() % 500;
3063 param_len = (sys_random() % 64);
3065 rand_buf(param, param_len);
3067 SSVAL(param,0,api);
3069 cli_api(cli,
3070 param, param_len, 8,
3071 NULL, 0, BUFFER_SIZE,
3072 &rparam, &rprcnt,
3073 &rdata, &rdrcnt);
3074 if (i % 100 == 0) {
3075 printf("%d/%d\r", i,count);
3078 printf("%d/%d\n", i, count);
3080 if (!torture_close_connection(cli)) {
3081 correct = False;
3084 printf("finished random ipc test\n");
3086 return correct;
3091 static void browse_callback(const char *sname, uint32 stype,
3092 const char *comment, void *state)
3094 printf("\t%20.20s %08x %s\n", sname, stype, comment);
3100 This test checks the browse list code
3103 static bool run_browsetest(int dummy)
3105 static struct cli_state *cli;
3106 bool correct = True;
3108 printf("starting browse test\n");
3110 if (!torture_open_connection(&cli, 0)) {
3111 return False;
3114 printf("domain list:\n");
3115 cli_NetServerEnum(cli, cli->server_domain,
3116 SV_TYPE_DOMAIN_ENUM,
3117 browse_callback, NULL);
3119 printf("machine list:\n");
3120 cli_NetServerEnum(cli, cli->server_domain,
3121 SV_TYPE_ALL,
3122 browse_callback, NULL);
3124 if (!torture_close_connection(cli)) {
3125 correct = False;
3128 printf("browse test finished\n");
3130 return correct;
3136 This checks how the getatr calls works
3138 static bool run_attrtest(int dummy)
3140 struct cli_state *cli;
3141 uint16_t fnum;
3142 time_t t, t2;
3143 const char *fname = "\\attrib123456789.tst";
3144 bool correct = True;
3145 NTSTATUS status;
3147 printf("starting attrib test\n");
3149 if (!torture_open_connection(&cli, 0)) {
3150 return False;
3153 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3154 cli_open(cli, fname,
3155 O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum);
3156 cli_close(cli, fnum);
3158 status = cli_getatr(cli, fname, NULL, NULL, &t);
3159 if (!NT_STATUS_IS_OK(status)) {
3160 printf("getatr failed (%s)\n", nt_errstr(status));
3161 correct = False;
3164 if (abs(t - time(NULL)) > 60*60*24*10) {
3165 printf("ERROR: SMBgetatr bug. time is %s",
3166 ctime(&t));
3167 t = time(NULL);
3168 correct = True;
3171 t2 = t-60*60*24; /* 1 day ago */
3173 status = cli_setatr(cli, fname, 0, t2);
3174 if (!NT_STATUS_IS_OK(status)) {
3175 printf("setatr failed (%s)\n", nt_errstr(status));
3176 correct = True;
3179 status = cli_getatr(cli, fname, NULL, NULL, &t);
3180 if (!NT_STATUS_IS_OK(status)) {
3181 printf("getatr failed (%s)\n", nt_errstr(status));
3182 correct = True;
3185 if (t != t2) {
3186 printf("ERROR: getatr/setatr bug. times are\n%s",
3187 ctime(&t));
3188 printf("%s", ctime(&t2));
3189 correct = True;
3192 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3194 if (!torture_close_connection(cli)) {
3195 correct = False;
3198 printf("attrib test finished\n");
3200 return correct;
3205 This checks a couple of trans2 calls
3207 static bool run_trans2test(int dummy)
3209 struct cli_state *cli;
3210 uint16_t fnum;
3211 SMB_OFF_T size;
3212 time_t c_time, a_time, m_time;
3213 struct timespec c_time_ts, a_time_ts, m_time_ts, w_time_ts, m_time2_ts;
3214 const char *fname = "\\trans2.tst";
3215 const char *dname = "\\trans2";
3216 const char *fname2 = "\\trans2\\trans2.tst";
3217 char *pname;
3218 bool correct = True;
3219 NTSTATUS status;
3220 uint32_t fs_attr;
3222 printf("starting trans2 test\n");
3224 if (!torture_open_connection(&cli, 0)) {
3225 return False;
3228 status = cli_get_fs_attr_info(cli, &fs_attr);
3229 if (!NT_STATUS_IS_OK(status)) {
3230 printf("ERROR: cli_get_fs_attr_info returned %s\n",
3231 nt_errstr(status));
3232 correct = false;
3235 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3236 cli_open(cli, fname, O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum);
3237 status = cli_qfileinfo_basic(cli, fnum, NULL, &size, &c_time_ts,
3238 &a_time_ts, &w_time_ts, &m_time_ts, NULL);
3239 if (!NT_STATUS_IS_OK(status)) {
3240 printf("ERROR: qfileinfo failed (%s)\n", nt_errstr(status));
3241 correct = False;
3244 status = cli_qfilename(cli, fnum, talloc_tos(), &pname);
3245 if (!NT_STATUS_IS_OK(status)) {
3246 printf("ERROR: qfilename failed (%s)\n", nt_errstr(status));
3247 correct = False;
3250 if (strcmp(pname, fname)) {
3251 printf("qfilename gave different name? [%s] [%s]\n",
3252 fname, pname);
3253 correct = False;
3256 cli_close(cli, fnum);
3258 sleep(2);
3260 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3261 status = cli_open(cli, fname, O_RDWR | O_CREAT | O_TRUNC, DENY_NONE,
3262 &fnum);
3263 if (!NT_STATUS_IS_OK(status)) {
3264 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
3265 return False;
3267 cli_close(cli, fnum);
3269 status = cli_qpathinfo1(cli, fname, &c_time, &a_time, &m_time, &size,
3270 NULL);
3271 if (!NT_STATUS_IS_OK(status)) {
3272 printf("ERROR: qpathinfo failed (%s)\n", nt_errstr(status));
3273 correct = False;
3274 } else {
3275 if (c_time != m_time) {
3276 printf("create time=%s", ctime(&c_time));
3277 printf("modify time=%s", ctime(&m_time));
3278 printf("This system appears to have sticky create times\n");
3280 if (a_time % (60*60) == 0) {
3281 printf("access time=%s", ctime(&a_time));
3282 printf("This system appears to set a midnight access time\n");
3283 correct = False;
3286 if (abs(m_time - time(NULL)) > 60*60*24*7) {
3287 printf("ERROR: totally incorrect times - maybe word reversed? mtime=%s", ctime(&m_time));
3288 correct = False;
3293 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3294 cli_open(cli, fname,
3295 O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum);
3296 cli_close(cli, fnum);
3297 status = cli_qpathinfo2(cli, fname, &c_time_ts, &a_time_ts, &w_time_ts,
3298 &m_time_ts, &size, NULL, NULL);
3299 if (!NT_STATUS_IS_OK(status)) {
3300 printf("ERROR: qpathinfo2 failed (%s)\n", nt_errstr(status));
3301 correct = False;
3302 } else {
3303 if (w_time_ts.tv_sec < 60*60*24*2) {
3304 printf("write time=%s", ctime(&w_time_ts.tv_sec));
3305 printf("This system appears to set a initial 0 write time\n");
3306 correct = False;
3310 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3313 /* check if the server updates the directory modification time
3314 when creating a new file */
3315 status = cli_mkdir(cli, dname);
3316 if (!NT_STATUS_IS_OK(status)) {
3317 printf("ERROR: mkdir failed (%s)\n", nt_errstr(status));
3318 correct = False;
3320 sleep(3);
3321 status = cli_qpathinfo2(cli, "\\trans2\\", &c_time_ts, &a_time_ts,
3322 &w_time_ts, &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;
3328 cli_open(cli, fname2,
3329 O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum);
3330 cli_writeall(cli, fnum, 0, (uint8_t *)&fnum, 0, sizeof(fnum), NULL);
3331 cli_close(cli, fnum);
3332 status = cli_qpathinfo2(cli, "\\trans2\\", &c_time_ts, &a_time_ts,
3333 &w_time_ts, &m_time2_ts, &size, NULL, NULL);
3334 if (!NT_STATUS_IS_OK(status)) {
3335 printf("ERROR: qpathinfo2 failed (%s)\n", nt_errstr(status));
3336 correct = False;
3337 } else {
3338 if (memcmp(&m_time_ts, &m_time2_ts, sizeof(struct timespec))
3339 == 0) {
3340 printf("This system does not update directory modification times\n");
3341 correct = False;
3344 cli_unlink(cli, fname2, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3345 cli_rmdir(cli, dname);
3347 if (!torture_close_connection(cli)) {
3348 correct = False;
3351 printf("trans2 test finished\n");
3353 return correct;
3357 This checks new W2K calls.
3360 static NTSTATUS new_trans(struct cli_state *pcli, int fnum, int level)
3362 uint8_t *buf = NULL;
3363 uint32 len;
3364 NTSTATUS status;
3366 status = cli_qfileinfo(talloc_tos(), pcli, fnum, level, 0,
3367 pcli->max_xmit, NULL, &buf, &len);
3368 if (!NT_STATUS_IS_OK(status)) {
3369 printf("ERROR: qfileinfo (%d) failed (%s)\n", level,
3370 nt_errstr(status));
3371 } else {
3372 printf("qfileinfo: level %d, len = %u\n", level, len);
3373 dump_data(0, (uint8 *)buf, len);
3374 printf("\n");
3376 TALLOC_FREE(buf);
3377 return status;
3380 static bool run_w2ktest(int dummy)
3382 struct cli_state *cli;
3383 uint16_t fnum;
3384 const char *fname = "\\w2ktest