s3:torture: add SMB2-NEGPROT test
[Samba/gebeck_regimport.git] / source3 / torture / torture.c
blobdb8f1cd20fe8f74169260d7f3dc0f5f6c7cd2323
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/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"
44 extern char *optarg;
45 extern int optind;
47 fstring host, workgroup, share, password, username, myname;
48 static int max_protocol = PROTOCOL_NT1;
49 static const char *sockops="TCP_NODELAY";
50 static int 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 int signing_state = SMB_SIGNING_DEFAULT;
68 char *test_filename;
70 bool torture_showall = False;
72 static double create_procs(bool (*fn)(int), bool *result);
75 /* return a pointer to a anonymous shared memory segment of size "size"
76 which will persist across fork() but will disappear when all processes
77 exit
79 The memory is not zeroed
81 This function uses system5 shared memory. It takes advantage of a property
82 that the memory is not destroyed if it is attached when the id is removed
84 void *shm_setup(int size)
86 int shmid;
87 void *ret;
89 #ifdef __QNXNTO__
90 shmid = shm_open("private", O_RDWR | O_CREAT | O_EXCL, S_IRUSR | S_IWUSR);
91 if (shmid == -1) {
92 printf("can't get shared memory\n");
93 exit(1);
95 shm_unlink("private");
96 if (ftruncate(shmid, size) == -1) {
97 printf("can't set shared memory size\n");
98 exit(1);
100 ret = mmap(0, size, PROT_READ | PROT_WRITE, MAP_SHARED, shmid, 0);
101 if (ret == MAP_FAILED) {
102 printf("can't map shared memory\n");
103 exit(1);
105 #else
106 shmid = shmget(IPC_PRIVATE, size, S_IRUSR | S_IWUSR);
107 if (shmid == -1) {
108 printf("can't get shared memory\n");
109 exit(1);
111 ret = (void *)shmat(shmid, 0, 0);
112 if (!ret || ret == (void *)-1) {
113 printf("can't attach to shared memory\n");
114 return NULL;
116 /* the following releases the ipc, but note that this process
117 and all its children will still have access to the memory, its
118 just that the shmid is no longer valid for other shm calls. This
119 means we don't leave behind lots of shm segments after we exit
121 See Stevens "advanced programming in unix env" for details
123 shmctl(shmid, IPC_RMID, 0);
124 #endif
126 return ret;
129 /********************************************************************
130 Ensure a connection is encrypted.
131 ********************************************************************/
133 static bool force_cli_encryption(struct cli_state *c,
134 const char *sharename)
136 uint16 major, minor;
137 uint32 caplow, caphigh;
138 NTSTATUS status;
140 if (!SERVER_HAS_UNIX_CIFS(c)) {
141 d_printf("Encryption required and "
142 "server that doesn't support "
143 "UNIX extensions - failing connect\n");
144 return false;
147 status = cli_unix_extensions_version(c, &major, &minor, &caplow,
148 &caphigh);
149 if (!NT_STATUS_IS_OK(status)) {
150 d_printf("Encryption required and "
151 "can't get UNIX CIFS extensions "
152 "version from server: %s\n", nt_errstr(status));
153 return false;
156 if (!(caplow & CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP)) {
157 d_printf("Encryption required and "
158 "share %s doesn't support "
159 "encryption.\n", sharename);
160 return false;
163 if (c->use_kerberos) {
164 status = cli_gss_smb_encryption_start(c);
165 } else {
166 status = cli_raw_ntlm_smb_encryption_start(c,
167 username,
168 password,
169 workgroup);
172 if (!NT_STATUS_IS_OK(status)) {
173 d_printf("Encryption required and "
174 "setup failed with error %s.\n",
175 nt_errstr(status));
176 return false;
179 return true;
183 static struct cli_state *open_nbt_connection(void)
185 struct cli_state *c;
186 NTSTATUS status;
187 int flags = 0;
189 if (disable_spnego) {
190 flags |= CLI_FULL_CONNECTION_DONT_SPNEGO;
193 if (use_oplocks) {
194 flags |= CLI_FULL_CONNECTION_OPLOCKS;
197 if (use_level_II_oplocks) {
198 flags |= CLI_FULL_CONNECTION_LEVEL_II_OPLOCKS;
201 if (use_kerberos) {
202 flags |= CLI_FULL_CONNECTION_USE_KERBEROS;
205 if (force_dos_errors) {
206 flags |= CLI_FULL_CONNECTION_FORCE_DOS_ERRORS;
209 status = cli_connect_nb(host, NULL, port_to_use, 0x20, myname,
210 signing_state, flags, &c);
211 if (!NT_STATUS_IS_OK(status)) {
212 printf("Failed to connect with %s. Error %s\n", host, nt_errstr(status) );
213 return NULL;
216 cli_set_timeout(c, 120000); /* set a really long timeout (2 minutes) */
218 return c;
221 /****************************************************************************
222 Send a corrupt session request. See rfc1002.txt 4.3 and 4.3.2.
223 ****************************************************************************/
225 static bool cli_bad_session_request(int fd,
226 struct nmb_name *calling, struct nmb_name *called)
228 TALLOC_CTX *frame;
229 uint8_t len_buf[4];
230 struct iovec iov[3];
231 ssize_t len;
232 uint8_t *inbuf;
233 int err;
234 bool ret = false;
235 uint8_t message_type;
236 uint8_t error;
237 struct event_context *ev;
238 struct tevent_req *req;
240 frame = talloc_stackframe();
242 iov[0].iov_base = len_buf;
243 iov[0].iov_len = sizeof(len_buf);
245 /* put in the destination name */
247 iov[1].iov_base = name_mangle(talloc_tos(), called->name,
248 called->name_type);
249 if (iov[1].iov_base == NULL) {
250 goto fail;
252 iov[1].iov_len = name_len((unsigned char *)iov[1].iov_base,
253 talloc_get_size(iov[1].iov_base));
255 /* and my name */
257 iov[2].iov_base = name_mangle(talloc_tos(), calling->name,
258 calling->name_type);
259 if (iov[2].iov_base == NULL) {
260 goto fail;
262 iov[2].iov_len = name_len((unsigned char *)iov[2].iov_base,
263 talloc_get_size(iov[2].iov_base));
265 /* Deliberately corrupt the name len (first byte) */
266 *((uint8_t *)iov[2].iov_base) = 100;
268 /* send a session request (RFC 1002) */
269 /* setup the packet length
270 * Remove four bytes from the length count, since the length
271 * field in the NBT Session Service header counts the number
272 * of bytes which follow. The cli_send_smb() function knows
273 * about this and accounts for those four bytes.
274 * CRH.
277 _smb_setlen(len_buf, iov[1].iov_len + iov[2].iov_len);
278 SCVAL(len_buf,0,0x81);
280 len = write_data_iov(fd, iov, 3);
281 if (len == -1) {
282 goto fail;
285 ev = event_context_init(frame);
286 if (ev == NULL) {
287 goto fail;
289 req = read_smb_send(frame, ev, fd);
290 if (req == NULL) {
291 goto fail;
293 if (!tevent_req_poll(req, ev)) {
294 goto fail;
296 len = read_smb_recv(req, talloc_tos(), &inbuf, &err);
297 if (len == -1) {
298 errno = err;
299 goto fail;
301 TALLOC_FREE(ev);
303 message_type = CVAL(inbuf, 0);
304 if (message_type != 0x83) {
305 d_fprintf(stderr, "Expected msg type 0x83, got 0x%2.2x\n",
306 message_type);
307 goto fail;
310 if (smb_len(inbuf) != 1) {
311 d_fprintf(stderr, "Expected smb_len 1, got %d\n",
312 (int)smb_len(inbuf));
313 goto fail;
316 error = CVAL(inbuf, 4);
317 if (error != 0x82) {
318 d_fprintf(stderr, "Expected error 0x82, got %d\n",
319 (int)error);
320 goto fail;
323 ret = true;
324 fail:
325 TALLOC_FREE(frame);
326 return ret;
329 /* Insert a NULL at the first separator of the given path and return a pointer
330 * to the remainder of the string.
332 static char *
333 terminate_path_at_separator(char * path)
335 char * p;
337 if (!path) {
338 return NULL;
341 if ((p = strchr_m(path, '/'))) {
342 *p = '\0';
343 return p + 1;
346 if ((p = strchr_m(path, '\\'))) {
347 *p = '\0';
348 return p + 1;
351 /* No separator. */
352 return NULL;
356 parse a //server/share type UNC name
358 bool smbcli_parse_unc(const char *unc_name, TALLOC_CTX *mem_ctx,
359 char **hostname, char **sharename)
361 char *p;
363 *hostname = *sharename = NULL;
365 if (strncmp(unc_name, "\\\\", 2) &&
366 strncmp(unc_name, "//", 2)) {
367 return False;
370 *hostname = talloc_strdup(mem_ctx, &unc_name[2]);
371 p = terminate_path_at_separator(*hostname);
373 if (p && *p) {
374 *sharename = talloc_strdup(mem_ctx, p);
375 terminate_path_at_separator(*sharename);
378 if (*hostname && *sharename) {
379 return True;
382 TALLOC_FREE(*hostname);
383 TALLOC_FREE(*sharename);
384 return False;
387 static bool torture_open_connection_share(struct cli_state **c,
388 const char *hostname,
389 const char *sharename)
391 int flags = 0;
392 NTSTATUS status;
394 if (use_kerberos)
395 flags |= CLI_FULL_CONNECTION_USE_KERBEROS;
396 if (use_oplocks)
397 flags |= CLI_FULL_CONNECTION_OPLOCKS;
398 if (use_level_II_oplocks)
399 flags |= CLI_FULL_CONNECTION_LEVEL_II_OPLOCKS;
401 status = cli_full_connection(c, myname,
402 hostname, NULL, port_to_use,
403 sharename, "?????",
404 username, workgroup,
405 password, flags, signing_state);
406 if (!NT_STATUS_IS_OK(status)) {
407 printf("failed to open share connection: //%s/%s port:%d - %s\n",
408 hostname, sharename, port_to_use, nt_errstr(status));
409 return False;
412 cli_set_timeout(*c, 120000); /* set a really long timeout (2 minutes) */
414 if (do_encrypt) {
415 return force_cli_encryption(*c,
416 sharename);
418 return True;
421 bool torture_open_connection(struct cli_state **c, int conn_index)
423 char **unc_list = NULL;
424 int num_unc_names = 0;
425 bool result;
427 if (use_multishare_conn==True) {
428 char *h, *s;
429 unc_list = file_lines_load(multishare_conn_fname, &num_unc_names, 0, NULL);
430 if (!unc_list || num_unc_names <= 0) {
431 printf("Failed to load unc names list from '%s'\n", multishare_conn_fname);
432 exit(1);
435 if (!smbcli_parse_unc(unc_list[conn_index % num_unc_names],
436 NULL, &h, &s)) {
437 printf("Failed to parse UNC name %s\n",
438 unc_list[conn_index % num_unc_names]);
439 TALLOC_FREE(unc_list);
440 exit(1);
443 result = torture_open_connection_share(c, h, s);
445 /* h, s were copied earlier */
446 TALLOC_FREE(unc_list);
447 return result;
450 return torture_open_connection_share(c, host, share);
453 bool torture_init_connection(struct cli_state **pcli)
455 struct cli_state *cli;
457 cli = open_nbt_connection();
458 if (cli == NULL) {
459 return false;
462 *pcli = cli;
463 return true;
466 bool torture_cli_session_setup2(struct cli_state *cli, uint16 *new_vuid)
468 uint16_t old_vuid = cli_state_get_uid(cli);
469 fstring old_user_name;
470 size_t passlen = strlen(password);
471 NTSTATUS status;
472 bool ret;
474 fstrcpy(old_user_name, cli->user_name);
475 cli_state_set_uid(cli, 0);
476 ret = NT_STATUS_IS_OK(cli_session_setup(cli, username,
477 password, passlen,
478 password, passlen,
479 workgroup));
480 *new_vuid = cli_state_get_uid(cli);
481 cli_state_set_uid(cli, old_vuid);
482 status = cli_set_username(cli, old_user_name);
483 if (!NT_STATUS_IS_OK(status)) {
484 return false;
486 return ret;
490 bool torture_close_connection(struct cli_state *c)
492 bool ret = True;
493 NTSTATUS status;
495 status = cli_tdis(c);
496 if (!NT_STATUS_IS_OK(status)) {
497 printf("tdis failed (%s)\n", nt_errstr(status));
498 ret = False;
501 cli_shutdown(c);
503 return ret;
507 /* check if the server produced the expected dos or nt error code */
508 static bool check_both_error(int line, NTSTATUS status,
509 uint8 eclass, uint32 ecode, NTSTATUS nterr)
511 if (NT_STATUS_IS_DOS(status)) {
512 uint8 cclass;
513 uint32 num;
515 /* Check DOS error */
516 cclass = NT_STATUS_DOS_CLASS(status);
517 num = NT_STATUS_DOS_CODE(status);
519 if (eclass != cclass || ecode != num) {
520 printf("unexpected error code class=%d code=%d\n",
521 (int)cclass, (int)num);
522 printf(" expected %d/%d %s (line=%d)\n",
523 (int)eclass, (int)ecode, nt_errstr(nterr), line);
524 return false;
526 } else {
527 /* Check NT error */
528 if (!NT_STATUS_EQUAL(nterr, status)) {
529 printf("unexpected error code %s\n",
530 nt_errstr(status));
531 printf(" expected %s (line=%d)\n",
532 nt_errstr(nterr), line);
533 return false;
537 return true;
541 /* check if the server produced the expected error code */
542 static bool check_error(int line, NTSTATUS status,
543 uint8 eclass, uint32 ecode, NTSTATUS nterr)
545 if (NT_STATUS_IS_DOS(status)) {
546 uint8 cclass;
547 uint32 num;
549 /* Check DOS error */
551 cclass = NT_STATUS_DOS_CLASS(status);
552 num = NT_STATUS_DOS_CODE(status);
554 if (eclass != cclass || ecode != num) {
555 printf("unexpected error code class=%d code=%d\n",
556 (int)cclass, (int)num);
557 printf(" expected %d/%d %s (line=%d)\n",
558 (int)eclass, (int)ecode, nt_errstr(nterr),
559 line);
560 return False;
563 } else {
564 /* Check NT error */
566 if (NT_STATUS_V(nterr) != NT_STATUS_V(status)) {
567 printf("unexpected error code %s\n",
568 nt_errstr(status));
569 printf(" expected %s (line=%d)\n", nt_errstr(nterr),
570 line);
571 return False;
575 return True;
579 static bool wait_lock(struct cli_state *c, int fnum, uint32 offset, uint32 len)
581 NTSTATUS status;
583 status = cli_lock32(c, fnum, offset, len, -1, WRITE_LOCK);
585 while (!NT_STATUS_IS_OK(status)) {
586 if (!check_both_error(__LINE__, status, ERRDOS,
587 ERRlock, NT_STATUS_LOCK_NOT_GRANTED)) {
588 return false;
591 status = cli_lock32(c, fnum, offset, len, -1, WRITE_LOCK);
594 return true;
598 static bool rw_torture(struct cli_state *c)
600 const char *lockfname = "\\torture.lck";
601 fstring fname;
602 uint16_t fnum;
603 uint16_t fnum2;
604 pid_t pid2, pid = getpid();
605 int i, j;
606 char buf[1024];
607 bool correct = True;
608 size_t nread = 0;
609 NTSTATUS status;
611 memset(buf, '\0', sizeof(buf));
613 status = cli_open(c, lockfname, O_RDWR | O_CREAT | O_EXCL,
614 DENY_NONE, &fnum2);
615 if (!NT_STATUS_IS_OK(status)) {
616 status = cli_open(c, lockfname, O_RDWR, DENY_NONE, &fnum2);
618 if (!NT_STATUS_IS_OK(status)) {
619 printf("open of %s failed (%s)\n",
620 lockfname, nt_errstr(status));
621 return False;
624 for (i=0;i<torture_numops;i++) {
625 unsigned n = (unsigned)sys_random()%10;
627 if (i % 10 == 0) {
628 printf("%d\r", i); fflush(stdout);
630 slprintf(fname, sizeof(fstring) - 1, "\\torture.%u", n);
632 if (!wait_lock(c, fnum2, n*sizeof(int), sizeof(int))) {
633 return False;
636 status = cli_open(c, fname, O_RDWR | O_CREAT | O_TRUNC,
637 DENY_ALL, &fnum);
638 if (!NT_STATUS_IS_OK(status)) {
639 printf("open failed (%s)\n", nt_errstr(status));
640 correct = False;
641 break;
644 status = cli_writeall(c, fnum, 0, (uint8_t *)&pid, 0,
645 sizeof(pid), NULL);
646 if (!NT_STATUS_IS_OK(status)) {
647 printf("write failed (%s)\n", nt_errstr(status));
648 correct = False;
651 for (j=0;j<50;j++) {
652 status = cli_writeall(c, fnum, 0, (uint8_t *)buf,
653 sizeof(pid)+(j*sizeof(buf)),
654 sizeof(buf), NULL);
655 if (!NT_STATUS_IS_OK(status)) {
656 printf("write failed (%s)\n",
657 nt_errstr(status));
658 correct = False;
662 pid2 = 0;
664 status = cli_read(c, fnum, (char *)&pid2, 0, sizeof(pid),
665 &nread);
666 if (!NT_STATUS_IS_OK(status)) {
667 printf("read failed (%s)\n", nt_errstr(status));
668 correct = false;
669 } else if (nread != sizeof(pid)) {
670 printf("read/write compare failed: "
671 "recv %ld req %ld\n", (unsigned long)nread,
672 (unsigned long)sizeof(pid));
673 correct = false;
676 if (pid2 != pid) {
677 printf("data corruption!\n");
678 correct = False;
681 status = cli_close(c, fnum);
682 if (!NT_STATUS_IS_OK(status)) {
683 printf("close failed (%s)\n", nt_errstr(status));
684 correct = False;
687 status = cli_unlink(c, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
688 if (!NT_STATUS_IS_OK(status)) {
689 printf("unlink failed (%s)\n", nt_errstr(status));
690 correct = False;
693 status = cli_unlock(c, fnum2, n*sizeof(int), sizeof(int));
694 if (!NT_STATUS_IS_OK(status)) {
695 printf("unlock failed (%s)\n", nt_errstr(status));
696 correct = False;
700 cli_close(c, fnum2);
701 cli_unlink(c, lockfname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
703 printf("%d\n", i);
705 return correct;
708 static bool run_torture(int dummy)
710 struct cli_state *cli;
711 bool ret;
713 cli = current_cli;
715 cli_sockopt(cli, sockops);
717 ret = rw_torture(cli);
719 if (!torture_close_connection(cli)) {
720 ret = False;
723 return ret;
726 static bool rw_torture3(struct cli_state *c, char *lockfname)
728 uint16_t fnum = (uint16_t)-1;
729 unsigned int i = 0;
730 char buf[131072];
731 char buf_rd[131072];
732 unsigned count;
733 unsigned countprev = 0;
734 size_t sent = 0;
735 bool correct = True;
736 NTSTATUS status = NT_STATUS_OK;
738 srandom(1);
739 for (i = 0; i < sizeof(buf); i += sizeof(uint32))
741 SIVAL(buf, i, sys_random());
744 if (procnum == 0)
746 status = cli_unlink(
747 c, lockfname,
748 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
749 if (!NT_STATUS_IS_OK(status)) {
750 printf("unlink failed (%s) (normal, this file should "
751 "not exist)\n", nt_errstr(status));
754 status = cli_open(c, lockfname, O_RDWR | O_CREAT | O_EXCL,
755 DENY_NONE, &fnum);
756 if (!NT_STATUS_IS_OK(status)) {
757 printf("first open read/write of %s failed (%s)\n",
758 lockfname, nt_errstr(status));
759 return False;
762 else
764 for (i = 0; i < 500 && fnum == (uint16_t)-1; i++)
766 status = cli_open(c, lockfname, O_RDONLY,
767 DENY_NONE, &fnum);
768 if (!NT_STATUS_IS_OK(status)) {
769 break;
771 smb_msleep(10);
773 if (!NT_STATUS_IS_OK(status)) {
774 printf("second open read-only of %s failed (%s)\n",
775 lockfname, nt_errstr(status));
776 return False;
780 i = 0;
781 for (count = 0; count < sizeof(buf); count += sent)
783 if (count >= countprev) {
784 printf("%d %8d\r", i, count);
785 fflush(stdout);
786 i++;
787 countprev += (sizeof(buf) / 20);
790 if (procnum == 0)
792 sent = ((unsigned)sys_random()%(20))+ 1;
793 if (sent > sizeof(buf) - count)
795 sent = sizeof(buf) - count;
798 status = cli_writeall(c, fnum, 0, (uint8_t *)buf+count,
799 count, sent, NULL);
800 if (!NT_STATUS_IS_OK(status)) {
801 printf("write failed (%s)\n",
802 nt_errstr(status));
803 correct = False;
806 else
808 status = cli_read(c, fnum, buf_rd+count, count,
809 sizeof(buf)-count, &sent);
810 if(!NT_STATUS_IS_OK(status)) {
811 printf("read failed offset:%d size:%ld (%s)\n",
812 count, (unsigned long)sizeof(buf)-count,
813 nt_errstr(status));
814 correct = False;
815 sent = 0;
816 } else if (sent > 0) {
817 if (memcmp(buf_rd+count, buf+count, sent) != 0)
819 printf("read/write compare failed\n");
820 printf("offset: %d req %ld recvd %ld\n", count, (unsigned long)sizeof(buf)-count, (unsigned long)sent);
821 correct = False;
822 break;
829 status = cli_close(c, fnum);
830 if (!NT_STATUS_IS_OK(status)) {
831 printf("close failed (%s)\n", nt_errstr(status));
832 correct = False;
835 return correct;
838 static bool rw_torture2(struct cli_state *c1, struct cli_state *c2)
840 const char *lockfname = "\\torture2.lck";
841 uint16_t fnum1;
842 uint16_t fnum2;
843 int i;
844 char buf[131072];
845 char buf_rd[131072];
846 bool correct = True;
847 size_t bytes_read;
848 NTSTATUS status;
850 status = cli_unlink(c1, lockfname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
851 if (!NT_STATUS_IS_OK(status)) {
852 printf("unlink failed (%s) (normal, this file should not exist)\n", nt_errstr(status));
855 status = cli_open(c1, lockfname, O_RDWR | O_CREAT | O_EXCL,
856 DENY_NONE, &fnum1);
857 if (!NT_STATUS_IS_OK(status)) {
858 printf("first open read/write of %s failed (%s)\n",
859 lockfname, nt_errstr(status));
860 return False;
863 status = cli_open(c2, lockfname, O_RDONLY, DENY_NONE, &fnum2);
864 if (!NT_STATUS_IS_OK(status)) {
865 printf("second open read-only of %s failed (%s)\n",
866 lockfname, nt_errstr(status));
867 cli_close(c1, fnum1);
868 return False;
871 for (i = 0; i < torture_numops; i++)
873 size_t buf_size = ((unsigned)sys_random()%(sizeof(buf)-1))+ 1;
874 if (i % 10 == 0) {
875 printf("%d\r", i); fflush(stdout);
878 generate_random_buffer((unsigned char *)buf, buf_size);
880 status = cli_writeall(c1, fnum1, 0, (uint8_t *)buf, 0,
881 buf_size, NULL);
882 if (!NT_STATUS_IS_OK(status)) {
883 printf("write failed (%s)\n", nt_errstr(status));
884 correct = False;
885 break;
888 status = cli_read(c2, fnum2, buf_rd, 0, buf_size, &bytes_read);
889 if(!NT_STATUS_IS_OK(status)) {
890 printf("read failed (%s)\n", nt_errstr(status));
891 correct = false;
892 break;
893 } else if (bytes_read != buf_size) {
894 printf("read failed\n");
895 printf("read %ld, expected %ld\n",
896 (unsigned long)bytes_read,
897 (unsigned long)buf_size);
898 correct = False;
899 break;
902 if (memcmp(buf_rd, buf, buf_size) != 0)
904 printf("read/write compare failed\n");
905 correct = False;
906 break;
910 status = cli_close(c2, fnum2);
911 if (!NT_STATUS_IS_OK(status)) {
912 printf("close failed (%s)\n", nt_errstr(status));
913 correct = False;
916 status = cli_close(c1, fnum1);
917 if (!NT_STATUS_IS_OK(status)) {
918 printf("close failed (%s)\n", nt_errstr(status));
919 correct = False;
922 status = cli_unlink(c1, lockfname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
923 if (!NT_STATUS_IS_OK(status)) {
924 printf("unlink failed (%s)\n", nt_errstr(status));
925 correct = False;
928 return correct;
931 static bool run_readwritetest(int dummy)
933 struct cli_state *cli1, *cli2;
934 bool test1, test2 = False;
936 if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
937 return False;
939 cli_sockopt(cli1, sockops);
940 cli_sockopt(cli2, sockops);
942 printf("starting readwritetest\n");
944 test1 = rw_torture2(cli1, cli2);
945 printf("Passed readwritetest v1: %s\n", BOOLSTR(test1));
947 if (test1) {
948 test2 = rw_torture2(cli1, cli1);
949 printf("Passed readwritetest v2: %s\n", BOOLSTR(test2));
952 if (!torture_close_connection(cli1)) {
953 test1 = False;
956 if (!torture_close_connection(cli2)) {
957 test2 = False;
960 return (test1 && test2);
963 static bool run_readwritemulti(int dummy)
965 struct cli_state *cli;
966 bool test;
968 cli = current_cli;
970 cli_sockopt(cli, sockops);
972 printf("run_readwritemulti: fname %s\n", randomfname);
973 test = rw_torture3(cli, randomfname);
975 if (!torture_close_connection(cli)) {
976 test = False;
979 return test;
982 static bool run_readwritelarge_internal(void)
984 static struct cli_state *cli1;
985 uint16_t fnum1;
986 const char *lockfname = "\\large.dat";
987 SMB_OFF_T fsize;
988 char buf[126*1024];
989 bool correct = True;
990 NTSTATUS status;
992 if (!torture_open_connection(&cli1, 0)) {
993 return False;
995 cli_sockopt(cli1, sockops);
996 memset(buf,'\0',sizeof(buf));
998 printf("starting readwritelarge_internal\n");
1000 cli_unlink(cli1, lockfname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1002 status = cli_open(cli1, lockfname, O_RDWR | O_CREAT | O_EXCL,
1003 DENY_NONE, &fnum1);
1004 if (!NT_STATUS_IS_OK(status)) {
1005 printf("open read/write of %s failed (%s)\n", lockfname, nt_errstr(status));
1006 return False;
1009 cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 0, sizeof(buf), NULL);
1011 status = cli_qfileinfo_basic(cli1, fnum1, NULL, &fsize, NULL, NULL,
1012 NULL, NULL, NULL);
1013 if (!NT_STATUS_IS_OK(status)) {
1014 printf("qfileinfo failed (%s)\n", nt_errstr(status));
1015 correct = False;
1018 if (fsize == sizeof(buf))
1019 printf("readwritelarge_internal test 1 succeeded (size = %lx)\n",
1020 (unsigned long)fsize);
1021 else {
1022 printf("readwritelarge_internal test 1 failed (size = %lx)\n",
1023 (unsigned long)fsize);
1024 correct = False;
1027 status = cli_close(cli1, fnum1);
1028 if (!NT_STATUS_IS_OK(status)) {
1029 printf("close failed (%s)\n", nt_errstr(status));
1030 correct = False;
1033 status = cli_unlink(cli1, lockfname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1034 if (!NT_STATUS_IS_OK(status)) {
1035 printf("unlink failed (%s)\n", nt_errstr(status));
1036 correct = False;
1039 status = cli_open(cli1, lockfname, O_RDWR | O_CREAT | O_EXCL,
1040 DENY_NONE, &fnum1);
1041 if (!NT_STATUS_IS_OK(status)) {
1042 printf("open read/write of %s failed (%s)\n", lockfname, nt_errstr(status));
1043 return False;
1046 cli_smbwrite(cli1, fnum1, buf, 0, sizeof(buf), NULL);
1048 status = cli_qfileinfo_basic(cli1, fnum1, NULL, &fsize, NULL, NULL,
1049 NULL, NULL, NULL);
1050 if (!NT_STATUS_IS_OK(status)) {
1051 printf("qfileinfo failed (%s)\n", nt_errstr(status));
1052 correct = False;
1055 if (fsize == sizeof(buf))
1056 printf("readwritelarge_internal test 2 succeeded (size = %lx)\n",
1057 (unsigned long)fsize);
1058 else {
1059 printf("readwritelarge_internal test 2 failed (size = %lx)\n",
1060 (unsigned long)fsize);
1061 correct = False;
1064 #if 0
1065 /* ToDo - set allocation. JRA */
1066 if(!cli_set_allocation_size(cli1, fnum1, 0)) {
1067 printf("set allocation size to zero failed (%s)\n", cli_errstr(&cli1));
1068 return False;
1070 if (!cli_qfileinfo_basic(cli1, fnum1, NULL, &fsize, NULL, NULL, NULL,
1071 NULL, NULL)) {
1072 printf("qfileinfo failed (%s)\n", cli_errstr(cli1));
1073 correct = False;
1075 if (fsize != 0)
1076 printf("readwritelarge test 3 (truncate test) succeeded (size = %x)\n", fsize);
1077 #endif
1079 status = cli_close(cli1, fnum1);
1080 if (!NT_STATUS_IS_OK(status)) {
1081 printf("close failed (%s)\n", nt_errstr(status));
1082 correct = False;
1085 if (!torture_close_connection(cli1)) {
1086 correct = False;
1088 return correct;
1091 static bool run_readwritelarge(int dummy)
1093 return run_readwritelarge_internal();
1096 static bool run_readwritelarge_signtest(int dummy)
1098 bool ret;
1099 signing_state = SMB_SIGNING_REQUIRED;
1100 ret = run_readwritelarge_internal();
1101 signing_state = SMB_SIGNING_DEFAULT;
1102 return ret;
1105 int line_count = 0;
1106 int nbio_id;
1108 #define ival(s) strtol(s, NULL, 0)
1110 /* run a test that simulates an approximate netbench client load */
1111 static bool run_netbench(int client)
1113 struct cli_state *cli;
1114 int i;
1115 char line[1024];
1116 char cname[20];
1117 FILE *f;
1118 const char *params[20];
1119 bool correct = True;
1121 cli = current_cli;
1123 nbio_id = client;
1125 cli_sockopt(cli, sockops);
1127 nb_setup(cli);
1129 slprintf(cname,sizeof(cname)-1, "client%d", client);
1131 f = fopen(client_txt, "r");
1133 if (!f) {
1134 perror(client_txt);
1135 return False;
1138 while (fgets(line, sizeof(line)-1, f)) {
1139 char *saveptr;
1140 line_count++;
1142 line[strlen(line)-1] = 0;
1144 /* printf("[%d] %s\n", line_count, line); */
1146 all_string_sub(line,"client1", cname, sizeof(line));
1148 /* parse the command parameters */
1149 params[0] = strtok_r(line, " ", &saveptr);
1150 i = 0;
1151 while (params[i]) params[++i] = strtok_r(NULL, " ", &saveptr);
1153 params[i] = "";
1155 if (i < 2) continue;
1157 if (!strncmp(params[0],"SMB", 3)) {
1158 printf("ERROR: You are using a dbench 1 load file\n");
1159 exit(1);
1162 if (!strcmp(params[0],"NTCreateX")) {
1163 nb_createx(params[1], ival(params[2]), ival(params[3]),
1164 ival(params[4]));
1165 } else if (!strcmp(params[0],"Close")) {
1166 nb_close(ival(params[1]));
1167 } else if (!strcmp(params[0],"Rename")) {
1168 nb_rename(params[1], params[2]);
1169 } else if (!strcmp(params[0],"Unlink")) {
1170 nb_unlink(params[1]);
1171 } else if (!strcmp(params[0],"Deltree")) {
1172 nb_deltree(params[1]);
1173 } else if (!strcmp(params[0],"Rmdir")) {
1174 nb_rmdir(params[1]);
1175 } else if (!strcmp(params[0],"QUERY_PATH_INFORMATION")) {
1176 nb_qpathinfo(params[1]);
1177 } else if (!strcmp(params[0],"QUERY_FILE_INFORMATION")) {
1178 nb_qfileinfo(ival(params[1]));
1179 } else if (!strcmp(params[0],"QUERY_FS_INFORMATION")) {
1180 nb_qfsinfo(ival(params[1]));
1181 } else if (!strcmp(params[0],"FIND_FIRST")) {
1182 nb_findfirst(params[1]);
1183 } else if (!strcmp(params[0],"WriteX")) {
1184 nb_writex(ival(params[1]),
1185 ival(params[2]), ival(params[3]), ival(params[4]));
1186 } else if (!strcmp(params[0],"ReadX")) {
1187 nb_readx(ival(params[1]),
1188 ival(params[2]), ival(params[3]), ival(params[4]));
1189 } else if (!strcmp(params[0],"Flush")) {
1190 nb_flush(ival(params[1]));
1191 } else {
1192 printf("Unknown operation %s\n", params[0]);
1193 exit(1);
1196 fclose(f);
1198 nb_cleanup();
1200 if (!torture_close_connection(cli)) {
1201 correct = False;
1204 return correct;
1208 /* run a test that simulates an approximate netbench client load */
1209 static bool run_nbench(int dummy)
1211 double t;
1212 bool correct = True;
1214 nbio_shmem(nprocs);
1216 nbio_id = -1;
1218 signal(SIGALRM, nb_alarm);
1219 alarm(1);
1220 t = create_procs(run_netbench, &correct);
1221 alarm(0);
1223 printf("\nThroughput %g MB/sec\n",
1224 1.0e-6 * nbio_total() / t);
1225 return correct;
1230 This test checks for two things:
1232 1) correct support for retaining locks over a close (ie. the server
1233 must not use posix semantics)
1234 2) support for lock timeouts
1236 static bool run_locktest1(int dummy)
1238 struct cli_state *cli1, *cli2;
1239 const char *fname = "\\lockt1.lck";
1240 uint16_t fnum1, fnum2, fnum3;
1241 time_t t1, t2;
1242 unsigned lock_timeout;
1243 NTSTATUS status;
1245 if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
1246 return False;
1248 cli_sockopt(cli1, sockops);
1249 cli_sockopt(cli2, sockops);
1251 printf("starting locktest1\n");
1253 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1255 status = cli_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
1256 &fnum1);
1257 if (!NT_STATUS_IS_OK(status)) {
1258 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
1259 return False;
1262 status = cli_open(cli1, fname, O_RDWR, DENY_NONE, &fnum2);
1263 if (!NT_STATUS_IS_OK(status)) {
1264 printf("open2 of %s failed (%s)\n", fname, nt_errstr(status));
1265 return False;
1268 status = cli_open(cli2, fname, O_RDWR, DENY_NONE, &fnum3);
1269 if (!NT_STATUS_IS_OK(status)) {
1270 printf("open3 of %s failed (%s)\n", fname, nt_errstr(status));
1271 return False;
1274 status = cli_lock32(cli1, fnum1, 0, 4, 0, WRITE_LOCK);
1275 if (!NT_STATUS_IS_OK(status)) {
1276 printf("lock1 failed (%s)\n", nt_errstr(status));
1277 return false;
1280 status = cli_lock32(cli2, fnum3, 0, 4, 0, WRITE_LOCK);
1281 if (NT_STATUS_IS_OK(status)) {
1282 printf("lock2 succeeded! This is a locking bug\n");
1283 return false;
1284 } else {
1285 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1286 NT_STATUS_LOCK_NOT_GRANTED)) {
1287 return false;
1291 lock_timeout = (1 + (random() % 20));
1292 printf("Testing lock timeout with timeout=%u\n", lock_timeout);
1293 t1 = time(NULL);
1294 status = cli_lock32(cli2, fnum3, 0, 4, lock_timeout * 1000, WRITE_LOCK);
1295 if (NT_STATUS_IS_OK(status)) {
1296 printf("lock3 succeeded! This is a locking bug\n");
1297 return false;
1298 } else {
1299 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1300 NT_STATUS_FILE_LOCK_CONFLICT)) {
1301 return false;
1304 t2 = time(NULL);
1306 if (ABS(t2 - t1) < lock_timeout-1) {
1307 printf("error: This server appears not to support timed lock requests\n");
1310 printf("server slept for %u seconds for a %u second timeout\n",
1311 (unsigned int)(t2-t1), lock_timeout);
1313 status = cli_close(cli1, fnum2);
1314 if (!NT_STATUS_IS_OK(status)) {
1315 printf("close1 failed (%s)\n", nt_errstr(status));
1316 return False;
1319 status = cli_lock32(cli2, fnum3, 0, 4, 0, WRITE_LOCK);
1320 if (NT_STATUS_IS_OK(status)) {
1321 printf("lock4 succeeded! This is a locking bug\n");
1322 return false;
1323 } else {
1324 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1325 NT_STATUS_FILE_LOCK_CONFLICT)) {
1326 return false;
1330 status = cli_close(cli1, fnum1);
1331 if (!NT_STATUS_IS_OK(status)) {
1332 printf("close2 failed (%s)\n", nt_errstr(status));
1333 return False;
1336 status = cli_close(cli2, fnum3);
1337 if (!NT_STATUS_IS_OK(status)) {
1338 printf("close3 failed (%s)\n", nt_errstr(status));
1339 return False;
1342 status = cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1343 if (!NT_STATUS_IS_OK(status)) {
1344 printf("unlink failed (%s)\n", nt_errstr(status));
1345 return False;
1349 if (!torture_close_connection(cli1)) {
1350 return False;
1353 if (!torture_close_connection(cli2)) {
1354 return False;
1357 printf("Passed locktest1\n");
1358 return True;
1362 this checks to see if a secondary tconx can use open files from an
1363 earlier tconx
1365 static bool run_tcon_test(int dummy)
1367 static struct cli_state *cli;
1368 const char *fname = "\\tcontest.tmp";
1369 uint16 fnum1;
1370 uint16 cnum1, cnum2, cnum3;
1371 uint16 vuid1, vuid2;
1372 char buf[4];
1373 bool ret = True;
1374 NTSTATUS status;
1376 memset(buf, '\0', sizeof(buf));
1378 if (!torture_open_connection(&cli, 0)) {
1379 return False;
1381 cli_sockopt(cli, sockops);
1383 printf("starting tcontest\n");
1385 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1387 status = cli_open(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
1388 if (!NT_STATUS_IS_OK(status)) {
1389 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
1390 return False;
1393 cnum1 = cli_state_get_tid(cli);
1394 vuid1 = cli_state_get_uid(cli);
1396 status = cli_writeall(cli, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
1397 if (!NT_STATUS_IS_OK(status)) {
1398 printf("initial write failed (%s)", nt_errstr(status));
1399 return False;
1402 status = cli_tcon_andx(cli, share, "?????",
1403 password, strlen(password)+1);
1404 if (!NT_STATUS_IS_OK(status)) {
1405 printf("%s refused 2nd tree connect (%s)\n", host,
1406 nt_errstr(status));
1407 cli_shutdown(cli);
1408 return False;
1411 cnum2 = cli_state_get_tid(cli);
1412 cnum3 = MAX(cnum1, cnum2) + 1; /* any invalid number */
1413 vuid2 = cli_state_get_uid(cli) + 1;
1415 /* try a write with the wrong tid */
1416 cli_state_set_tid(cli, cnum2);
1418 status = cli_writeall(cli, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
1419 if (NT_STATUS_IS_OK(status)) {
1420 printf("* server allows write with wrong TID\n");
1421 ret = False;
1422 } else {
1423 printf("server fails write with wrong TID : %s\n",
1424 nt_errstr(status));
1428 /* try a write with an invalid tid */
1429 cli_state_set_tid(cli, cnum3);
1431 status = cli_writeall(cli, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
1432 if (NT_STATUS_IS_OK(status)) {
1433 printf("* server allows write with invalid TID\n");
1434 ret = False;
1435 } else {
1436 printf("server fails write with invalid TID : %s\n",
1437 nt_errstr(status));
1440 /* try a write with an invalid vuid */
1441 cli_state_set_uid(cli, vuid2);
1442 cli_state_set_tid(cli, cnum1);
1444 status = cli_writeall(cli, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
1445 if (NT_STATUS_IS_OK(status)) {
1446 printf("* server allows write with invalid VUID\n");
1447 ret = False;
1448 } else {
1449 printf("server fails write with invalid VUID : %s\n",
1450 nt_errstr(status));
1453 cli_state_set_tid(cli, cnum1);
1454 cli_state_set_uid(cli, vuid1);
1456 status = cli_close(cli, fnum1);
1457 if (!NT_STATUS_IS_OK(status)) {
1458 printf("close failed (%s)\n", nt_errstr(status));
1459 return False;
1462 cli_state_set_tid(cli, cnum2);
1464 status = cli_tdis(cli);
1465 if (!NT_STATUS_IS_OK(status)) {
1466 printf("secondary tdis failed (%s)\n", nt_errstr(status));
1467 return False;
1470 cli_state_set_tid(cli, cnum1);
1472 if (!torture_close_connection(cli)) {
1473 return False;
1476 return ret;
1481 checks for old style tcon support
1483 static bool run_tcon2_test(int dummy)
1485 static struct cli_state *cli;
1486 uint16 cnum, max_xmit;
1487 char *service;
1488 NTSTATUS status;
1490 if (!torture_open_connection(&cli, 0)) {
1491 return False;
1493 cli_sockopt(cli, sockops);
1495 printf("starting tcon2 test\n");
1497 if (asprintf(&service, "\\\\%s\\%s", host, share) == -1) {
1498 return false;
1501 status = cli_raw_tcon(cli, service, password, "?????", &max_xmit, &cnum);
1503 SAFE_FREE(service);
1505 if (!NT_STATUS_IS_OK(status)) {
1506 printf("tcon2 failed : %s\n", nt_errstr(status));
1507 } else {
1508 printf("tcon OK : max_xmit=%d cnum=%d\n",
1509 (int)max_xmit, (int)cnum);
1512 if (!torture_close_connection(cli)) {
1513 return False;
1516 printf("Passed tcon2 test\n");
1517 return True;
1520 static bool tcon_devtest(struct cli_state *cli,
1521 const char *myshare, const char *devtype,
1522 const char *return_devtype,
1523 NTSTATUS expected_error)
1525 NTSTATUS status;
1526 bool ret;
1528 status = cli_tcon_andx(cli, myshare, devtype,
1529 password, strlen(password)+1);
1531 if (NT_STATUS_IS_OK(expected_error)) {
1532 if (NT_STATUS_IS_OK(status)) {
1533 if (strcmp(cli->dev, return_devtype) == 0) {
1534 ret = True;
1535 } else {
1536 printf("tconX to share %s with type %s "
1537 "succeeded but returned the wrong "
1538 "device type (got [%s] but should have got [%s])\n",
1539 myshare, devtype, cli->dev, return_devtype);
1540 ret = False;
1542 } else {
1543 printf("tconX to share %s with type %s "
1544 "should have succeeded but failed\n",
1545 myshare, devtype);
1546 ret = False;
1548 cli_tdis(cli);
1549 } else {
1550 if (NT_STATUS_IS_OK(status)) {
1551 printf("tconx to share %s with type %s "
1552 "should have failed but succeeded\n",
1553 myshare, devtype);
1554 ret = False;
1555 } else {
1556 if (NT_STATUS_EQUAL(status, expected_error)) {
1557 ret = True;
1558 } else {
1559 printf("Returned unexpected error\n");
1560 ret = False;
1564 return ret;
1568 checks for correct tconX support
1570 static bool run_tcon_devtype_test(int dummy)
1572 static struct cli_state *cli1 = NULL;
1573 int flags = 0;
1574 NTSTATUS status;
1575 bool ret = True;
1577 status = cli_full_connection(&cli1, myname,
1578 host, NULL, port_to_use,
1579 NULL, NULL,
1580 username, workgroup,
1581 password, flags, signing_state);
1583 if (!NT_STATUS_IS_OK(status)) {
1584 printf("could not open connection\n");
1585 return False;
1588 if (!tcon_devtest(cli1, "IPC$", "A:", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1589 ret = False;
1591 if (!tcon_devtest(cli1, "IPC$", "?????", "IPC", NT_STATUS_OK))
1592 ret = False;
1594 if (!tcon_devtest(cli1, "IPC$", "LPT:", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1595 ret = False;
1597 if (!tcon_devtest(cli1, "IPC$", "IPC", "IPC", NT_STATUS_OK))
1598 ret = False;
1600 if (!tcon_devtest(cli1, "IPC$", "FOOBA", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1601 ret = False;
1603 if (!tcon_devtest(cli1, share, "A:", "A:", NT_STATUS_OK))
1604 ret = False;
1606 if (!tcon_devtest(cli1, share, "?????", "A:", NT_STATUS_OK))
1607 ret = False;
1609 if (!tcon_devtest(cli1, share, "LPT:", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1610 ret = False;
1612 if (!tcon_devtest(cli1, share, "IPC", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1613 ret = False;
1615 if (!tcon_devtest(cli1, share, "FOOBA", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1616 ret = False;
1618 cli_shutdown(cli1);
1620 if (ret)
1621 printf("Passed tcondevtest\n");
1623 return ret;
1628 This test checks that
1630 1) the server supports multiple locking contexts on the one SMB
1631 connection, distinguished by PID.
1633 2) the server correctly fails overlapping locks made by the same PID (this
1634 goes against POSIX behaviour, which is why it is tricky to implement)
1636 3) the server denies unlock requests by an incorrect client PID
1638 static bool run_locktest2(int dummy)
1640 static struct cli_state *cli;
1641 const char *fname = "\\lockt2.lck";
1642 uint16_t fnum1, fnum2, fnum3;
1643 bool correct = True;
1644 NTSTATUS status;
1646 if (!torture_open_connection(&cli, 0)) {
1647 return False;
1650 cli_sockopt(cli, sockops);
1652 printf("starting locktest2\n");
1654 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1656 cli_setpid(cli, 1);
1658 status = cli_open(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
1659 if (!NT_STATUS_IS_OK(status)) {
1660 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
1661 return False;
1664 status = cli_open(cli, fname, O_RDWR, DENY_NONE, &fnum2);
1665 if (!NT_STATUS_IS_OK(status)) {
1666 printf("open2 of %s failed (%s)\n", fname, nt_errstr(status));
1667 return False;
1670 cli_setpid(cli, 2);
1672 status = cli_open(cli, fname, O_RDWR, DENY_NONE, &fnum3);
1673 if (!NT_STATUS_IS_OK(status)) {
1674 printf("open3 of %s failed (%s)\n", fname, nt_errstr(status));
1675 return False;
1678 cli_setpid(cli, 1);
1680 status = cli_lock32(cli, fnum1, 0, 4, 0, WRITE_LOCK);
1681 if (!NT_STATUS_IS_OK(status)) {
1682 printf("lock1 failed (%s)\n", nt_errstr(status));
1683 return false;
1686 status = cli_lock32(cli, fnum1, 0, 4, 0, WRITE_LOCK);
1687 if (NT_STATUS_IS_OK(status)) {
1688 printf("WRITE lock1 succeeded! This is a locking bug\n");
1689 correct = false;
1690 } else {
1691 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1692 NT_STATUS_LOCK_NOT_GRANTED)) {
1693 return false;
1697 status = cli_lock32(cli, fnum2, 0, 4, 0, WRITE_LOCK);
1698 if (NT_STATUS_IS_OK(status)) {
1699 printf("WRITE lock2 succeeded! This is a locking bug\n");
1700 correct = false;
1701 } else {
1702 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1703 NT_STATUS_LOCK_NOT_GRANTED)) {
1704 return false;
1708 status = cli_lock32(cli, fnum2, 0, 4, 0, READ_LOCK);
1709 if (NT_STATUS_IS_OK(status)) {
1710 printf("READ lock2 succeeded! This is a locking bug\n");
1711 correct = false;
1712 } else {
1713 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1714 NT_STATUS_FILE_LOCK_CONFLICT)) {
1715 return false;
1719 status = cli_lock32(cli, fnum1, 100, 4, 0, WRITE_LOCK);
1720 if (!NT_STATUS_IS_OK(status)) {
1721 printf("lock at 100 failed (%s)\n", nt_errstr(status));
1723 cli_setpid(cli, 2);
1724 if (NT_STATUS_IS_OK(cli_unlock(cli, fnum1, 100, 4))) {
1725 printf("unlock at 100 succeeded! This is a locking bug\n");
1726 correct = False;
1729 status = cli_unlock(cli, fnum1, 0, 4);
1730 if (NT_STATUS_IS_OK(status)) {
1731 printf("unlock1 succeeded! This is a locking bug\n");
1732 correct = false;
1733 } else {
1734 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1735 NT_STATUS_RANGE_NOT_LOCKED)) {
1736 return false;
1740 status = cli_unlock(cli, fnum1, 0, 8);
1741 if (NT_STATUS_IS_OK(status)) {
1742 printf("unlock2 succeeded! This is a locking bug\n");
1743 correct = false;
1744 } else {
1745 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1746 NT_STATUS_RANGE_NOT_LOCKED)) {
1747 return false;
1751 status = cli_lock32(cli, fnum3, 0, 4, 0, WRITE_LOCK);
1752 if (NT_STATUS_IS_OK(status)) {
1753 printf("lock3 succeeded! This is a locking bug\n");
1754 correct = false;
1755 } else {
1756 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1757 NT_STATUS_LOCK_NOT_GRANTED)) {
1758 return false;
1762 cli_setpid(cli, 1);
1764 status = cli_close(cli, fnum1);
1765 if (!NT_STATUS_IS_OK(status)) {
1766 printf("close1 failed (%s)\n", nt_errstr(status));
1767 return False;
1770 status = cli_close(cli, fnum2);
1771 if (!NT_STATUS_IS_OK(status)) {
1772 printf("close2 failed (%s)\n", nt_errstr(status));
1773 return False;
1776 status = cli_close(cli, fnum3);
1777 if (!NT_STATUS_IS_OK(status)) {
1778 printf("close3 failed (%s)\n", nt_errstr(status));
1779 return False;
1782 if (!torture_close_connection(cli)) {
1783 correct = False;
1786 printf("locktest2 finished\n");
1788 return correct;
1793 This test checks that
1795 1) the server supports the full offset range in lock requests
1797 static bool run_locktest3(int dummy)
1799 static struct cli_state *cli1, *cli2;
1800 const char *fname = "\\lockt3.lck";
1801 uint16_t fnum1, fnum2;
1802 int i;
1803 uint32 offset;
1804 bool correct = True;
1805 NTSTATUS status;
1807 #define NEXT_OFFSET offset += (~(uint32)0) / torture_numops
1809 if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
1810 return False;
1812 cli_sockopt(cli1, sockops);
1813 cli_sockopt(cli2, sockops);
1815 printf("starting locktest3\n");
1817 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1819 status = cli_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
1820 &fnum1);
1821 if (!NT_STATUS_IS_OK(status)) {
1822 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
1823 return False;
1826 status = cli_open(cli2, fname, O_RDWR, DENY_NONE, &fnum2);
1827 if (!NT_STATUS_IS_OK(status)) {
1828 printf("open2 of %s failed (%s)\n", fname, nt_errstr(status));
1829 return False;
1832 for (offset=i=0;i<torture_numops;i++) {
1833 NEXT_OFFSET;
1835 status = cli_lock32(cli1, fnum1, offset-1, 1, 0, WRITE_LOCK);
1836 if (!NT_STATUS_IS_OK(status)) {
1837 printf("lock1 %d failed (%s)\n",
1839 nt_errstr(status));
1840 return False;
1843 status = cli_lock32(cli2, fnum2, offset-2, 1, 0, WRITE_LOCK);
1844 if (!NT_STATUS_IS_OK(status)) {
1845 printf("lock2 %d failed (%s)\n",
1847 nt_errstr(status));
1848 return False;
1852 for (offset=i=0;i<torture_numops;i++) {
1853 NEXT_OFFSET;
1855 status = cli_lock32(cli1, fnum1, offset-2, 1, 0, WRITE_LOCK);
1856 if (NT_STATUS_IS_OK(status)) {
1857 printf("error: lock1 %d succeeded!\n", i);
1858 return False;
1861 status = cli_lock32(cli2, fnum2, offset-1, 1, 0, WRITE_LOCK);
1862 if (NT_STATUS_IS_OK(status)) {
1863 printf("error: lock2 %d succeeded!\n", i);
1864 return False;
1867 status = cli_lock32(cli1, fnum1, offset-1, 1, 0, WRITE_LOCK);
1868 if (NT_STATUS_IS_OK(status)) {
1869 printf("error: lock3 %d succeeded!\n", i);
1870 return False;
1873 status = cli_lock32(cli2, fnum2, offset-2, 1, 0, WRITE_LOCK);
1874 if (NT_STATUS_IS_OK(status)) {
1875 printf("error: lock4 %d succeeded!\n", i);
1876 return False;
1880 for (offset=i=0;i<torture_numops;i++) {
1881 NEXT_OFFSET;
1883 status = cli_unlock(cli1, fnum1, offset-1, 1);
1884 if (!NT_STATUS_IS_OK(status)) {
1885 printf("unlock1 %d failed (%s)\n",
1887 nt_errstr(status));
1888 return False;
1891 status = cli_unlock(cli2, fnum2, offset-2, 1);
1892 if (!NT_STATUS_IS_OK(status)) {
1893 printf("unlock2 %d failed (%s)\n",
1895 nt_errstr(status));
1896 return False;
1900 status = cli_close(cli1, fnum1);
1901 if (!NT_STATUS_IS_OK(status)) {
1902 printf("close1 failed (%s)\n", nt_errstr(status));
1903 return False;
1906 status = cli_close(cli2, fnum2);
1907 if (!NT_STATUS_IS_OK(status)) {
1908 printf("close2 failed (%s)\n", nt_errstr(status));
1909 return False;
1912 status = cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1913 if (!NT_STATUS_IS_OK(status)) {
1914 printf("unlink failed (%s)\n", nt_errstr(status));
1915 return False;
1918 if (!torture_close_connection(cli1)) {
1919 correct = False;
1922 if (!torture_close_connection(cli2)) {
1923 correct = False;
1926 printf("finished locktest3\n");
1928 return correct;
1931 static bool test_cli_read(struct cli_state *cli, uint16_t fnum,
1932 char *buf, off_t offset, size_t size,
1933 size_t *nread, size_t expect)
1935 NTSTATUS status;
1936 size_t l_nread;
1938 status = cli_read(cli, fnum, buf, offset, size, &l_nread);
1940 if(!NT_STATUS_IS_OK(status)) {
1941 return false;
1942 } else if (l_nread != expect) {
1943 return false;
1946 if (nread) {
1947 *nread = l_nread;
1950 return true;
1953 #define EXPECTED(ret, v) if ((ret) != (v)) { \
1954 printf("** "); correct = False; \
1958 looks at overlapping locks
1960 static bool run_locktest4(int dummy)
1962 static struct cli_state *cli1, *cli2;
1963 const char *fname = "\\lockt4.lck";
1964 uint16_t fnum1, fnum2, f;
1965 bool ret;
1966 char buf[1000];
1967 bool correct = True;
1968 NTSTATUS status;
1970 if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
1971 return False;
1974 cli_sockopt(cli1, sockops);
1975 cli_sockopt(cli2, sockops);
1977 printf("starting locktest4\n");
1979 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1981 cli_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
1982 cli_open(cli2, fname, O_RDWR, DENY_NONE, &fnum2);
1984 memset(buf, 0, sizeof(buf));
1986 status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 0, sizeof(buf),
1987 NULL);
1988 if (!NT_STATUS_IS_OK(status)) {
1989 printf("Failed to create file: %s\n", nt_errstr(status));
1990 correct = False;
1991 goto fail;
1994 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 4, 0, WRITE_LOCK)) &&
1995 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 2, 4, 0, WRITE_LOCK));
1996 EXPECTED(ret, False);
1997 printf("the same process %s set overlapping write locks\n", ret?"can":"cannot");
1999 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 10, 4, 0, READ_LOCK)) &&
2000 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 12, 4, 0, READ_LOCK));
2001 EXPECTED(ret, True);
2002 printf("the same process %s set overlapping read locks\n", ret?"can":"cannot");
2004 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 20, 4, 0, WRITE_LOCK)) &&
2005 NT_STATUS_IS_OK(cli_lock32(cli2, fnum2, 22, 4, 0, WRITE_LOCK));
2006 EXPECTED(ret, False);
2007 printf("a different connection %s set overlapping write locks\n", ret?"can":"cannot");
2009 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 30, 4, 0, READ_LOCK)) &&
2010 NT_STATUS_IS_OK(cli_lock32(cli2, fnum2, 32, 4, 0, READ_LOCK));
2011 EXPECTED(ret, True);
2012 printf("a different connection %s set overlapping read locks\n", ret?"can":"cannot");
2014 ret = (cli_setpid(cli1, 1),
2015 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 40, 4, 0, WRITE_LOCK))) &&
2016 (cli_setpid(cli1, 2),
2017 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 42, 4, 0, WRITE_LOCK)));
2018 EXPECTED(ret, False);
2019 printf("a different pid %s set overlapping write locks\n", ret?"can":"cannot");
2021 ret = (cli_setpid(cli1, 1),
2022 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 50, 4, 0, READ_LOCK))) &&
2023 (cli_setpid(cli1, 2),
2024 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 52, 4, 0, READ_LOCK)));
2025 EXPECTED(ret, True);
2026 printf("a different pid %s set overlapping read locks\n", ret?"can":"cannot");
2028 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 60, 4, 0, READ_LOCK)) &&
2029 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 60, 4, 0, READ_LOCK));
2030 EXPECTED(ret, True);
2031 printf("the same process %s set the same read lock twice\n", ret?"can":"cannot");
2033 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 70, 4, 0, WRITE_LOCK)) &&
2034 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 70, 4, 0, WRITE_LOCK));
2035 EXPECTED(ret, False);
2036 printf("the same process %s set the same write lock twice\n", ret?"can":"cannot");
2038 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 80, 4, 0, READ_LOCK)) &&
2039 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 80, 4, 0, WRITE_LOCK));
2040 EXPECTED(ret, False);
2041 printf("the same process %s overlay a read lock with a write lock\n", ret?"can":"cannot");
2043 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 90, 4, 0, WRITE_LOCK)) &&
2044 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 90, 4, 0, READ_LOCK));
2045 EXPECTED(ret, True);
2046 printf("the same process %s overlay a write lock with a read lock\n", ret?"can":"cannot");
2048 ret = (cli_setpid(cli1, 1),
2049 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 100, 4, 0, WRITE_LOCK))) &&
2050 (cli_setpid(cli1, 2),
2051 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 100, 4, 0, READ_LOCK)));
2052 EXPECTED(ret, False);
2053 printf("a different pid %s overlay a write lock with a read lock\n", ret?"can":"cannot");
2055 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 110, 4, 0, READ_LOCK)) &&
2056 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 112, 4, 0, READ_LOCK)) &&
2057 NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 110, 6));
2058 EXPECTED(ret, False);
2059 printf("the same process %s coalesce read locks\n", ret?"can":"cannot");
2062 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 120, 4, 0, WRITE_LOCK)) &&
2063 test_cli_read(cli2, fnum2, buf, 120, 4, NULL, 4);
2064 EXPECTED(ret, False);
2065 printf("this server %s strict write locking\n", ret?"doesn't do":"does");
2067 status = cli_lock32(cli1, fnum1, 130, 4, 0, READ_LOCK);
2068 ret = NT_STATUS_IS_OK(status);
2069 if (ret) {
2070 status = cli_writeall(cli2, fnum2, 0, (uint8_t *)buf, 130, 4,
2071 NULL);
2072 ret = NT_STATUS_IS_OK(status);
2074 EXPECTED(ret, False);
2075 printf("this server %s strict read locking\n", ret?"doesn't do":"does");
2078 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 140, 4, 0, READ_LOCK)) &&
2079 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 140, 4, 0, READ_LOCK)) &&
2080 NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 140, 4)) &&
2081 NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 140, 4));
2082 EXPECTED(ret, True);
2083 printf("this server %s do recursive read locking\n", ret?"does":"doesn't");
2086 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 150, 4, 0, WRITE_LOCK)) &&
2087 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 150, 4, 0, READ_LOCK)) &&
2088 NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 150, 4)) &&
2089 test_cli_read(cli2, fnum2, buf, 150, 4, NULL, 4) &&
2090 !(NT_STATUS_IS_OK(cli_writeall(cli2, fnum2, 0, (uint8_t *)buf,
2091 150, 4, NULL))) &&
2092 NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 150, 4));
2093 EXPECTED(ret, True);
2094 printf("this server %s do recursive lock overlays\n", ret?"does":"doesn't");
2096 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 160, 4, 0, READ_LOCK)) &&
2097 NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 160, 4)) &&
2098 NT_STATUS_IS_OK(cli_writeall(cli2, fnum2, 0, (uint8_t *)buf,
2099 160, 4, NULL)) &&
2100 test_cli_read(cli2, fnum2, buf, 160, 4, NULL, 4);
2101 EXPECTED(ret, True);
2102 printf("the same process %s remove a read lock using write locking\n", ret?"can":"cannot");
2104 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 170, 4, 0, WRITE_LOCK)) &&
2105 NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 170, 4)) &&
2106 NT_STATUS_IS_OK(cli_writeall(cli2, fnum2, 0, (uint8_t *)buf,
2107 170, 4, NULL)) &&
2108 test_cli_read(cli2, fnum2, buf, 170, 4, NULL, 4);
2109 EXPECTED(ret, True);
2110 printf("the same process %s remove a write lock using read locking\n", ret?"can":"cannot");
2112 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 190, 4, 0, WRITE_LOCK)) &&
2113 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 190, 4, 0, READ_LOCK)) &&
2114 NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 190, 4)) &&
2115 !NT_STATUS_IS_OK(cli_writeall(cli2, fnum2, 0, (uint8_t *)buf,
2116 190, 4, NULL)) &&
2117 test_cli_read(cli2, fnum2, buf, 190, 4, NULL, 4);
2118 EXPECTED(ret, True);
2119 printf("the same process %s remove the first lock first\n", ret?"does":"doesn't");
2121 cli_close(cli1, fnum1);
2122 cli_close(cli2, fnum2);
2123 cli_open(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
2124 cli_open(cli1, fname, O_RDWR, DENY_NONE, &f);
2125 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 8, 0, READ_LOCK)) &&
2126 NT_STATUS_IS_OK(cli_lock32(cli1, f, 0, 1, 0, READ_LOCK)) &&
2127 NT_STATUS_IS_OK(cli_close(cli1, fnum1)) &&
2128 NT_STATUS_IS_OK(cli_open(cli1, fname, O_RDWR, DENY_NONE, &fnum1)) &&
2129 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 7, 1, 0, WRITE_LOCK));
2130 cli_close(cli1, f);
2131 cli_close(cli1, fnum1);
2132 EXPECTED(ret, True);
2133 printf("the server %s have the NT byte range lock bug\n", !ret?"does":"doesn't");
2135 fail:
2136 cli_close(cli1, fnum1);
2137 cli_close(cli2, fnum2);
2138 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2139 torture_close_connection(cli1);
2140 torture_close_connection(cli2);
2142 printf("finished locktest4\n");
2143 return correct;
2147 looks at lock upgrade/downgrade.
2149 static bool run_locktest5(int dummy)
2151 static struct cli_state *cli1, *cli2;
2152 const char *fname = "\\lockt5.lck";
2153 uint16_t fnum1, fnum2, fnum3;
2154 bool ret;
2155 char buf[1000];
2156 bool correct = True;
2157 NTSTATUS status;
2159 if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
2160 return False;
2163 cli_sockopt(cli1, sockops);
2164 cli_sockopt(cli2, sockops);
2166 printf("starting locktest5\n");
2168 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2170 cli_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
2171 cli_open(cli2, fname, O_RDWR, DENY_NONE, &fnum2);
2172 cli_open(cli1, fname, O_RDWR, DENY_NONE, &fnum3);
2174 memset(buf, 0, sizeof(buf));
2176 status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 0, sizeof(buf),
2177 NULL);
2178 if (!NT_STATUS_IS_OK(status)) {
2179 printf("Failed to create file: %s\n", nt_errstr(status));
2180 correct = False;
2181 goto fail;
2184 /* Check for NT bug... */
2185 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 8, 0, READ_LOCK)) &&
2186 NT_STATUS_IS_OK(cli_lock32(cli1, fnum3, 0, 1, 0, READ_LOCK));
2187 cli_close(cli1, fnum1);
2188 cli_open(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
2189 status = cli_lock32(cli1, fnum1, 7, 1, 0, WRITE_LOCK);
2190 ret = NT_STATUS_IS_OK(status);
2191 EXPECTED(ret, True);
2192 printf("this server %s the NT locking bug\n", ret ? "doesn't have" : "has");
2193 cli_close(cli1, fnum1);
2194 cli_open(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
2195 cli_unlock(cli1, fnum3, 0, 1);
2197 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 4, 0, WRITE_LOCK)) &&
2198 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 1, 1, 0, READ_LOCK));
2199 EXPECTED(ret, True);
2200 printf("the same process %s overlay a write with a read lock\n", ret?"can":"cannot");
2202 status = cli_lock32(cli2, fnum2, 0, 4, 0, READ_LOCK);
2203 ret = NT_STATUS_IS_OK(status);
2204 EXPECTED(ret, False);
2206 printf("a different processs %s get a read lock on the first process lock stack\n", ret?"can":"cannot");
2208 /* Unlock the process 2 lock. */
2209 cli_unlock(cli2, fnum2, 0, 4);
2211 status = cli_lock32(cli1, fnum3, 0, 4, 0, READ_LOCK);
2212 ret = NT_STATUS_IS_OK(status);
2213 EXPECTED(ret, False);
2215 printf("the same processs on a different fnum %s get a read lock\n", ret?"can":"cannot");
2217 /* Unlock the process 1 fnum3 lock. */
2218 cli_unlock(cli1, fnum3, 0, 4);
2220 /* Stack 2 more locks here. */
2221 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 4, 0, READ_LOCK)) &&
2222 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 4, 0, READ_LOCK));
2224 EXPECTED(ret, True);
2225 printf("the same process %s stack read locks\n", ret?"can":"cannot");
2227 /* Unlock the first process lock, then check this was the WRITE lock that was
2228 removed. */
2230 ret = NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 0, 4)) &&
2231 NT_STATUS_IS_OK(cli_lock32(cli2, fnum2, 0, 4, 0, READ_LOCK));
2233 EXPECTED(ret, True);
2234 printf("the first unlock removes the %s lock\n", ret?"WRITE":"READ");
2236 /* Unlock the process 2 lock. */
2237 cli_unlock(cli2, fnum2, 0, 4);
2239 /* We should have 3 stacked locks here. Ensure we need to do 3 unlocks. */
2241 ret = NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 1, 1)) &&
2242 NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 0, 4)) &&
2243 NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 0, 4));
2245 EXPECTED(ret, True);
2246 printf("the same process %s unlock the stack of 4 locks\n", ret?"can":"cannot");
2248 /* Ensure the next unlock fails. */
2249 ret = NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 0, 4));
2250 EXPECTED(ret, False);
2251 printf("the same process %s count the lock stack\n", !ret?"can":"cannot");
2253 /* Ensure connection 2 can get a write lock. */
2254 status = cli_lock32(cli2, fnum2, 0, 4, 0, WRITE_LOCK);
2255 ret = NT_STATUS_IS_OK(status);
2256 EXPECTED(ret, True);
2258 printf("a different processs %s get a write lock on the unlocked stack\n", ret?"can":"cannot");
2261 fail:
2262 cli_close(cli1, fnum1);
2263 cli_close(cli2, fnum2);
2264 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2265 if (!torture_close_connection(cli1)) {
2266 correct = False;
2268 if (!torture_close_connection(cli2)) {
2269 correct = False;
2272 printf("finished locktest5\n");
2274 return correct;
2278 tries the unusual lockingX locktype bits
2280 static bool run_locktest6(int dummy)
2282 static struct cli_state *cli;
2283 const char *fname[1] = { "\\lock6.txt" };
2284 int i;
2285 uint16_t fnum;
2286 NTSTATUS status;
2288 if (!torture_open_connection(&cli, 0)) {
2289 return False;
2292 cli_sockopt(cli, sockops);
2294 printf("starting locktest6\n");
2296 for (i=0;i<1;i++) {
2297 printf("Testing %s\n", fname[i]);
2299 cli_unlink(cli, fname[i], FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2301 cli_open(cli, fname[i], O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
2302 status = cli_locktype(cli, fnum, 0, 8, 0, LOCKING_ANDX_CHANGE_LOCKTYPE);
2303 cli_close(cli, fnum);
2304 printf("CHANGE_LOCKTYPE gave %s\n", nt_errstr(status));
2306 cli_open(cli, fname[i], O_RDWR, DENY_NONE, &fnum);
2307 status = cli_locktype(cli, fnum, 0, 8, 0, LOCKING_ANDX_CANCEL_LOCK);
2308 cli_close(cli, fnum);
2309 printf("CANCEL_LOCK gave %s\n", nt_errstr(status));
2311 cli_unlink(cli, fname[i], FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2314 torture_close_connection(cli);
2316 printf("finished locktest6\n");
2317 return True;
2320 static bool run_locktest7(int dummy)
2322 struct cli_state *cli1;
2323 const char *fname = "\\lockt7.lck";
2324 uint16_t fnum1;
2325 char buf[200];
2326 bool correct = False;
2327 size_t nread;
2328 NTSTATUS status;
2330 if (!torture_open_connection(&cli1, 0)) {
2331 return False;
2334 cli_sockopt(cli1, sockops);
2336 printf("starting locktest7\n");
2338 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2340 cli_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
2342 memset(buf, 0, sizeof(buf));
2344 status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 0, sizeof(buf),
2345 NULL);
2346 if (!NT_STATUS_IS_OK(status)) {
2347 printf("Failed to create file: %s\n", nt_errstr(status));
2348 goto fail;
2351 cli_setpid(cli1, 1);
2353 status = cli_lock32(cli1, fnum1, 130, 4, 0, READ_LOCK);
2354 if (!NT_STATUS_IS_OK(status)) {
2355 printf("Unable to apply read lock on range 130:4, "
2356 "error was %s\n", nt_errstr(status));
2357 goto fail;
2358 } else {
2359 printf("pid1 successfully locked range 130:4 for READ\n");
2362 status = cli_read(cli1, fnum1, buf, 130, 4, &nread);
2363 if (!NT_STATUS_IS_OK(status)) {
2364 printf("pid1 unable to read the range 130:4, error was %s\n",
2365 nt_errstr(status));
2366 goto fail;
2367 } else if (nread != 4) {
2368 printf("pid1 unable to read the range 130:4, "
2369 "recv %ld req %d\n", (unsigned long)nread, 4);
2370 goto fail;
2371 } else {
2372 printf("pid1 successfully read the range 130:4\n");
2375 status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
2376 if (!NT_STATUS_IS_OK(status)) {
2377 printf("pid1 unable to write to the range 130:4, error was "
2378 "%s\n", nt_errstr(status));
2379 if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
2380 printf("Incorrect error (should be NT_STATUS_FILE_LOCK_CONFLICT)\n");
2381 goto fail;
2383 } else {
2384 printf("pid1 successfully wrote to the range 130:4 (should be denied)\n");
2385 goto fail;
2388 cli_setpid(cli1, 2);
2390 status = cli_read(cli1, fnum1, buf, 130, 4, &nread);
2391 if (!NT_STATUS_IS_OK(status)) {
2392 printf("pid2 unable to read the range 130:4, error was %s\n",
2393 nt_errstr(status));
2394 goto fail;
2395 } else if (nread != 4) {
2396 printf("pid2 unable to read the range 130:4, "
2397 "recv %ld req %d\n", (unsigned long)nread, 4);
2398 goto fail;
2399 } else {
2400 printf("pid2 successfully read the range 130:4\n");
2403 status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
2404 if (!NT_STATUS_IS_OK(status)) {
2405 printf("pid2 unable to write to the range 130:4, error was "
2406 "%s\n", nt_errstr(status));
2407 if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
2408 printf("Incorrect error (should be NT_STATUS_FILE_LOCK_CONFLICT)\n");
2409 goto fail;
2411 } else {
2412 printf("pid2 successfully wrote to the range 130:4 (should be denied)\n");
2413 goto fail;
2416 cli_setpid(cli1, 1);
2417 cli_unlock(cli1, fnum1, 130, 4);
2419 status = cli_lock32(cli1, fnum1, 130, 4, 0, WRITE_LOCK);
2420 if (!NT_STATUS_IS_OK(status)) {
2421 printf("Unable to apply write lock on range 130:4, error was %s\n", nt_errstr(status));
2422 goto fail;
2423 } else {
2424 printf("pid1 successfully locked range 130:4 for WRITE\n");
2427 status = cli_read(cli1, fnum1, buf, 130, 4, &nread);
2428 if (!NT_STATUS_IS_OK(status)) {
2429 printf("pid1 unable to read the range 130:4, error was %s\n",
2430 nt_errstr(status));
2431 goto fail;
2432 } else if (nread != 4) {
2433 printf("pid1 unable to read the range 130:4, "
2434 "recv %ld req %d\n", (unsigned long)nread, 4);
2435 goto fail;
2436 } else {
2437 printf("pid1 successfully read the range 130:4\n");
2440 status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
2441 if (!NT_STATUS_IS_OK(status)) {
2442 printf("pid1 unable to write to the range 130:4, error was "
2443 "%s\n", nt_errstr(status));
2444 goto fail;
2445 } else {
2446 printf("pid1 successfully wrote to the range 130:4\n");
2449 cli_setpid(cli1, 2);
2451 status = cli_read(cli1, fnum1, buf, 130, 4, &nread);
2452 if (!NT_STATUS_IS_OK(status)) {
2453 printf("pid2 unable to read the range 130:4, error was "
2454 "%s\n", nt_errstr(status));
2455 if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
2456 printf("Incorrect error (should be NT_STATUS_FILE_LOCK_CONFLICT)\n");
2457 goto fail;
2459 } else {
2460 printf("pid2 successfully read the range 130:4 (should be denied) recv %ld\n",
2461 (unsigned long)nread);
2462 goto fail;
2465 status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
2466 if (!NT_STATUS_IS_OK(status)) {
2467 printf("pid2 unable to write to the range 130:4, error was "
2468 "%s\n", nt_errstr(status));
2469 if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
2470 printf("Incorrect error (should be NT_STATUS_FILE_LOCK_CONFLICT)\n");
2471 goto fail;
2473 } else {
2474 printf("pid2 successfully wrote to the range 130:4 (should be denied)\n");
2475 goto fail;
2478 cli_unlock(cli1, fnum1, 130, 0);
2479 correct = True;
2481 fail:
2482 cli_close(cli1, fnum1);
2483 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2484 torture_close_connection(cli1);
2486 printf("finished locktest7\n");
2487 return correct;
2491 * This demonstrates a problem with our use of GPFS share modes: A file
2492 * descriptor sitting in the pending close queue holding a GPFS share mode
2493 * blocks opening a file another time. Happens with Word 2007 temp files.
2494 * With "posix locking = yes" and "gpfs:sharemodes = yes" enabled, the third
2495 * open is denied with NT_STATUS_SHARING_VIOLATION.
2498 static bool run_locktest8(int dummy)
2500 struct cli_state *cli1;
2501 const char *fname = "\\lockt8.lck";
2502 uint16_t fnum1, fnum2;
2503 char buf[200];
2504 bool correct = False;
2505 NTSTATUS status;
2507 if (!torture_open_connection(&cli1, 0)) {
2508 return False;
2511 cli_sockopt(cli1, sockops);
2513 printf("starting locktest8\n");
2515 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2517 status = cli_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_WRITE,
2518 &fnum1);
2519 if (!NT_STATUS_IS_OK(status)) {
2520 d_fprintf(stderr, "cli_open returned %s\n", nt_errstr(status));
2521 return false;
2524 memset(buf, 0, sizeof(buf));
2526 status = cli_open(cli1, fname, O_RDONLY, DENY_NONE, &fnum2);
2527 if (!NT_STATUS_IS_OK(status)) {
2528 d_fprintf(stderr, "cli_open second time returned %s\n",
2529 nt_errstr(status));
2530 goto fail;
2533 status = cli_lock32(cli1, fnum2, 1, 1, 0, READ_LOCK);
2534 if (!NT_STATUS_IS_OK(status)) {
2535 printf("Unable to apply read lock on range 1:1, error was "
2536 "%s\n", nt_errstr(status));
2537 goto fail;
2540 status = cli_close(cli1, fnum1);
2541 if (!NT_STATUS_IS_OK(status)) {
2542 d_fprintf(stderr, "cli_close(fnum1) %s\n", nt_errstr(status));
2543 goto fail;
2546 status = cli_open(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
2547 if (!NT_STATUS_IS_OK(status)) {
2548 d_fprintf(stderr, "cli_open third time returned %s\n",
2549 nt_errstr(status));
2550 goto fail;
2553 correct = true;
2555 fail:
2556 cli_close(cli1, fnum1);
2557 cli_close(cli1, fnum2);
2558 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2559 torture_close_connection(cli1);
2561 printf("finished locktest8\n");
2562 return correct;
2566 * This test is designed to be run in conjunction with
2567 * external NFS or POSIX locks taken in the filesystem.
2568 * It checks that the smbd server will block until the
2569 * lock is released and then acquire it. JRA.
2572 static bool got_alarm;
2573 static struct cli_state *alarm_cli;
2575 static void alarm_handler(int dummy)
2577 got_alarm = True;
2580 static void alarm_handler_parent(int dummy)
2582 cli_state_disconnect(alarm_cli);
2585 static void do_local_lock(int read_fd, int write_fd)
2587 int fd;
2588 char c = '\0';
2589 struct flock lock;
2590 const char *local_pathname = NULL;
2591 int ret;
2593 local_pathname = talloc_asprintf(talloc_tos(),
2594 "%s/lockt9.lck", local_path);
2595 if (!local_pathname) {
2596 printf("child: alloc fail\n");
2597 exit(1);
2600 unlink(local_pathname);
2601 fd = open(local_pathname, O_RDWR|O_CREAT, 0666);
2602 if (fd == -1) {
2603 printf("child: open of %s failed %s.\n",
2604 local_pathname, strerror(errno));
2605 exit(1);
2608 /* Now take a fcntl lock. */
2609 lock.l_type = F_WRLCK;
2610 lock.l_whence = SEEK_SET;
2611 lock.l_start = 0;
2612 lock.l_len = 4;
2613 lock.l_pid = getpid();
2615 ret = fcntl(fd,F_SETLK,&lock);
2616 if (ret == -1) {
2617 printf("child: failed to get lock 0:4 on file %s. Error %s\n",
2618 local_pathname, strerror(errno));
2619 exit(1);
2620 } else {
2621 printf("child: got lock 0:4 on file %s.\n",
2622 local_pathname );
2623 fflush(stdout);
2626 CatchSignal(SIGALRM, alarm_handler);
2627 alarm(5);
2628 /* Signal the parent. */
2629 if (write(write_fd, &c, 1) != 1) {
2630 printf("child: start signal fail %s.\n",
2631 strerror(errno));
2632 exit(1);
2634 alarm(0);
2636 alarm(10);
2637 /* Wait for the parent to be ready. */
2638 if (read(read_fd, &c, 1) != 1) {
2639 printf("child: reply signal fail %s.\n",
2640 strerror(errno));
2641 exit(1);
2643 alarm(0);
2645 sleep(5);
2646 close(fd);
2647 printf("child: released lock 0:4 on file %s.\n",
2648 local_pathname );
2649 fflush(stdout);
2650 exit(0);
2653 static bool run_locktest9(int dummy)
2655 struct cli_state *cli1;
2656 const char *fname = "\\lockt9.lck";
2657 uint16_t fnum;
2658 bool correct = False;
2659 int pipe_in[2], pipe_out[2];
2660 pid_t child_pid;
2661 char c = '\0';
2662 int ret;
2663 struct timeval start;
2664 double seconds;
2665 NTSTATUS status;
2667 printf("starting locktest9\n");
2669 if (local_path == NULL) {
2670 d_fprintf(stderr, "locktest9 must be given a local path via -l <localpath>\n");
2671 return false;
2674 if (pipe(pipe_in) == -1 || pipe(pipe_out) == -1) {
2675 return false;
2678 child_pid = fork();
2679 if (child_pid == -1) {
2680 return false;
2683 if (child_pid == 0) {
2684 /* Child. */
2685 do_local_lock(pipe_out[0], pipe_in[1]);
2686 exit(0);
2689 close(pipe_out[0]);
2690 close(pipe_in[1]);
2691 pipe_out[0] = -1;
2692 pipe_in[1] = -1;
2694 /* Parent. */
2695 ret = read(pipe_in[0], &c, 1);
2696 if (ret != 1) {
2697 d_fprintf(stderr, "failed to read start signal from child. %s\n",
2698 strerror(errno));
2699 return false;
2702 if (!torture_open_connection(&cli1, 0)) {
2703 return false;
2706 cli_sockopt(cli1, sockops);
2708 status = cli_open(cli1, fname, O_RDWR, DENY_NONE,
2709 &fnum);
2710 if (!NT_STATUS_IS_OK(status)) {
2711 d_fprintf(stderr, "cli_open returned %s\n", nt_errstr(status));
2712 return false;
2715 /* Ensure the child has the lock. */
2716 status = cli_lock32(cli1, fnum, 0, 4, 0, WRITE_LOCK);
2717 if (NT_STATUS_IS_OK(status)) {
2718 d_fprintf(stderr, "Got the lock on range 0:4 - this should not happen !\n");
2719 goto fail;
2720 } else {
2721 d_printf("Child has the lock.\n");
2724 /* Tell the child to wait 5 seconds then exit. */
2725 ret = write(pipe_out[1], &c, 1);
2726 if (ret != 1) {
2727 d_fprintf(stderr, "failed to send exit signal to child. %s\n",
2728 strerror(errno));
2729 goto fail;
2732 /* Wait 20 seconds for the lock. */
2733 alarm_cli = cli1;
2734 CatchSignal(SIGALRM, alarm_handler_parent);
2735 alarm(20);
2737 start = timeval_current();
2739 status = cli_lock32(cli1, fnum, 0, 4, -1, WRITE_LOCK);
2740 if (!NT_STATUS_IS_OK(status)) {
2741 d_fprintf(stderr, "Unable to apply write lock on range 0:4, error was "
2742 "%s\n", nt_errstr(status));
2743 goto fail_nofd;
2745 alarm(0);
2747 seconds = timeval_elapsed(&start);
2749 printf("Parent got the lock after %.2f seconds.\n",
2750 seconds);
2752 status = cli_close(cli1, fnum);
2753 if (!NT_STATUS_IS_OK(status)) {
2754 d_fprintf(stderr, "cli_close(fnum1) %s\n", nt_errstr(status));
2755 goto fail;
2758 correct = true;
2760 fail:
2761 cli_close(cli1, fnum);
2762 torture_close_connection(cli1);
2764 fail_nofd:
2766 printf("finished locktest9\n");
2767 return correct;
2771 test whether fnums and tids open on one VC are available on another (a major
2772 security hole)
2774 static bool run_fdpasstest(int dummy)
2776 struct cli_state *cli1, *cli2;
2777 const char *fname = "\\fdpass.tst";
2778 uint16_t fnum1;
2779 char buf[1024];
2780 NTSTATUS status;
2782 if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
2783 return False;
2785 cli_sockopt(cli1, sockops);
2786 cli_sockopt(cli2, sockops);
2788 printf("starting fdpasstest\n");
2790 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2792 status = cli_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
2793 &fnum1);
2794 if (!NT_STATUS_IS_OK(status)) {
2795 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
2796 return False;
2799 status = cli_writeall(cli1, fnum1, 0, (const uint8_t *)"hello world\n", 0,
2800 13, NULL);
2801 if (!NT_STATUS_IS_OK(status)) {
2802 printf("write failed (%s)\n", nt_errstr(status));
2803 return False;
2806 cli_state_set_uid(cli2, cli_state_get_uid(cli1));
2807 cli_state_set_tid(cli2, cli_state_get_tid(cli1));
2808 cli_setpid(cli2, cli_getpid(cli1));
2810 if (test_cli_read(cli2, fnum1, buf, 0, 13, NULL, 13)) {
2811 printf("read succeeded! nasty security hole [%s]\n", buf);
2812 return false;
2815 cli_close(cli1, fnum1);
2816 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2818 torture_close_connection(cli1);
2819 torture_close_connection(cli2);
2821 printf("finished fdpasstest\n");
2822 return True;
2825 static bool run_fdsesstest(int dummy)
2827 struct cli_state *cli;
2828 uint16 new_vuid;
2829 uint16 saved_vuid;
2830 uint16 new_cnum;
2831 uint16 saved_cnum;
2832 const char *fname = "\\fdsess.tst";
2833 const char *fname1 = "\\fdsess1.tst";
2834 uint16_t fnum1;
2835 uint16_t fnum2;
2836 char buf[1024];
2837 bool ret = True;
2838 NTSTATUS status;
2840 if (!torture_open_connection(&cli, 0))
2841 return False;
2842 cli_sockopt(cli, sockops);
2844 if (!torture_cli_session_setup2(cli, &new_vuid))
2845 return False;
2847 saved_cnum = cli_state_get_tid(cli);
2848 if (!NT_STATUS_IS_OK(cli_tcon_andx(cli, share, "?????", "", 1)))
2849 return False;
2850 new_cnum = cli_state_get_tid(cli);
2851 cli_state_set_tid(cli, saved_cnum);
2853 printf("starting fdsesstest\n");
2855 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2856 cli_unlink(cli, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2858 status = cli_open(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
2859 if (!NT_STATUS_IS_OK(status)) {
2860 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
2861 return False;
2864 status = cli_writeall(cli, fnum1, 0, (const uint8_t *)"hello world\n", 0, 13,
2865 NULL);
2866 if (!NT_STATUS_IS_OK(status)) {
2867 printf("write failed (%s)\n", nt_errstr(status));
2868 return False;
2871 saved_vuid = cli_state_get_uid(cli);
2872 cli_state_set_uid(cli, new_vuid);
2874 if (test_cli_read(cli, fnum1, buf, 0, 13, NULL, 13)) {
2875 printf("read succeeded with different vuid! "
2876 "nasty security hole [%s]\n", buf);
2877 ret = false;
2879 /* Try to open a file with different vuid, samba cnum. */
2880 if (NT_STATUS_IS_OK(cli_open(cli, fname1, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum2))) {
2881 printf("create with different vuid, same cnum succeeded.\n");
2882 cli_close(cli, fnum2);
2883 cli_unlink(cli, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2884 } else {
2885 printf("create with different vuid, same cnum failed.\n");
2886 printf("This will cause problems with service clients.\n");
2887 ret = False;
2890 cli_state_set_uid(cli, saved_vuid);
2892 /* Try with same vuid, different cnum. */
2893 cli_state_set_tid(cli, new_cnum);
2895 if (test_cli_read(cli, fnum1, buf, 0, 13, NULL, 13)) {
2896 printf("read succeeded with different cnum![%s]\n", buf);
2897 ret = false;
2900 cli_state_set_tid(cli, saved_cnum);
2901 cli_close(cli, fnum1);
2902 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2904 torture_close_connection(cli);
2906 printf("finished fdsesstest\n");
2907 return ret;
2911 This test checks that
2913 1) the server does not allow an unlink on a file that is open
2915 static bool run_unlinktest(int dummy)
2917 struct cli_state *cli;
2918 const char *fname = "\\unlink.tst";
2919 uint16_t fnum;
2920 bool correct = True;
2921 NTSTATUS status;
2923 if (!torture_open_connection(&cli, 0)) {
2924 return False;
2927 cli_sockopt(cli, sockops);
2929 printf("starting unlink test\n");
2931 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2933 cli_setpid(cli, 1);
2935 status = cli_open(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
2936 if (!NT_STATUS_IS_OK(status)) {
2937 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
2938 return False;
2941 status = cli_unlink(cli, fname,
2942 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2943 if (NT_STATUS_IS_OK(status)) {
2944 printf("error: server allowed unlink on an open file\n");
2945 correct = False;
2946 } else {
2947 correct = check_error(__LINE__, status, ERRDOS, ERRbadshare,
2948 NT_STATUS_SHARING_VIOLATION);
2951 cli_close(cli, fnum);
2952 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2954 if (!torture_close_connection(cli)) {
2955 correct = False;
2958 printf("unlink test finished\n");
2960 return correct;
2965 test how many open files this server supports on the one socket
2967 static bool run_maxfidtest(int dummy)
2969 struct cli_state *cli;
2970 fstring fname;
2971 uint16_t fnums[0x11000];
2972 int i;
2973 int retries=4;
2974 bool correct = True;
2975 NTSTATUS status;
2977 cli = current_cli;
2979 if (retries <= 0) {
2980 printf("failed to connect\n");
2981 return False;
2984 cli_sockopt(cli, sockops);
2986 for (i=0; i<0x11000; i++) {
2987 slprintf(fname,sizeof(fname)-1,"\\maxfid.%d.%d", i,(int)getpid());
2988 status = cli_open(cli, fname, O_RDWR|O_CREAT|O_TRUNC, DENY_NONE,
2989 &fnums[i]);
2990 if (!NT_STATUS_IS_OK(status)) {
2991 printf("open of %s failed (%s)\n",
2992 fname, nt_errstr(status));
2993 printf("maximum fnum is %d\n", i);
2994 break;
2996 printf("%6d\r", i);
2998 printf("%6d\n", i);
2999 i--;
3001 printf("cleaning up\n");
3002 for (;i>=0;i--) {
3003 slprintf(fname,sizeof(fname)-1,"\\maxfid.%d.%d", i,(int)getpid());
3004 cli_close(cli, fnums[i]);
3006 status = cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3007 if (!NT_STATUS_IS_OK(status)) {
3008 printf("unlink of %s failed (%s)\n",
3009 fname, nt_errstr(status));
3010 correct = False;
3012 printf("%6d\r", i);
3014 printf("%6d\n", 0);
3016 printf("maxfid test finished\n");
3017 if (!torture_close_connection(cli)) {
3018 correct = False;
3020 return correct;
3023 /* generate a random buffer */
3024 static void rand_buf(char *buf, int len)
3026 while (len--) {
3027 *buf = (char)sys_random();
3028 buf++;
3032 /* send smb negprot commands, not reading the response */
3033 static bool run_negprot_nowait(int dummy)
3035 struct tevent_context *ev;
3036 int i;
3037 struct cli_state *cli;
3038 bool correct = True;
3040 printf("starting negprot nowait test\n");
3042 ev = tevent_context_init(talloc_tos());
3043 if (ev == NULL) {
3044 return false;
3047 if (!(cli = open_nbt_connection())) {
3048 TALLOC_FREE(ev);
3049 return False;
3052 for (i=0;i<50000;i++) {
3053 struct tevent_req *req;
3055 req = cli_negprot_send(ev, ev, cli, PROTOCOL_NT1);
3056 if (req == NULL) {
3057 TALLOC_FREE(ev);
3058 return false;
3060 if (!tevent_req_poll(req, ev)) {
3061 d_fprintf(stderr, "tevent_req_poll failed: %s\n",
3062 strerror(errno));
3063 TALLOC_FREE(ev);
3064 return false;
3066 TALLOC_FREE(req);
3069 if (torture_close_connection(cli)) {
3070 correct = False;
3073 printf("finished negprot nowait test\n");
3075 return correct;
3078 /* send smb negprot commands, not reading the response */
3079 static bool run_bad_nbt_session(int dummy)
3081 struct nmb_name called, calling;
3082 struct sockaddr_storage ss;
3083 NTSTATUS status;
3084 int fd;
3085 bool ret;
3087 printf("starting bad nbt session test\n");
3089 make_nmb_name(&calling, myname, 0x0);
3090 make_nmb_name(&called , host, 0x20);
3092 if (!resolve_name(host, &ss, 0x20, true)) {
3093 d_fprintf(stderr, "Could not resolve name %s\n", host);
3094 return false;
3097 status = open_socket_out(&ss, 139, 10000, &fd);
3098 if (!NT_STATUS_IS_OK(status)) {
3099 d_fprintf(stderr, "open_socket_out failed: %s\n",
3100 nt_errstr(status));
3101 return false;
3104 ret = cli_bad_session_request(fd, &calling, &called);
3105 close(fd);
3106 if (!ret) {
3107 d_fprintf(stderr, "open_socket_out failed: %s\n",
3108 nt_errstr(status));
3109 return false;
3112 printf("finished bad nbt session test\n");
3113 return true;
3116 /* send random IPC commands */
3117 static bool run_randomipc(int dummy)
3119 char *rparam = NULL;
3120 char *rdata = NULL;
3121 unsigned int rdrcnt,rprcnt;
3122 char param[1024];
3123 int api, param_len, i;
3124 struct cli_state *cli;
3125 bool correct = True;
3126 int count = 50000;
3128 printf("starting random ipc test\n");
3130 if (!torture_open_connection(&cli, 0)) {
3131 return False;
3134 for (i=0;i<count;i++) {
3135 api = sys_random() % 500;
3136 param_len = (sys_random() % 64);
3138 rand_buf(param, param_len);
3140 SSVAL(param,0,api);
3142 cli_api(cli,
3143 param, param_len, 8,
3144 NULL, 0, BUFFER_SIZE,
3145 &rparam, &rprcnt,
3146 &rdata, &rdrcnt);
3147 if (i % 100 == 0) {
3148 printf("%d/%d\r", i,count);
3151 printf("%d/%d\n", i, count);
3153 if (!torture_close_connection(cli)) {
3154 correct = False;
3157 printf("finished random ipc test\n");
3159 return correct;
3164 static void browse_callback(const char *sname, uint32 stype,
3165 const char *comment, void *state)
3167 printf("\t%20.20s %08x %s\n", sname, stype, comment);
3173 This test checks the browse list code
3176 static bool run_browsetest(int dummy)
3178 static struct cli_state *cli;
3179 bool correct = True;
3181 printf("starting browse test\n");
3183 if (!torture_open_connection(&cli, 0)) {
3184 return False;
3187 printf("domain list:\n");
3188 cli_NetServerEnum(cli, cli->server_domain,
3189 SV_TYPE_DOMAIN_ENUM,
3190 browse_callback, NULL);
3192 printf("machine list:\n");
3193 cli_NetServerEnum(cli, cli->server_domain,
3194 SV_TYPE_ALL,
3195 browse_callback, NULL);
3197 if (!torture_close_connection(cli)) {
3198 correct = False;
3201 printf("browse test finished\n");
3203 return correct;
3209 This checks how the getatr calls works
3211 static bool run_attrtest(int dummy)
3213 struct cli_state *cli;
3214 uint16_t fnum;
3215 time_t t, t2;
3216 const char *fname = "\\attrib123456789.tst";
3217 bool correct = True;
3218 NTSTATUS status;
3220 printf("starting attrib test\n");
3222 if (!torture_open_connection(&cli, 0)) {
3223 return False;
3226 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3227 cli_open(cli, fname,
3228 O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum);
3229 cli_close(cli, fnum);
3231 status = cli_getatr(cli, fname, NULL, NULL, &t);
3232 if (!NT_STATUS_IS_OK(status)) {
3233 printf("getatr failed (%s)\n", nt_errstr(status));
3234 correct = False;
3237 if (abs(t - time(NULL)) > 60*60*24*10) {
3238 printf("ERROR: SMBgetatr bug. time is %s",
3239 ctime(&t));
3240 t = time(NULL);
3241 correct = True;
3244 t2 = t-60*60*24; /* 1 day ago */
3246 status = cli_setatr(cli, fname, 0, t2);
3247 if (!NT_STATUS_IS_OK(status)) {
3248 printf("setatr failed (%s)\n", nt_errstr(status));
3249 correct = True;
3252 status = cli_getatr(cli, fname, NULL, NULL, &t);
3253 if (!NT_STATUS_IS_OK(status)) {
3254 printf("getatr failed (%s)\n", nt_errstr(status));
3255 correct = True;
3258 if (t != t2) {
3259 printf("ERROR: getatr/setatr bug. times are\n%s",
3260 ctime(&t));
3261 printf("%s", ctime(&t2));
3262 correct = True;
3265 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3267 if (!torture_close_connection(cli)) {
3268 correct = False;
3271 printf("attrib test finished\n");
3273 return correct;
3278 This checks a couple of trans2 calls
3280 static bool run_trans2test(int dummy)
3282 struct cli_state *cli;
3283 uint16_t fnum;
3284 SMB_OFF_T size;
3285 time_t c_time, a_time, m_time;
3286 struct timespec c_time_ts, a_time_ts, m_time_ts, w_time_ts, m_time2_ts;
3287 const char *fname = "\\trans2.tst";
3288 const char *dname = "\\trans2";
3289 const char *fname2 = "\\trans2\\trans2.tst";
3290 char *pname;
3291 bool correct = True;
3292 NTSTATUS status;
3293 uint32_t fs_attr;
3295 printf("starting trans2 test\n");
3297 if (!torture_open_connection(&cli, 0)) {
3298 return False;
3301 status = cli_get_fs_attr_info(cli, &fs_attr);
3302 if (!NT_STATUS_IS_OK(status)) {
3303 printf("ERROR: cli_get_fs_attr_info returned %s\n",
3304 nt_errstr(status));
3305 correct = false;
3308 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3309 cli_open(cli, fname, O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum);
3310 status = cli_qfileinfo_basic(cli, fnum, NULL, &size, &c_time_ts,
3311 &a_time_ts, &w_time_ts, &m_time_ts, NULL);
3312 if (!NT_STATUS_IS_OK(status)) {
3313 printf("ERROR: qfileinfo failed (%s)\n", nt_errstr(status));
3314 correct = False;
3317 status = cli_qfilename(cli, fnum, talloc_tos(), &pname);
3318 if (!NT_STATUS_IS_OK(status)) {
3319 printf("ERROR: qfilename failed (%s)\n", nt_errstr(status));
3320 correct = False;
3323 if (strcmp(pname, fname)) {
3324 printf("qfilename gave different name? [%s] [%s]\n",
3325 fname, pname);
3326 correct = False;
3329 cli_close(cli, fnum);
3331 sleep(2);
3333 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3334 status = cli_open(cli, fname, O_RDWR | O_CREAT | O_TRUNC, DENY_NONE,
3335 &fnum);
3336 if (!NT_STATUS_IS_OK(status)) {
3337 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
3338 return False;
3340 cli_close(cli, fnum);
3342 status = cli_qpathinfo1(cli, fname, &c_time, &a_time, &m_time, &size,
3343 NULL);
3344 if (!NT_STATUS_IS_OK(status)) {
3345 printf("ERROR: qpathinfo failed (%s)\n", nt_errstr(status));
3346 correct = False;
3347 } else {
3348 time_t t = time(NULL);
3350 if (c_time != m_time) {
3351 printf("create time=%s", ctime(&c_time));
3352 printf("modify time=%s", ctime(&m_time));
3353 printf("This system appears to have sticky create times\n");
3355 if ((abs(a_time - t) > 60) && (a_time % (60*60) == 0)) {
3356 printf("access time=%s", ctime(&a_time));
3357 printf("This system appears to set a midnight access time\n");
3358 correct = False;
3361 if (abs(m_time - t) > 60*60*24*7) {
3362 printf("ERROR: totally incorrect times - maybe word reversed? mtime=%s", ctime(&m_time));
3363 correct = False;
3368 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3369 cli_open(cli, fname,
3370 O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum);
3371 cli_close(cli, fnum);
3372 status = cli_qpathinfo2(cli, fname, &c_time_ts, &a_time_ts, &w_time_ts,
3373 &m_time_ts, &size, NULL, NULL);
3374 if (!NT_STATUS_IS_OK(status)) {
3375 printf("ERROR: qpathinfo2 failed (%s)\n", nt_errstr(status));
3376 correct = False;
3377 } else {
3378 if (w_time_ts.tv_sec < 60*60*24*2) {
3379 printf("write time=%s", ctime(&w_time_ts.tv_sec));
3380 printf("This system appears to set a initial 0 write time\n");
3381 correct = False;
3385 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3388 /* check if the server updates the directory modification time
3389 when creating a new file */
3390 status = cli_mkdir(cli, dname);
3391 if (!NT_STATUS_IS_OK(status)) {
3392 printf("ERROR: mkdir failed (%s)\n", nt_errstr(status));
3393 correct = False;
3395 sleep(3);
3396 status = cli_qpathinfo2(cli, "\\trans2\\", &c_time_ts, &a_time_ts,
3397 &w_time_ts, &m_time_ts, &size, NULL, NULL);
3398 if (!NT_STATUS_IS_OK(status)) {
3399 printf("ERROR: qpathinfo2 failed (%s)\n", nt_errstr(status));
3400 correct = False;
3403 cli_open(cli, fname2,
3404 O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum);
3405 cli_writeall(cli, fnum, 0, (uint8_t *)&fnum, 0, sizeof(fnum), NULL);
3406 cli_close(cli, fnum);
3407 status = cli_qpathinfo2(cli, "\\trans2\\", &c_time_ts, &a_time_ts,
3408 &w_time_ts, &m_time2_ts, &size, NULL, NULL);
3409 if (!NT_STATUS_IS_OK(status)) {
3410 printf("ERROR: qpathinfo2 failed (%s)\n", nt_errstr(status));
3411 correct = False;
3412 } else {
3413 if (memcmp(&m_time_ts, &m_time2_ts, sizeof(struct timespec))
3414 == 0) {
3415 printf("This system does not update directory modification times\n");
3416 correct = False;
3419 cli_unlink(cli, fname2, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3420 cli_rmdir(cli, dname);
3422 if (!torture_close_connection(cli)) {
3423 correct = False;
3426 printf("trans2 test finished\n");
3428 return correct;
3432 This checks new W2K calls.
3435 static NTSTATUS new_trans(struct cli_state *pcli, int fnum, int level)
3437 uint8_t *buf = NULL;
3438 uint32 len;
3439 NTSTATUS status;
3441 status = cli_qfileinfo(talloc_tos(), pcli, fnum, level, 0,
3442 CLI_BUFFER_SIZE, NULL, &buf, &len);
3443 if (!NT_STATUS_IS_OK(status)) {
3444 printf("ERROR: qfileinfo (%d) failed (%s)\n", level,
3445 nt_errstr(status));
3446 } else {
3447 printf("qfileinfo: level %d, len = %u\n", level, len);
3448 dump_data(0, (uint8 *)buf, len);
3449 printf("\n");
3451 TALLOC_FREE(buf);
3452 return status;
3455 static bool run_w2ktest(int dummy)
3457 struct cli_state *cli;
3458 uint16_t fnum;
3459 const char *fname = "\\w2ktest\\w2k.tst";
3460 int level;
3461 bool correct = True;
3463 printf("starting w2k test\n");
3465 if (!torture_open_connection(&cli, 0)) {
3466 return False;
3469 cli_open(cli, fname,
3470 O_RDWR | O_CREAT , DENY_NONE, &fnum);
3472 for (level = 1004; level < 1040; level++) {
3473 new_trans(cli, fnum, level);
3476 cli_close(cli, fnum);
3478 if (!torture_close_connection(cli)) {
3479 correct = False;
3482 printf("w2k test finished\n");
3484 return correct;
3489 this is a harness for some oplock tests
3491 static bool run_oplock1(int dummy)
3493 struct cli_state *cli1;
3494 const char *fname = "\\lockt1.lck";
3495 uint16_t fnum1;
3496 bool correct = True;
3497 NTSTATUS status;
3499 printf("starting oplock test 1\n");
3501 if (!torture_open_connection(&cli1, 0)) {
3502 return False;
3505 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3507 cli_sockopt(cli1, sockops);
3509 cli1->use_oplocks = True;
3511 status = cli_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
3512 &fnum1);
3513 if (!NT_STATUS_IS_OK(status)) {
3514 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
3515 return False;
3518 cli1->use_oplocks = False;
3520 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3521 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3523 status = cli_close(cli1, fnum1);
3524 if (!NT_STATUS_IS_OK(status)) {
3525 printf("close2 failed (%s)\n", nt_errstr(status));
3526 return False;
3529 status = cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3530 if (!NT_STATUS_IS_OK(status)) {
3531 printf("unlink failed (%s)\n", nt_errstr(status));
3532 return False;
3535 if (!torture_close_connection(cli1)) {
3536 correct = False;
3539 printf("finished oplock test 1\n");
3541 return correct;
3544 static bool run_oplock2(int dummy)
3546 struct cli_state *cli1, *cli2;
3547 const char *fname = "\\lockt2.lck";
3548 uint16_t fnum1, fnum2;
3549 int saved_use_oplocks = use_oplocks;
3550 char buf[4];
3551 bool correct = True;
3552 volatile bool *shared_correct;
3553 size_t nread;
3554 NTSTATUS status;
3556 shared_correct = (volatile bool *)shm_setup(sizeof(bool));
3557 *shared_correct = True;
3559 use_level_II_oplocks = True;
3560 use_oplocks = True;
3562 printf("starting oplock test 2\n");
3564 if (!torture_open_connection(&cli1, 0)) {
3565 use_level_II_oplocks = False;
3566 use_oplocks = saved_use_oplocks;
3567 return False;
3570 if (!torture_open_connection(&cli2, 1)) {
3571 use_level_II_oplocks = False;
3572 use_oplocks = saved_use_oplocks;
3573 return False;
3576 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3578 cli_sockopt(cli1, sockops);
3579 cli_sockopt(cli2, sockops);
3581 status = cli_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
3582 &fnum1);
3583 if (!NT_STATUS_IS_OK(status)) {
3584 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
3585 return False;
3588 /* Don't need the globals any more. */
3589 use_level_II_oplocks = False;
3590 use_oplocks = saved_use_oplocks;
3592 if (fork() == 0) {
3593 /* Child code */
3594 status = cli_open(cli2, fname, O_RDWR, DENY_NONE, &fnum2);
3595 if (!NT_STATUS_IS_OK(status)) {
3596 printf("second open of %s failed (%s)\n", fname, nt_errstr(status));
3597 *shared_correct = False;
3598 exit(0);
3601 sleep(2);
3603 status = cli_close(cli2, fnum2);
3604 if (!NT_STATUS_IS_OK(status)) {
3605 printf("close2 failed (%s)\n", nt_errstr(status));
3606 *shared_correct = False;
3609 exit(0);
3612 sleep(2);
3614 /* Ensure cli1 processes the break. Empty file should always return 0
3615 * bytes. */
3616 status = cli_read(cli1, fnum1, buf, 0, 4, &nread);
3617 if (!NT_STATUS_IS_OK(status)) {
3618 printf("read on fnum1 failed (%s)\n", nt_errstr(status));
3619 correct = false;
3620 } else if (nread != 0) {
3621 printf("read on empty fnum1 failed. recv %ld expected %d\n",
3622 (unsigned long)nread, 0);
3623 correct = false;
3626 /* Should now be at level II. */
3627 /* Test if sending a write locks causes a break to none. */
3628 status = cli_lock32(cli1, fnum1, 0, 4, 0, READ_LOCK);
3629 if (!NT_STATUS_IS_OK(status)) {
3630 printf("lock failed (%s)\n", nt_errstr(status));
3631 correct = False;
3634 cli_unlock(cli1, fnum1, 0, 4);
3636 sleep(2);
3638 status = cli_lock32(cli1, fnum1, 0, 4, 0, WRITE_LOCK);
3639 if (!NT_STATUS_IS_OK(status)) {
3640 printf("lock failed (%s)\n", nt_errstr(status));
3641 correct = False;
3644 cli_unlock(cli1, fnum1, 0, 4);
3646 sleep(2);
3648 cli_read(cli1, fnum1, buf, 0, 4, NULL);
3650 status = cli_close(cli1, fnum1);
3651 if (!NT_STATUS_IS_OK(status)) {
3652 printf("close1 failed (%s)\n", nt_errstr(status));
3653 correct = False;
3656 sleep(4);
3658 status = cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3659 if (!NT_STATUS_IS_OK(status)) {
3660 printf("unlink failed (%s)\n", nt_errstr(status));
3661 correct = False;
3664 if (!torture_close_connection(cli1)) {
3665 correct = False;
3668 if (!*shared_correct) {
3669 correct = False;
3672 printf("finished oplock test 2\n");
3674 return correct;
3677 struct oplock4_state {
3678 struct tevent_context *ev;
3679 struct cli_state *cli;
3680 bool *got_break;
3681 uint16_t *fnum2;
3684 static void oplock4_got_break(struct tevent_req *req);
3685 static void oplock4_got_open(struct tevent_req *req);
3687 static bool run_oplock4(int dummy)
3689 struct tevent_context *ev;
3690 struct cli_state *cli1, *cli2;
3691 struct tevent_req *oplock_req, *open_req;
3692 const char *fname = "\\lockt4.lck";
3693 const char *fname_ln = "\\lockt4_ln.lck";
3694 uint16_t fnum1, fnum2;
3695 int saved_use_oplocks = use_oplocks;
3696 NTSTATUS status;
3697 bool correct = true;
3699 bool got_break;
3701 struct oplock4_state *state;
3703 printf("starting oplock test 4\n");
3705 if (!torture_open_connection(&cli1, 0)) {
3706 use_level_II_oplocks = false;
3707 use_oplocks = saved_use_oplocks;
3708 return false;
3711 if (!torture_open_connection(&cli2, 1)) {
3712 use_level_II_oplocks = false;
3713 use_oplocks = saved_use_oplocks;
3714 return false;
3717 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3718 cli_unlink(cli1, fname_ln, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3720 cli_sockopt(cli1, sockops);
3721 cli_sockopt(cli2, sockops);
3723 /* Create the file. */
3724 status = cli_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
3725 &fnum1);
3726 if (!NT_STATUS_IS_OK(status)) {
3727 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
3728 return false;
3731 status = cli_close(cli1, fnum1);
3732 if (!NT_STATUS_IS_OK(status)) {
3733 printf("close1 failed (%s)\n", nt_errstr(status));
3734 return false;
3737 /* Now create a hardlink. */
3738 status = cli_nt_hardlink(cli1, fname, fname_ln);
3739 if (!NT_STATUS_IS_OK(status)) {
3740 printf("nt hardlink failed (%s)\n", nt_errstr(status));
3741 return false;
3744 /* Prove that opening hardlinks cause deny modes to conflict. */
3745 status = cli_open(cli1, fname, O_RDWR, DENY_ALL, &fnum1);
3746 if (!NT_STATUS_IS_OK(status)) {
3747 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
3748 return false;
3751 status = cli_open(cli1, fname_ln, O_RDWR, DENY_NONE, &fnum2);
3752 if (NT_STATUS_IS_OK(status)) {
3753 printf("open of %s succeeded - should fail with sharing violation.\n",
3754 fname_ln);
3755 return false;
3758 if (!NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
3759 printf("open of %s should fail with sharing violation. Got %s\n",
3760 fname_ln, nt_errstr(status));
3761 return false;
3764 status = cli_close(cli1, fnum1);
3765 if (!NT_STATUS_IS_OK(status)) {
3766 printf("close1 failed (%s)\n", nt_errstr(status));
3767 return false;
3770 cli1->use_oplocks = true;
3771 cli2->use_oplocks = true;
3773 status = cli_open(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
3774 if (!NT_STATUS_IS_OK(status)) {
3775 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
3776 return false;
3779 ev = tevent_context_init(talloc_tos());
3780 if (ev == NULL) {
3781 printf("tevent_req_create failed\n");
3782 return false;
3785 state = talloc(ev, struct oplock4_state);
3786 if (state == NULL) {
3787 printf("talloc failed\n");
3788 return false;
3790 state->ev = ev;
3791 state->cli = cli1;
3792 state->got_break = &got_break;
3793 state->fnum2 = &fnum2;
3795 oplock_req = cli_smb_oplock_break_waiter_send(
3796 talloc_tos(), ev, cli1);
3797 if (oplock_req == NULL) {
3798 printf("cli_smb_oplock_break_waiter_send failed\n");
3799 return false;
3801 tevent_req_set_callback(oplock_req, oplock4_got_break, state);
3803 open_req = cli_open_send(
3804 talloc_tos(), ev, cli2, fname_ln, O_RDWR, DENY_NONE);
3805 if (oplock_req == NULL) {
3806 printf("cli_open_send failed\n");
3807 return false;
3809 tevent_req_set_callback(open_req, oplock4_got_open, state);
3811 got_break = false;
3812 fnum2 = 0xffff;
3814 while (!got_break || fnum2 == 0xffff) {
3815 int ret;
3816 ret = tevent_loop_once(ev);
3817 if (ret == -1) {
3818 printf("tevent_loop_once failed: %s\n",
3819 strerror(errno));
3820 return false;
3824 status = cli_close(cli2, fnum2);
3825 if (!NT_STATUS_IS_OK(status)) {
3826 printf("close2 failed (%s)\n", nt_errstr(status));
3827 correct = false;
3830 status = cli_close(cli1, fnum1);
3831 if (!NT_STATUS_IS_OK(status)) {
3832 printf("close1 failed (%s)\n", nt_errstr(status));
3833 correct = false;
3836 status = cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3837 if (!NT_STATUS_IS_OK(status)) {
3838 printf("unlink failed (%s)\n", nt_errstr(status));
3839 correct = false;
3842 status = cli_unlink(cli1, fname_ln, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3843 if (!NT_STATUS_IS_OK(status)) {
3844 printf("unlink failed (%s)\n", nt_errstr(status));
3845 correct = false;
3848 if (!torture_close_connection(cli1)) {
3849 correct = false;
3852 if (!got_break) {
3853 correct = false;
3856 printf("finished oplock test 4\n");
3858 return correct;
3861 static void oplock4_got_break(struct tevent_req *req)
3863 struct oplock4_state *state = tevent_req_callback_data(
3864 req, struct oplock4_state);
3865 uint16_t fnum;
3866 uint8_t level;
3867 NTSTATUS status;
3869 status = cli_smb_oplock_break_waiter_recv(req, &fnum, &level);
3870 TALLOC_FREE(req);
3871 if (!NT_STATUS_IS_OK(status)) {
3872 printf("cli_smb_oplock_break_waiter_recv returned %s\n",
3873 nt_errstr(status));
3874 return;
3876 *state->got_break = true;
3878 req = cli_oplock_ack_send(state, state->ev, state->cli, fnum,
3879 NO_OPLOCK);
3880 if (req == NULL) {
3881 printf("cli_oplock_ack_send failed\n");
3882 return;
3886 static void oplock4_got_open(struct tevent_req *req)
3888 struct oplock4_state *state = tevent_req_callback_data(
3889 req, struct oplock4_state);
3890 NTSTATUS status;
3892 status = cli_open_recv(req, state->fnum2);
3893 if (!NT_STATUS_IS_OK(status)) {
3894 printf("cli_open_recv returned %s\n", nt_errstr(status));
3895 *state->fnum2 = 0xffff;
3900 Test delete on close semantics.
3902 static bool run_deletetest(int dummy)
3904 struct cli_state *cli1 = NULL;
3905 struct cli_state *cli2 = NULL;
3906 const char *fname = "\\delete.file";
3907 uint16_t fnum1 = (uint16_t)-1;
3908 uint16_t fnum2 = (uint16_t)-1;
3909 bool correct = True;
3910 NTSTATUS status;
3912 printf("starting delete test\n");
3914 if (!torture_open_connection(&cli1, 0)) {
3915 return False;
3918 cli_sockopt(cli1, sockops);
3920 /* Test 1 - this should delete the file on close. */
3922 cli_setatr(cli1, fname, 0, 0);
3923 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3925 status = cli_ntcreate(cli1, fname, 0, GENERIC_ALL_ACCESS|DELETE_ACCESS,
3926 FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
3927 FILE_DELETE_ON_CLOSE, 0, &fnum1);
3928 if (!NT_STATUS_IS_OK(status)) {
3929 printf("[1] open of %s failed (%s)\n", fname, nt_errstr(status));
3930 correct = False;
3931 goto fail;
3934 status = cli_close(cli1, fnum1);
3935 if (!NT_STATUS_IS_OK(status)) {
3936 printf("[1] close failed (%s)\n", nt_errstr(status));
3937 correct = False;
3938 goto fail;
3941 if (NT_STATUS_IS_OK(cli_open(cli1, fname, O_RDWR, DENY_NONE, &fnum1))) {
3942 printf("[1] open of %s succeeded (should fail)\n", fname);
3943 correct = False;
3944 goto fail;
3947 printf("first delete on close test succeeded.\n");
3949 /* Test 2 - this should delete the file on close. */
3951 cli_setatr(cli1, fname, 0, 0);
3952 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3954 status = cli_ntcreate(cli1, fname, 0, GENERIC_ALL_ACCESS,
3955 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
3956 FILE_OVERWRITE_IF, 0, 0, &fnum1);
3957 if (!NT_STATUS_IS_OK(status)) {
3958 printf("[2] open of %s failed (%s)\n", fname, nt_errstr(status));
3959 correct = False;
3960 goto fail;
3963 status = cli_nt_delete_on_close(cli1, fnum1, true);
3964 if (!NT_STATUS_IS_OK(status)) {
3965 printf("[2] setting delete_on_close failed (%s)\n", nt_errstr(status));
3966 correct = False;
3967 goto fail;
3970 status = cli_close(cli1, fnum1);
3971 if (!NT_STATUS_IS_OK(status)) {
3972 printf("[2] close failed (%s)\n", nt_errstr(status));
3973 correct = False;
3974 goto fail;
3977 if (NT_STATUS_IS_OK(cli_open(cli1, fname, O_RDONLY, DENY_NONE, &fnum1))) {
3978 printf("[2] open of %s succeeded should have been deleted on close !\n", fname);
3979 status = cli_close(cli1, fnum1);
3980 if (!NT_STATUS_IS_OK(status)) {
3981 printf("[2] close failed (%s)\n", nt_errstr(status));
3982 correct = False;
3983 goto fail;
3985 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3986 } else
3987 printf("second delete on close test succeeded.\n");
3989 /* Test 3 - ... */
3990 cli_setatr(cli1, fname, 0, 0);
3991 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3993 status = cli_ntcreate(cli1, fname, 0, GENERIC_ALL_ACCESS,
3994 FILE_ATTRIBUTE_NORMAL,
3995 FILE_SHARE_READ|FILE_SHARE_WRITE,
3996 FILE_OVERWRITE_IF, 0, 0, &fnum1);
3997 if (!NT_STATUS_IS_OK(status)) {
3998 printf("[3] open - 1 of %s failed (%s)\n", fname, nt_errstr(status));
3999 correct = False;
4000 goto fail;
4003 /* This should fail with a sharing violation - open for delete is only compatible
4004 with SHARE_DELETE. */
4006 if (NT_STATUS_IS_OK(cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS, FILE_ATTRIBUTE_NORMAL,
4007 FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OPEN, 0, 0, &fnum2))) {
4008 printf("[3] open - 2 of %s succeeded - should have failed.\n", fname);
4009 correct = False;
4010 goto fail;
4013 /* This should succeed. */
4014 status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
4015 FILE_ATTRIBUTE_NORMAL,
4016 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4017 FILE_OPEN, 0, 0, &fnum2);
4018 if (!NT_STATUS_IS_OK(status)) {
4019 printf("[3] open - 2 of %s failed (%s)\n", fname, nt_errstr(status));
4020 correct = False;
4021 goto fail;
4024 status = cli_nt_delete_on_close(cli1, fnum1, true);
4025 if (!NT_STATUS_IS_OK(status)) {
4026 printf("[3] setting delete_on_close failed (%s)\n", nt_errstr(status));
4027 correct = False;
4028 goto fail;
4031 status = cli_close(cli1, fnum1);
4032 if (!NT_STATUS_IS_OK(status)) {
4033 printf("[3] close 1 failed (%s)\n", nt_errstr(status));
4034 correct = False;
4035 goto fail;
4038 status = cli_close(cli1, fnum2);
4039 if (!NT_STATUS_IS_OK(status)) {
4040 printf("[3] close 2 failed (%s)\n", nt_errstr(status));
4041 correct = False;
4042 goto fail;
4045 /* This should fail - file should no longer be there. */
4047 if (NT_STATUS_IS_OK(cli_open(cli1, fname, O_RDONLY, DENY_NONE, &fnum1))) {
4048 printf("[3] open of %s succeeded should have been deleted on close !\n", fname);
4049 status = cli_close(cli1, fnum1);
4050 if (!NT_STATUS_IS_OK(status)) {
4051 printf("[3] close failed (%s)\n", nt_errstr(status));
4053 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4054 correct = False;
4055 goto fail;
4056 } else
4057 printf("third delete on close test succeeded.\n");
4059 /* Test 4 ... */
4060 cli_setatr(cli1, fname, 0, 0);
4061 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4063 status = cli_ntcreate(cli1, fname, 0,
4064 FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
4065 FILE_ATTRIBUTE_NORMAL,
4066 FILE_SHARE_READ|FILE_SHARE_WRITE,
4067 FILE_OVERWRITE_IF, 0, 0, &fnum1);
4068 if (!NT_STATUS_IS_OK(status)) {
4069 printf("[4] open of %s failed (%s)\n", fname, nt_errstr(status));
4070 correct = False;
4071 goto fail;
4074 /* This should succeed. */
4075 status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
4076 FILE_ATTRIBUTE_NORMAL,
4077 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4078 FILE_OPEN, 0, 0, &fnum2);
4079 if (!NT_STATUS_IS_OK(status)) {
4080 printf("[4] open - 2 of %s failed (%s)\n", fname, nt_errstr(status));
4081 correct = False;
4082 goto fail;
4085 status = cli_close(cli1, fnum2);
4086 if (!NT_STATUS_IS_OK(status)) {
4087 printf("[4] close - 1 failed (%s)\n", nt_errstr(status));
4088 correct = False;
4089 goto fail;
4092 status = cli_nt_delete_on_close(cli1, fnum1, true);
4093 if (!NT_STATUS_IS_OK(status)) {
4094 printf("[4] setting delete_on_close failed (%s)\n", nt_errstr(status));
4095 correct = False;
4096 goto fail;
4099 /* This should fail - no more opens once delete on close set. */
4100 if (NT_STATUS_IS_OK(cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
4101 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4102 FILE_OPEN, 0, 0, &fnum2))) {
4103 printf("[4] open - 3 of %s succeeded ! Should have failed.\n", fname );
4104 correct = False;
4105 goto fail;
4106 } else
4107 printf("fourth delete on close test succeeded.\n");
4109 status = cli_close(cli1, fnum1);
4110 if (!NT_STATUS_IS_OK(status)) {
4111 printf("[4] close - 2 failed (%s)\n", nt_errstr(status));
4112 correct = False;
4113 goto fail;
4116 /* Test 5 ... */
4117 cli_setatr(cli1, fname, 0, 0);
4118 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4120 status = cli_open(cli1, fname, O_RDWR|O_CREAT, DENY_NONE, &fnum1);
4121 if (!NT_STATUS_IS_OK(status)) {
4122 printf("[5] open of %s failed (%s)\n", fname, nt_errstr(status));
4123 correct = False;
4124 goto fail;
4127 /* This should fail - only allowed on NT opens with DELETE access. */
4129 if (NT_STATUS_IS_OK(cli_nt_delete_on_close(cli1, fnum1, true))) {
4130 printf("[5] setting delete_on_close on OpenX file succeeded - should fail !\n");
4131 correct = False;
4132 goto fail;
4135 status = cli_close(cli1, fnum1);
4136 if (!NT_STATUS_IS_OK(status)) {
4137 printf("[5] close - 2 failed (%s)\n", nt_errstr(status));
4138 correct = False;
4139 goto fail;
4142 printf("fifth delete on close test succeeded.\n");
4144 /* Test 6 ... */
4145 cli_setatr(cli1, fname, 0, 0);
4146 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4148 status = cli_ntcreate(cli1, fname, 0, FILE_READ_DATA|FILE_WRITE_DATA,
4149 FILE_ATTRIBUTE_NORMAL,
4150 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4151 FILE_OVERWRITE_IF, 0, 0, &fnum1);
4152 if (!NT_STATUS_IS_OK(status)) {
4153 printf("[6] open of %s failed (%s)\n", fname,
4154 nt_errstr(status));
4155 correct = False;
4156 goto fail;
4159 /* This should fail - only allowed on NT opens with DELETE access. */
4161 if (NT_STATUS_IS_OK(cli_nt_delete_on_close(cli1, fnum1, true))) {
4162 printf("[6] setting delete_on_close on file with no delete access succeeded - should fail !\n");
4163 correct = False;
4164 goto fail;
4167 status = cli_close(cli1, fnum1);
4168 if (!NT_STATUS_IS_OK(status)) {
4169 printf("[6] close - 2 failed (%s)\n", nt_errstr(status));
4170 correct = False;
4171 goto fail;
4174 printf("sixth delete on close test succeeded.\n");
4176 /* Test 7 ... */
4177 cli_setatr(cli1, fname, 0, 0);
4178 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4180 status = cli_ntcreate(cli1, fname, 0,
4181 FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
4182 FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
4183 0, 0, &fnum1);
4184 if (!NT_STATUS_IS_OK(status)) {
4185 printf("[7] open of %s failed (%s)\n", fname, nt_errstr(status));
4186 correct = False;
4187 goto fail;
4190 if (!NT_STATUS_IS_OK(cli_nt_delete_on_close(cli1, fnum1, true))) {
4191 printf("[7] setting delete_on_close on file failed !\n");
4192 correct = False;
4193 goto fail;
4196 if (!NT_STATUS_IS_OK(cli_nt_delete_on_close(cli1, fnum1, false))) {
4197 printf("[7] unsetting delete_on_close on file failed !\n");
4198 correct = False;
4199 goto fail;
4202 status = cli_close(cli1, fnum1);
4203 if (!NT_STATUS_IS_OK(status)) {
4204 printf("[7] close - 2 failed (%s)\n", nt_errstr(status));
4205 correct = False;
4206 goto fail;
4209 /* This next open should succeed - we reset the flag. */
4210 status = cli_open(cli1, fname, O_RDONLY, DENY_NONE, &fnum1);
4211 if (!NT_STATUS_IS_OK(status)) {
4212 printf("[5] open of %s failed (%s)\n", fname, nt_errstr(status));
4213 correct = False;
4214 goto fail;
4217 status = cli_close(cli1, fnum1);
4218 if (!NT_STATUS_IS_OK(status)) {
4219 printf("[7] close - 2 failed (%s)\n", nt_errstr(status));
4220 correct = False;
4221 goto fail;
4224 printf("seventh delete on close test succeeded.\n");
4226 /* Test 7 ... */
4227 cli_setatr(cli1, fname, 0, 0);
4228 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4230 if (!torture_open_connection(&cli2, 1)) {
4231 printf("[8] failed to open second connection.\n");
4232 correct = False;
4233 goto fail;
4236 cli_sockopt(cli1, sockops);
4238 status = cli_ntcreate(cli1, fname, 0,
4239 FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
4240 FILE_ATTRIBUTE_NORMAL,
4241 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4242 FILE_OVERWRITE_IF, 0, 0, &fnum1);
4243 if (!NT_STATUS_IS_OK(status)) {
4244 printf("[8] open 1 of %s failed (%s)\n", fname, nt_errstr(status));
4245 correct = False;
4246 goto fail;
4249 status = cli_ntcreate(cli2, fname, 0,
4250 FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
4251 FILE_ATTRIBUTE_NORMAL,
4252 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4253 FILE_OPEN, 0, 0, &fnum2);
4254 if (!NT_STATUS_IS_OK(status)) {
4255 printf("[8] open 2 of %s failed (%s)\n", fname, nt_errstr(status));
4256 correct = False;
4257 goto fail;
4260 if (!NT_STATUS_IS_OK(cli_nt_delete_on_close(cli1, fnum1, true))) {
4261 printf("[8] setting delete_on_close on file failed !\n");
4262 correct = False;
4263 goto fail;
4266 status = cli_close(cli1, fnum1);
4267 if (!NT_STATUS_IS_OK(status)) {
4268 printf("[8] close - 1 failed (%s)\n", nt_errstr(status));
4269 correct = False;
4270 goto fail;
4273 status = cli_close(cli2, fnum2);
4274 if (!NT_STATUS_IS_OK(status)) {
4275 printf("[8] close - 2 failed (%s)\n", nt_errstr(status));
4276 correct = False;
4277 goto fail;
4280 /* This should fail.. */
4281 status = cli_open(cli1, fname, O_RDONLY, DENY_NONE, &fnum1);
4282 if (NT_STATUS_IS_OK(status)) {
4283 printf("[8] open of %s succeeded should have been deleted on close !\n", fname);
4284 goto fail;
4285 correct = False;
4286 } else
4287 printf("eighth delete on close test succeeded.\n");
4289 /* This should fail - we need to set DELETE_ACCESS. */
4290 if (NT_STATUS_IS_OK(cli_ntcreate(cli1, fname, 0,FILE_READ_DATA|FILE_WRITE_DATA,
4291 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE, FILE_OVERWRITE_IF, FILE_DELETE_ON_CLOSE, 0, &fnum1))) {
4292 printf("[9] open of %s succeeded should have failed!\n", fname);
4293 correct = False;
4294 goto fail;
4297 printf("ninth delete on close test succeeded.\n");
4299 status = cli_ntcreate(cli1, fname, 0,
4300 FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
4301 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
4302 FILE_OVERWRITE_IF, FILE_DELETE_ON_CLOSE,
4303 0, &fnum1);
4304 if (!NT_STATUS_IS_OK(status)) {
4305 printf("[10] open of %s failed (%s)\n", fname, nt_errstr(status));
4306 correct = False;
4307 goto fail;
4310 /* This should delete the file. */
4311 status = cli_close(cli1, fnum1);
4312 if (!NT_STATUS_IS_OK(status)) {
4313 printf("[10] close failed (%s)\n", nt_errstr(status));
4314 correct = False;
4315 goto fail;
4318 /* This should fail.. */
4319 if (NT_STATUS_IS_OK(cli_open(cli1, fname, O_RDONLY, DENY_NONE, &fnum1))) {
4320 printf("[10] open of %s succeeded should have been deleted on close !\n", fname);
4321 goto fail;
4322 correct = False;
4323 } else
4324 printf("tenth delete on close test succeeded.\n");
4326 cli_setatr(cli1, fname, 0, 0);
4327 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4329 /* What error do we get when attempting to open a read-only file with
4330 delete access ? */
4332 /* Create a readonly file. */
4333 status = cli_ntcreate(cli1, fname, 0, FILE_READ_DATA|FILE_WRITE_DATA,
4334 FILE_ATTRIBUTE_READONLY, FILE_SHARE_NONE,
4335 FILE_OVERWRITE_IF, 0, 0, &fnum1);
4336 if (!NT_STATUS_IS_OK(status)) {
4337 printf("[11] open of %s failed (%s)\n", fname, nt_errstr(status));
4338 correct = False;
4339 goto fail;
4342 status = cli_close(cli1, fnum1);
4343 if (!NT_STATUS_IS_OK(status)) {
4344 printf("[11] close failed (%s)\n", nt_errstr(status));
4345 correct = False;
4346 goto fail;
4349 /* Now try open for delete access. */
4350 status = cli_ntcreate(cli1, fname, 0,
4351 FILE_READ_ATTRIBUTES|DELETE_ACCESS,
4353 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4354 FILE_OVERWRITE_IF, 0, 0, &fnum1);
4355 if (NT_STATUS_IS_OK(status)) {
4356 printf("[11] open of %s succeeded should have been denied with ACCESS_DENIED!\n", fname);
4357 cli_close(cli1, fnum1);
4358 goto fail;
4359 correct = False;
4360 } else {
4361 if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
4362 printf("[11] open of %s should have been denied with ACCESS_DENIED! Got error %s\n", fname, nt_errstr(status));
4363 goto fail;
4364 correct = False;
4365 } else {
4366 printf("eleventh delete on close test succeeded.\n");
4370 printf("finished delete test\n");
4372 fail:
4373 /* FIXME: This will crash if we aborted before cli2 got
4374 * intialized, because these functions don't handle
4375 * uninitialized connections. */
4377 if (fnum1 != (uint16_t)-1) cli_close(cli1, fnum1);
4378 if (fnum2 != (uint16_t)-1) cli_close(cli1, fnum2);
4379 cli_setatr(cli1, fname, 0, 0);
4380 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4382 if (cli1 && !torture_close_connection(cli1)) {
4383 correct = False;
4385 if (cli2 && !torture_close_connection(cli2)) {
4386 correct = False;
4388 return correct;
4391 static bool run_deletetest_ln(int dummy)
4393 struct cli_state *cli;
4394 const char *fname = "\\delete1";
4395 const char *fname_ln = "\\delete1_ln";
4396 uint16_t fnum;
4397 uint16_t fnum1;
4398 NTSTATUS status;
4399 bool correct = true;
4400 time_t t;
4402 printf("starting deletetest-ln\n");
4404 if (!torture_open_connection(&cli, 0)) {
4405 return false;
4408 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4409 cli_unlink(cli, fname_ln, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4411 cli_sockopt(cli, sockops);
4413 /* Create the file. */
4414 status = cli_open(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
4415 if (!NT_STATUS_IS_OK(status)) {
4416 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
4417 return false;
4420 status = cli_close(cli, fnum);
4421 if (!NT_STATUS_IS_OK(status)) {
4422 printf("close1 failed (%s)\n", nt_errstr(status));
4423 return false;
4426 /* Now create a hardlink. */
4427 status = cli_nt_hardlink(cli, fname, fname_ln);
4428 if (!NT_STATUS_IS_OK(status)) {
4429 printf("nt hardlink failed (%s)\n", nt_errstr(status));
4430 return false;
4433 /* Open the original file. */
4434 status = cli_ntcreate(cli, fname, 0, FILE_READ_DATA,
4435 FILE_ATTRIBUTE_NORMAL,
4436 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4437 FILE_OPEN_IF, 0, 0, &fnum);
4438 if (!NT_STATUS_IS_OK(status)) {
4439 printf("ntcreate of %s failed (%s)\n", fname, nt_errstr(status));
4440 return false;
4443 /* Unlink the hard link path. */
4444 status = cli_ntcreate(cli, fname_ln, 0, DELETE_ACCESS,
4445 FILE_ATTRIBUTE_NORMAL,
4446 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4447 FILE_OPEN_IF, 0, 0, &fnum1);
4448 if (!NT_STATUS_IS_OK(status)) {
4449 printf("ntcreate of %s failed (%s)\n", fname_ln, nt_errstr(status));
4450 return false;
4452 status = cli_nt_delete_on_close(cli, fnum1, true);
4453 if (!NT_STATUS_IS_OK(status)) {
4454 d_printf("(%s) failed to set delete_on_close %s: %s\n",
4455 __location__, fname_ln, nt_errstr(status));
4456 return false;
4459 status = cli_close(cli, fnum1);
4460 if (!NT_STATUS_IS_OK(status)) {
4461 printf("close %s failed (%s)\n",
4462 fname_ln, nt_errstr(status));
4463 return false;
4466 status = cli_close(cli, fnum);
4467 if (!NT_STATUS_IS_OK(status)) {
4468 printf("close %s failed (%s)\n",
4469 fname, nt_errstr(status));
4470 return false;
4473 /* Ensure the original file is still there. */
4474 status = cli_getatr(cli, fname, NULL, NULL, &t);
4475 if (!NT_STATUS_IS_OK(status)) {
4476 printf("%s getatr on file %s failed (%s)\n",
4477 __location__,
4478 fname,
4479 nt_errstr(status));
4480 correct = False;
4483 /* Ensure the link path is gone. */
4484 status = cli_getatr(cli, fname_ln, NULL, NULL, &t);
4485 if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
4486 printf("%s, getatr for file %s returned wrong error code %s "
4487 "- should have been deleted\n",
4488 __location__,
4489 fname_ln, nt_errstr(status));
4490 correct = False;
4493 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4494 cli_unlink(cli, fname_ln, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4496 if (!torture_close_connection(cli)) {
4497 correct = false;
4500 printf("finished deletetest-ln\n");
4502 return correct;
4506 print out server properties
4508 static bool run_properties(int dummy)
4510 struct cli_state *cli;
4511 bool correct = True;
4513 printf("starting properties test\n");
4515 ZERO_STRUCT(cli);
4517 if (!torture_open_connection(&cli, 0)) {
4518 return False;
4521 cli_sockopt(cli, sockops);
4523 d_printf("Capabilities 0x%08x\n", cli_state_capabilities(cli));
4525 if (!torture_close_connection(cli)) {
4526 correct = False;
4529 return correct;
4534 /* FIRST_DESIRED_ACCESS 0xf019f */
4535 #define FIRST_DESIRED_ACCESS FILE_READ_DATA|FILE_WRITE_DATA|FILE_APPEND_DATA|\
4536 FILE_READ_EA| /* 0xf */ \
4537 FILE_WRITE_EA|FILE_READ_ATTRIBUTES| /* 0x90 */ \
4538 FILE_WRITE_ATTRIBUTES| /* 0x100 */ \
4539 DELETE_ACCESS|READ_CONTROL_ACCESS|\
4540 WRITE_DAC_ACCESS|WRITE_OWNER_ACCESS /* 0xf0000 */
4541 /* SECOND_DESIRED_ACCESS 0xe0080 */
4542 #define SECOND_DESIRED_ACCESS FILE_READ_ATTRIBUTES| /* 0x80 */ \
4543 READ_CONTROL_ACCESS|WRITE_DAC_ACCESS|\
4544 WRITE_OWNER_ACCESS /* 0xe0000 */
4546 #if 0
4547 #define THIRD_DESIRED_ACCESS FILE_READ_ATTRIBUTES| /* 0x80 */ \
4548 READ_CONTROL_ACCESS|WRITE_DAC_ACCESS|\
4549 FILE_READ_DATA|\
4550 WRITE_OWNER_ACCESS /* */
4551 #endif
4554 Test ntcreate calls made by xcopy
4556 static bool run_xcopy(int dummy)
4558 static struct cli_state *cli1;
4559 const char *fname = "\\test.txt";
4560 bool correct = True;
4561 uint16_t fnum1, fnum2;
4562 NTSTATUS status;
4564 printf("starting xcopy test\n");
4566 if (!torture_open_connection(&cli1, 0)) {
4567 return False;
4570 status = cli_ntcreate(cli1, fname, 0, FIRST_DESIRED_ACCESS,
4571 FILE_ATTRIBUTE_ARCHIVE, FILE_SHARE_NONE,
4572 FILE_OVERWRITE_IF, 0x4044, 0, &fnum1);
4573 if (!NT_STATUS_IS_OK(status)) {
4574 printf("First open failed - %s\n", nt_errstr(status));
4575 return False;
4578 status = cli_ntcreate(cli1, fname, 0, SECOND_DESIRED_ACCESS, 0,
4579 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4580 FILE_OPEN, 0x200000, 0, &fnum2);
4581 if (!NT_STATUS_IS_OK(status)) {
4582 printf("second open failed - %s\n", nt_errstr(status));
4583 return False;
4586 if (!torture_close_connection(cli1)) {
4587 correct = False;
4590 return correct;
4594 Test rename on files open with share delete and no share delete.
4596 static bool run_rename(int dummy)
4598 static struct cli_state *cli1;
4599 const char *fname = "\\test.txt";
4600 const char *fname1 = "\\test1.txt";
4601 bool correct = True;
4602 uint16_t fnum1;
4603 uint16_t attr;
4604 NTSTATUS status;
4606 printf("starting rename test\n");
4608 if (!torture_open_connection(&cli1, 0)) {
4609 return False;
4612 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4613 cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4615 status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
4616 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ,
4617 FILE_OVERWRITE_IF, 0, 0, &fnum1);
4618 if (!NT_STATUS_IS_OK(status)) {
4619 printf("First open failed - %s\n", nt_errstr(status));
4620 return False;
4623 status = cli_rename(cli1, fname, fname1);
4624 if (!NT_STATUS_IS_OK(status)) {
4625 printf("First rename failed (SHARE_READ) (this is correct) - %s\n", nt_errstr(status));
4626 } else {
4627 printf("First rename succeeded (SHARE_READ) - this should have failed !\n");
4628 correct = False;
4631 status = cli_close(cli1, fnum1);
4632 if (!NT_STATUS_IS_OK(status)) {
4633 printf("close - 1 failed (%s)\n", nt_errstr(status));
4634 return False;
4637 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4638 cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4639 status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS, FILE_ATTRIBUTE_NORMAL,
4640 #if 0
4641 FILE_SHARE_DELETE|FILE_SHARE_NONE,
4642 #else
4643 FILE_SHARE_DELETE|FILE_SHARE_READ,
4644 #endif
4645 FILE_OVERWRITE_IF, 0, 0, &fnum1);
4646 if (!NT_STATUS_IS_OK(status)) {
4647 printf("Second open failed - %s\n", nt_errstr(status));
4648 return False;
4651 status = cli_rename(cli1, fname, fname1);
4652 if (!NT_STATUS_IS_OK(status)) {
4653 printf("Second rename failed (SHARE_DELETE | SHARE_READ) - this should have succeeded - %s\n", nt_errstr(status));
4654 correct = False;
4655 } else {
4656 printf("Second rename succeeded (SHARE_DELETE | SHARE_READ)\n");
4659 status = cli_close(cli1, fnum1);
4660 if (!NT_STATUS_IS_OK(status)) {
4661 printf("close - 2 failed (%s)\n", nt_errstr(status));
4662 return False;
4665 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4666 cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4668 status = cli_ntcreate(cli1, fname, 0, READ_CONTROL_ACCESS,
4669 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
4670 FILE_OVERWRITE_IF, 0, 0, &fnum1);
4671 if (!NT_STATUS_IS_OK(status)) {
4672 printf("Third open failed - %s\n", nt_errstr(status));
4673 return False;
4677 #if 0
4679 uint16_t fnum2;
4681 if (!NT_STATUS_IS_OK(cli_ntcreate(cli1, fname, 0, DELETE_ACCESS, FILE_ATTRIBUTE_NORMAL,
4682 FILE_SHARE_NONE, FILE_OVERWRITE_IF, 0, 0, &fnum2))) {
4683 printf("Fourth open failed - %s\n", cli_errstr(cli1));
4684 return False;
4686 if (!NT_STATUS_IS_OK(cli_nt_delete_on_close(cli1, fnum2, true))) {
4687 printf("[8] setting delete_on_close on file failed !\n");
4688 return False;
4691 if (!NT_STATUS_IS_OK(cli_close(cli1, fnum2))) {
4692 printf("close - 4 failed (%s)\n", cli_errstr(cli1));
4693 return False;
4696 #endif
4698 status = cli_rename(cli1, fname, fname1);
4699 if (!NT_STATUS_IS_OK(status)) {
4700 printf("Third rename failed (SHARE_NONE) - this should have succeeded - %s\n", nt_errstr(status));
4701 correct = False;
4702 } else {
4703 printf("Third rename succeeded (SHARE_NONE)\n");
4706 status = cli_close(cli1, fnum1);
4707 if (!NT_STATUS_IS_OK(status)) {
4708 printf("close - 3 failed (%s)\n", nt_errstr(status));
4709 return False;
4712 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4713 cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4715 /*----*/
4717 status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
4718 FILE_ATTRIBUTE_NORMAL,
4719 FILE_SHARE_READ | FILE_SHARE_WRITE,
4720 FILE_OVERWRITE_IF, 0, 0, &fnum1);
4721 if (!NT_STATUS_IS_OK(status)) {
4722 printf("Fourth open failed - %s\n", nt_errstr(status));
4723 return False;
4726 status = cli_rename(cli1, fname, fname1);
4727 if (!NT_STATUS_IS_OK(status)) {
4728 printf("Fourth rename failed (SHARE_READ | SHARE_WRITE) (this is correct) - %s\n", nt_errstr(status));
4729 } else {
4730 printf("Fourth rename succeeded (SHARE_READ | SHARE_WRITE) - this should have failed !\n");
4731 correct = False;
4734 status = cli_close(cli1, fnum1);
4735 if (!NT_STATUS_IS_OK(status)) {
4736 printf("close - 4 failed (%s)\n", nt_errstr(status));
4737 return False;
4740 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4741 cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4743 /*--*/
4745 status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
4746 FILE_ATTRIBUTE_NORMAL,
4747 FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
4748 FILE_OVERWRITE_IF, 0, 0, &fnum1);
4749 if (!NT_STATUS_IS_OK(status)) {
4750 printf("Fifth open failed - %s\n", nt_errstr(status));
4751 return False;
4754 status = cli_rename(cli1, fname, fname1);
4755 if (!NT_STATUS_IS_OK(status)) {
4756 printf("Fifth rename failed (SHARE_READ | SHARE_WRITE | SHARE_DELETE) - this should have succeeded - %s ! \n", nt_errstr(status));
4757 correct = False;
4758 } else {
4759 printf("Fifth rename succeeded (SHARE_READ | SHARE_WRITE | SHARE_DELETE) (this is correct) - %s\n", nt_errstr(status));
4763 * Now check if the first name still exists ...
4766 /* if (!NT_STATUS_OP(cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS, FILE_ATTRIBUTE_NORMAL,
4767 FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, FILE_OVERWRITE_IF, 0, 0, &fnum2))) {
4768 printf("Opening original file after rename of open file fails: %s\n",
4769 cli_errstr(cli1));
4771 else {
4772 printf("Opening original file after rename of open file works ...\n");
4773 (void)cli_close(cli1, fnum2);
4774 } */
4776 /*--*/
4777 status = cli_close(cli1, fnum1);
4778 if (!NT_STATUS_IS_OK(status)) {
4779 printf("close - 5 failed (%s)\n", nt_errstr(status));
4780 return False;
4783 /* Check that the renamed file has FILE_ATTRIBUTE_ARCHIVE. */
4784 status = cli_getatr(cli1, fname1, &attr, NULL, NULL);
4785 if (!NT_STATUS_IS_OK(status)) {
4786 printf("getatr on file %s failed - %s ! \n",
4787 fname1, nt_errstr(status));
4788 correct = False;
4789 } else {
4790 if (attr != FILE_ATTRIBUTE_ARCHIVE) {
4791 printf("Renamed file %s has wrong attr 0x%x "
4792 "(should be 0x%x)\n",
4793 fname1,
4794 attr,
4795 (unsigned int)FILE_ATTRIBUTE_ARCHIVE);
4796 correct = False;
4797 } else {
4798 printf("Renamed file %s has archive bit set\n", fname1);
4802 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4803 cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4805 if (!torture_close_connection(cli1)) {
4806 correct = False;
4809 return correct;
4812 static bool run_pipe_number(int dummy)
4814 struct cli_state *cli1;
4815 const char *pipe_name = "\\SPOOLSS";
4816 uint16_t fnum;
4817 int num_pipes = 0;
4818 NTSTATUS status;
4820 printf("starting pipenumber test\n");
4821 if (!torture_open_connection(&cli1, 0)) {
4822 return False;
4825 cli_sockopt(cli1, sockops);
4826 while(1) {
4827 status = cli_ntcreate(cli1, pipe_name, 0, FILE_READ_DATA,
4828 FILE_ATTRIBUTE_NORMAL,
4829 FILE_SHARE_READ|FILE_SHARE_WRITE,
4830 FILE_OPEN_IF, 0, 0, &fnum);
4831 if (!NT_STATUS_IS_OK(status)) {
4832 printf("Open of pipe %s failed with error (%s)\n", pipe_name, nt_errstr(status));
4833 break;
4835 num_pipes++;
4836 printf("\r%6d", num_pipes);
4839 printf("pipe_number test - we can open %d %s pipes.\n", num_pipes, pipe_name );
4840 torture_close_connection(cli1);
4841 return True;
4845 Test open mode returns on read-only files.
4847 static bool run_opentest(int dummy)
4849 static struct cli_state *cli1;
4850 static struct cli_state *cli2;
4851 const char *fname = "\\readonly.file";
4852 uint16_t fnum1, fnum2;
4853 char buf[20];
4854 SMB_OFF_T fsize;
4855 bool correct = True;
4856 char *tmp_path;
4857 NTSTATUS status;
4859 printf("starting open test\n");
4861 if (!torture_open_connection(&cli1, 0)) {
4862 return False;
4865 cli_setatr(cli1, fname, 0, 0);
4866 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4868 cli_sockopt(cli1, sockops);
4870 status = cli_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
4871 if (!NT_STATUS_IS_OK(status)) {
4872 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
4873 return False;
4876 status = cli_close(cli1, fnum1);
4877 if (!NT_STATUS_IS_OK(status)) {
4878 printf("close2 failed (%s)\n", nt_errstr(status));
4879 return False;
4882 status = cli_setatr(cli1, fname, FILE_ATTRIBUTE_READONLY, 0);
4883 if (!NT_STATUS_IS_OK(status)) {
4884 printf("cli_setatr failed (%s)\n", nt_errstr(status));
4885 return False;
4888 status = cli_open(cli1, fname, O_RDONLY, DENY_WRITE, &fnum1);
4889 if (!NT_STATUS_IS_OK(status)) {
4890 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
4891 return False;
4894 /* This will fail - but the error should be ERRnoaccess, not ERRbadshare. */
4895 status = cli_open(cli1, fname, O_RDWR, DENY_ALL, &fnum2);
4897 if (check_error(__LINE__, status, ERRDOS, ERRnoaccess,
4898 NT_STATUS_ACCESS_DENIED)) {
4899 printf("correct error code ERRDOS/ERRnoaccess returned\n");
4902 printf("finished open test 1\n");
4904 cli_close(cli1, fnum1);
4906 /* Now try not readonly and ensure ERRbadshare is returned. */
4908 cli_setatr(cli1, fname, 0, 0);
4910 status = cli_open(cli1, fname, O_RDONLY, DENY_WRITE, &fnum1);
4911 if (!NT_STATUS_IS_OK(status)) {
4912 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
4913 return False;
4916 /* This will fail - but the error should be ERRshare. */
4917 status = cli_open(cli1, fname, O_RDWR, DENY_ALL, &fnum2);
4919 if (check_error(__LINE__, status, ERRDOS, ERRbadshare,
4920 NT_STATUS_SHARING_VIOLATION)) {
4921 printf("correct error code ERRDOS/ERRbadshare returned\n");
4924 status = cli_close(cli1, fnum1);
4925 if (!NT_STATUS_IS_OK(status)) {
4926 printf("close2 failed (%s)\n", nt_errstr(status));
4927 return False;
4930 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4932 printf("finished open test 2\n");
4934 /* Test truncate open disposition on file opened for read. */
4935 status = cli_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
4936 if (!NT_STATUS_IS_OK(status)) {
4937 printf("(3) open (1) of %s failed (%s)\n", fname, nt_errstr(status));
4938 return False;
4941 /* write 20 bytes. */
4943 memset(buf, '\0', 20);
4945 status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 0, 20, NULL);
4946 if (!NT_STATUS_IS_OK(status)) {
4947 printf("write failed (%s)\n", nt_errstr(status));
4948 correct = False;
4951 status = cli_close(cli1, fnum1);
4952 if (!NT_STATUS_IS_OK(status)) {
4953 printf("(3) close1 failed (%s)\n", nt_errstr(status));
4954 return False;
4957 /* Ensure size == 20. */
4958 status = cli_getatr(cli1, fname, NULL, &fsize, NULL);
4959 if (!NT_STATUS_IS_OK(status)) {
4960 printf("(3) getatr failed (%s)\n", nt_errstr(status));
4961 return False;
4964 if (fsize != 20) {
4965 printf("(3) file size != 20\n");
4966 return False;
4969 /* Now test if we can truncate a file opened for readonly. */
4970 status = cli_open(cli1, fname, O_RDONLY|O_TRUNC, DENY_NONE, &fnum1);
4971 if (!NT_STATUS_IS_OK(status)) {
4972 printf("(3) open (2) of %s failed (%s)\n", fname, nt_errstr(status));
4973 return False;
4976 status = cli_close(cli1, fnum1);
4977 if (!NT_STATUS_IS_OK(status)) {
4978 printf("close2 failed (%s)\n", nt_errstr(status));
4979 return False;
4982 /* Ensure size == 0. */
4983 status = cli_getatr(cli1, fname, NULL, &fsize, NULL);
4984 if (!NT_STATUS_IS_OK(status)) {
4985 printf("(3) getatr failed (%s)\n", nt_errstr(status));
4986 return False;
4989 if (fsize != 0) {
4990 printf("(3) file size != 0\n");
4991 return False;
4993 printf("finished open test 3\n");
4995 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4997 printf("Do ctemp tests\n");
4998 status = cli_ctemp(cli1, talloc_tos(), "\\", &fnum1, &tmp_path);
4999 if (!NT_STATUS_IS_OK(status)) {
5000 printf("ctemp failed (%s)\n", nt_errstr(status));
5001 return False;
5004 printf("ctemp gave path %s\n", tmp_path);
5005 status = cli_close(cli1, fnum1);
5006 if (!NT_STATUS_IS_OK(status)) {
5007 printf("close of temp failed (%s)\n", nt_errstr(status));
5010 status = cli_unlink(cli1, tmp_path, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5011 if (!NT_STATUS_IS_OK(status)) {
5012 printf("unlink of temp failed (%s)\n", nt_errstr(status));
5015 /* Test the non-io opens... */
5017 if (!torture_open_connection(&cli2, 1)) {
5018 return False;
5021 cli_setatr(cli2, fname, 0, 0);
5022 cli_unlink(cli2, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5024 cli_sockopt(cli2, sockops);
5026 printf("TEST #1 testing 2 non-io opens (no delete)\n");
5027 status = cli_ntcreate(cli1, fname, 0, FILE_READ_ATTRIBUTES,
5028 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
5029 FILE_OVERWRITE_IF, 0, 0, &fnum1);
5030 if (!NT_STATUS_IS_OK(status)) {
5031 printf("TEST #1 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
5032 return False;
5035 status = cli_ntcreate(cli2, fname, 0, FILE_READ_ATTRIBUTES,
5036 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
5037 FILE_OPEN_IF, 0, 0, &fnum2);
5038 if (!NT_STATUS_IS_OK(status)) {
5039 printf("TEST #1 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
5040 return False;
5043 status = cli_close(cli1, fnum1);
5044 if (!NT_STATUS_IS_OK(status)) {
5045 printf("TEST #1 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
5046 return False;
5049 status = cli_close(cli2, fnum2);
5050 if (!NT_STATUS_IS_OK(status)) {
5051 printf("TEST #1 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
5052 return False;
5055 printf("non-io open test #1 passed.\n");
5057 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5059 printf("TEST #2 testing 2 non-io opens (first with delete)\n");
5061 status = cli_ntcreate(cli1, fname, 0,
5062 DELETE_ACCESS|FILE_READ_ATTRIBUTES,
5063 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
5064 FILE_OVERWRITE_IF, 0, 0, &fnum1);
5065 if (!NT_STATUS_IS_OK(status)) {
5066 printf("TEST #2 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
5067 return False;
5070 status = cli_ntcreate(cli2, fname, 0, FILE_READ_ATTRIBUTES,
5071 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
5072 FILE_OPEN_IF, 0, 0, &fnum2);
5073 if (!NT_STATUS_IS_OK(status)) {
5074 printf("TEST #2 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
5075 return False;
5078 status = cli_close(cli1, fnum1);
5079 if (!NT_STATUS_IS_OK(status)) {
5080 printf("TEST #2 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
5081 return False;
5084 status = cli_close(cli2, fnum2);
5085 if (!NT_STATUS_IS_OK(status)) {
5086 printf("TEST #2 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
5087 return False;
5090 printf("non-io open test #2 passed.\n");
5092 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5094 printf("TEST #3 testing 2 non-io opens (second with delete)\n");
5096 status = cli_ntcreate(cli1, fname, 0, FILE_READ_ATTRIBUTES,
5097 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
5098 FILE_OVERWRITE_IF, 0, 0, &fnum1);
5099 if (!NT_STATUS_IS_OK(status)) {
5100 printf("TEST #3 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
5101 return False;
5104 status = cli_ntcreate(cli2, fname, 0,
5105 DELETE_ACCESS|FILE_READ_ATTRIBUTES,
5106 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
5107 FILE_OPEN_IF, 0, 0, &fnum2);
5108 if (!NT_STATUS_IS_OK(status)) {
5109 printf("TEST #3 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
5110 return False;
5113 status = cli_close(cli1, fnum1);
5114 if (!NT_STATUS_IS_OK(status)) {
5115 printf("TEST #3 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
5116 return False;
5119 status = cli_close(cli2, fnum2);
5120 if (!NT_STATUS_IS_OK(status)) {
5121 printf("TEST #3 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
5122 return False;
5125 printf("non-io open test #3 passed.\n");
5127 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5129 printf("TEST #4 testing 2 non-io opens (both with delete)\n");
5131 status = cli_ntcreate(cli1, fname, 0,
5132 DELETE_ACCESS|FILE_READ_ATTRIBUTES,
5133 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
5134 FILE_OVERWRITE_IF, 0, 0, &fnum1);
5135 if (!NT_STATUS_IS_OK(status)) {
5136 printf("TEST #4 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
5137 return False;
5140 status = cli_ntcreate(cli2, fname, 0,
5141 DELETE_ACCESS|FILE_READ_ATTRIBUTES,
5142 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
5143 FILE_OPEN_IF, 0, 0, &fnum2);
5144 if (NT_STATUS_IS_OK(status)) {
5145 printf("TEST #4 open 2 of %s SUCCEEDED - should have failed (%s)\n", fname, nt_errstr(status));
5146 return False;
5149 printf("TEST #4 open 2 of %s gave %s (correct error should be %s)\n", fname, nt_errstr(status), "sharing violation");
5151 status = cli_close(cli1, fnum1);
5152 if (!NT_STATUS_IS_OK(status)) {
5153 printf("TEST #4 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
5154 return False;
5157 printf("non-io open test #4 passed.\n");
5159 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5161 printf("TEST #5 testing 2 non-io opens (both with delete - both with file share delete)\n");
5163 status = cli_ntcreate(cli1, fname, 0,
5164 DELETE_ACCESS|FILE_READ_ATTRIBUTES,
5165 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_DELETE,
5166 FILE_OVERWRITE_IF, 0, 0, &fnum1);
5167 if (!NT_STATUS_IS_OK(status)) {
5168 printf("TEST #5 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
5169 return False;
5172 status = cli_ntcreate(cli2, fname, 0,
5173 DELETE_ACCESS|FILE_READ_ATTRIBUTES,
5174 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_DELETE,
5175 FILE_OPEN_IF, 0, 0, &fnum2);
5176 if (!NT_STATUS_IS_OK(status)) {
5177 printf("TEST #5 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
5178 return False;
5181 status = cli_close(cli1, fnum1);
5182 if (!NT_STATUS_IS_OK(status)) {
5183 printf("TEST #5 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
5184 return False;
5187 status = cli_close(cli2, fnum2);
5188 if (!NT_STATUS_IS_OK(status)) {
5189 printf("TEST #5 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
5190 return False;
5193 printf("non-io open test #5 passed.\n");
5195 printf("TEST #6 testing 1 non-io open, one io open\n");
5197 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5199 status = cli_ntcreate(cli1, fname, 0, FILE_READ_DATA,
5200 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
5201 FILE_OVERWRITE_IF, 0, 0, &fnum1);
5202 if (!NT_STATUS_IS_OK(status)) {
5203 printf("TEST #6 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
5204 return False;
5207 status = cli_ntcreate(cli2, fname, 0, FILE_READ_ATTRIBUTES,
5208 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ,
5209 FILE_OPEN_IF, 0, 0, &fnum2);
5210 if (!NT_STATUS_IS_OK(status)) {
5211 printf("TEST #6 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
5212 return False;
5215 status = cli_close(cli1, fnum1);
5216 if (!NT_STATUS_IS_OK(status)) {
5217 printf("TEST #6 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
5218 return False;
5221 status = cli_close(cli2, fnum2);
5222 if (!NT_STATUS_IS_OK(status)) {
5223 printf("TEST #6 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
5224 return False;
5227 printf("non-io open test #6 passed.\n");
5229 printf("TEST #7 testing 1 non-io open, one io open with delete\n");
5231 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5233 status = cli_ntcreate(cli1, fname, 0, FILE_READ_DATA,
5234 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
5235 FILE_OVERWRITE_IF, 0, 0, &fnum1);
5236 if (!NT_STATUS_IS_OK(status)) {
5237 printf("TEST #7 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
5238 return False;
5241 status = cli_ntcreate(cli2, fname, 0,
5242 DELETE_ACCESS|FILE_READ_ATTRIBUTES,
5243 FILE_ATTRIBUTE_NORMAL,
5244 FILE_SHARE_READ|FILE_SHARE_DELETE,
5245 FILE_OPEN_IF, 0, 0, &fnum2);
5246 if (NT_STATUS_IS_OK(status)) {
5247 printf("TEST #7 open 2 of %s SUCCEEDED - should have failed (%s)\n", fname, nt_errstr(status));
5248 return False;
5251 printf("TEST #7 open 2 of %s gave %s (correct error should be %s)\n", fname, nt_errstr(status), "sharing violation");
5253 status = cli_close(cli1, fnum1);
5254 if (!NT_STATUS_IS_OK(status)) {
5255 printf("TEST #7 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
5256 return False;
5259 printf("non-io open test #7 passed.\n");
5261 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5263 printf("TEST #8 testing open without WRITE_ATTRIBUTES, updating close write time.\n");
5264 status = cli_ntcreate(cli1, fname, 0, FILE_WRITE_DATA, FILE_ATTRIBUTE_NORMAL,
5265 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5266 FILE_OVERWRITE_IF, 0, 0, &fnum1);
5267 if (!NT_STATUS_IS_OK(status)) {
5268 printf("TEST #8 open of %s failed (%s)\n", fname, nt_errstr(status));
5269 correct = false;
5270 goto out;
5273 /* Write to ensure we have to update the file time. */
5274 status = cli_writeall(cli1, fnum1, 0, (const uint8_t *)"TEST DATA\n", 0, 10,
5275 NULL);
5276 if (!NT_STATUS_IS_OK(status)) {
5277 printf("TEST #8 cli_write failed: %s\n", nt_errstr(status));
5278 correct = false;
5279 goto out;
5282 status = cli_close(cli1, fnum1);
5283 if (!NT_STATUS_IS_OK(status)) {
5284 printf("TEST #8 close of %s failed (%s)\n", fname, nt_errstr(status));
5285 correct = false;
5288 out:
5290 if (!torture_close_connection(cli1)) {
5291 correct = False;
5293 if (!torture_close_connection(cli2)) {
5294 correct = False;
5297 return correct;
5300 NTSTATUS torture_setup_unix_extensions(struct cli_state *cli)
5302 uint16 major, minor;
5303 uint32 caplow, caphigh;
5304 NTSTATUS status;
5306 if (!SERVER_HAS_UNIX_CIFS(cli)) {
5307 printf("Server doesn't support UNIX CIFS extensions.\n");
5308 return NT_STATUS_NOT_SUPPORTED;
5311 status = cli_unix_extensions_version(cli, &major, &minor, &caplow,
5312 &caphigh);
5313 if (!NT_STATUS_IS_OK(status)) {
5314 printf("Server didn't return UNIX CIFS extensions: %s\n",
5315 nt_errstr(status));
5316 return status;
5319 status = cli_set_unix_extensions_capabilities(cli, major, minor,
5320 caplow, caphigh);
5321 if (!NT_STATUS_IS_OK(status)) {
5322 printf("Server doesn't support setting UNIX CIFS extensions: "
5323 "%s.\n", nt_errstr(status));
5324 return status;
5327 return NT_STATUS_OK;
5331 Test POSIX open /mkdir calls.
5333 static bool run_simple_posix_open_test(int dummy)
5335 static struct cli_state *cli1;
5336 const char *fname = "posix:file";
5337 const char *hname = "posix:hlink";
5338 const char *sname = "posix:symlink";
5339 const char *dname = "posix:dir";
5340 char buf[10];
5341 char namebuf[11];
5342 uint16_t fnum1 = (uint16_t)-1;
5343 SMB_STRUCT_STAT sbuf;
5344 bool correct = false;
5345 NTSTATUS status;
5346 size_t nread;
5348 printf("Starting simple POSIX open test\n");
5350 if (!torture_open_connection(&cli1, 0)) {
5351 return false;
5354 cli_sockopt(cli1, sockops);
5356 status = torture_setup_unix_extensions(cli1);
5357 if (!NT_STATUS_IS_OK(status)) {
5358 return false;
5361 cli_setatr(cli1, fname, 0, 0);
5362 cli_posix_unlink(cli1, fname);
5363 cli_setatr(cli1, dname, 0, 0);
5364 cli_posix_rmdir(cli1, dname);
5365 cli_setatr(cli1, hname, 0, 0);
5366 cli_posix_unlink(cli1, hname);
5367 cli_setatr(cli1, sname, 0, 0);
5368 cli_posix_unlink(cli1, sname);
5370 /* Create a directory. */
5371 status = cli_posix_mkdir(cli1, dname, 0777);
5372 if (!NT_STATUS_IS_OK(status)) {
5373 printf("POSIX mkdir of %s failed (%s)\n", dname, nt_errstr(status));
5374 goto out;
5377 status = cli_posix_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL,
5378 0600, &fnum1);
5379 if (!NT_STATUS_IS_OK(status)) {
5380 printf("POSIX create of %s failed (%s)\n", fname, nt_errstr(status));
5381 goto out;
5384 /* Test ftruncate - set file size. */
5385 status = cli_ftruncate(cli1, fnum1, 1000);
5386 if (!NT_STATUS_IS_OK(status)) {
5387 printf("ftruncate failed (%s)\n", nt_errstr(status));
5388 goto out;
5391 /* Ensure st_size == 1000 */
5392 status = cli_posix_stat(cli1, fname, &sbuf);
5393 if (!NT_STATUS_IS_OK(status)) {
5394 printf("stat failed (%s)\n", nt_errstr(status));
5395 goto out;
5398 if (sbuf.st_ex_size != 1000) {
5399 printf("ftruncate - stat size (%u) != 1000\n", (unsigned int)sbuf.st_ex_size);
5400 goto out;
5403 /* Test ftruncate - set file size back to zero. */
5404 status = cli_ftruncate(cli1, fnum1, 0);
5405 if (!NT_STATUS_IS_OK(status)) {
5406 printf("ftruncate failed (%s)\n", nt_errstr(status));
5407 goto out;
5410 status = cli_close(cli1, fnum1);
5411 if (!NT_STATUS_IS_OK(status)) {
5412 printf("close failed (%s)\n", nt_errstr(status));
5413 goto out;
5416 /* Now open the file again for read only. */
5417 status = cli_posix_open(cli1, fname, O_RDONLY, 0, &fnum1);
5418 if (!NT_STATUS_IS_OK(status)) {
5419 printf("POSIX open of %s failed (%s)\n", fname, nt_errstr(status));
5420 goto out;
5423 /* Now unlink while open. */
5424 status = cli_posix_unlink(cli1, fname);
5425 if (!NT_STATUS_IS_OK(status)) {
5426 printf("POSIX unlink of %s failed (%s)\n", fname, nt_errstr(status));
5427 goto out;
5430 status = cli_close(cli1, fnum1);
5431 if (!NT_STATUS_IS_OK(status)) {
5432 printf("close(2) failed (%s)\n", nt_errstr(status));
5433 goto out;
5436 /* Ensure the file has gone. */
5437 status = cli_posix_open(cli1, fname, O_RDONLY, 0, &fnum1);
5438 if (NT_STATUS_IS_OK(status)) {
5439 printf("POSIX open of %s succeeded, should have been deleted.\n", fname);
5440 goto out;
5443 /* Create again to test open with O_TRUNC. */
5444 status = cli_posix_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL, 0600, &fnum1);
5445 if (!NT_STATUS_IS_OK(status)) {
5446 printf("POSIX create of %s failed (%s)\n", fname, nt_errstr(status));
5447 goto out;
5450 /* Test ftruncate - set file size. */
5451 status = cli_ftruncate(cli1, fnum1, 1000);
5452 if (!NT_STATUS_IS_OK(status)) {
5453 printf("ftruncate failed (%s)\n", nt_errstr(status));
5454 goto out;
5457 /* Ensure st_size == 1000 */
5458 status = cli_posix_stat(cli1, fname, &sbuf);
5459 if (!NT_STATUS_IS_OK(status)) {
5460 printf("stat failed (%s)\n", nt_errstr(status));
5461 goto out;
5464 if (sbuf.st_ex_size != 1000) {
5465 printf("ftruncate - stat size (%u) != 1000\n", (unsigned int)sbuf.st_ex_size);
5466 goto out;
5469 status = cli_close(cli1, fnum1);
5470 if (!NT_STATUS_IS_OK(status)) {
5471 printf("close(2) failed (%s)\n", nt_errstr(status));
5472 goto out;
5475 /* Re-open with O_TRUNC. */
5476 status = cli_posix_open(cli1, fname, O_WRONLY|O_TRUNC, 0600, &fnum1);
5477 if (!NT_STATUS_IS_OK(status)) {
5478 printf("POSIX create of %s failed (%s)\n", fname, nt_errstr(status));
5479 goto out;
5482 /* Ensure st_size == 0 */
5483 status = cli_posix_stat(cli1, fname, &sbuf);
5484 if (!NT_STATUS_IS_OK(status)) {
5485 printf("stat failed (%s)\n", nt_errstr(status));
5486 goto out;
5489 if (sbuf.st_ex_size != 0) {
5490 printf("O_TRUNC - stat size (%u) != 0\n", (unsigned int)sbuf.st_ex_size);
5491 goto out;
5494 status = cli_close(cli1, fnum1);
5495 if (!NT_STATUS_IS_OK(status)) {
5496 printf("close failed (%s)\n", nt_errstr(status));
5497 goto out;
5500 status = cli_posix_unlink(cli1, fname);
5501 if (!NT_STATUS_IS_OK(status)) {
5502 printf("POSIX unlink of %s failed (%s)\n", fname, nt_errstr(status));
5503 goto out;
5506 status = cli_posix_open(cli1, dname, O_RDONLY, 0, &fnum1);
5507 if (!NT_STATUS_IS_OK(status)) {
5508 printf("POSIX open directory O_RDONLY of %s failed (%s)\n",
5509 dname, nt_errstr(status));
5510 goto out;
5513 cli_close(cli1, fnum1);
5515 /* What happens when we try and POSIX open a directory for write ? */
5516 status = cli_posix_open(cli1, dname, O_RDWR, 0, &fnum1);
5517 if (NT_STATUS_IS_OK(status)) {
5518 printf("POSIX open of directory %s succeeded, should have failed.\n", fname);
5519 goto out;
5520 } else {
5521 if (!check_both_error(__LINE__, status, ERRDOS, EISDIR,
5522 NT_STATUS_FILE_IS_A_DIRECTORY)) {
5523 goto out;
5527 /* Create the file. */
5528 status = cli_posix_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL,
5529 0600, &fnum1);
5530 if (!NT_STATUS_IS_OK(status)) {
5531 printf("POSIX create of %s failed (%s)\n", fname, nt_errstr(status));
5532 goto out;
5535 /* Write some data into it. */
5536 status = cli_writeall(cli1, fnum1, 0, (const uint8_t *)"TEST DATA\n", 0, 10,
5537 NULL);
5538 if (!NT_STATUS_IS_OK(status)) {
5539 printf("cli_write failed: %s\n", nt_errstr(status));
5540 goto out;
5543 cli_close(cli1, fnum1);
5545 /* Now create a hardlink. */
5546 status = cli_posix_hardlink(cli1, fname, hname);
5547 if (!NT_STATUS_IS_OK(status)) {
5548 printf("POSIX hardlink of %s failed (%s)\n", hname, nt_errstr(status));
5549 goto out;
5552 /* Now create a symlink. */
5553 status = cli_posix_symlink(cli1, fname, sname);
5554 if (!NT_STATUS_IS_OK(status)) {
5555 printf("POSIX symlink of %s failed (%s)\n", sname, nt_errstr(status));
5556 goto out;
5559 /* Open the hardlink for read. */
5560 status = cli_posix_open(cli1, hname, O_RDONLY, 0, &fnum1);
5561 if (!NT_STATUS_IS_OK(status)) {
5562 printf("POSIX open of %s failed (%s)\n", hname, nt_errstr(status));
5563 goto out;
5566 status = cli_read(cli1, fnum1, buf, 0, 10, &nread);
5567 if (!NT_STATUS_IS_OK(status)) {
5568 printf("POSIX read of %s failed (%s)\n", hname,
5569 nt_errstr(status));
5570 goto out;
5571 } else if (nread != 10) {
5572 printf("POSIX read of %s failed. Received %ld, expected %d\n",
5573 hname, (unsigned long)nread, 10);
5574 goto out;
5577 if (memcmp(buf, "TEST DATA\n", 10)) {
5578 printf("invalid data read from hardlink\n");
5579 goto out;
5582 /* Do a POSIX lock/unlock. */
5583 status = cli_posix_lock(cli1, fnum1, 0, 100, true, READ_LOCK);
5584 if (!NT_STATUS_IS_OK(status)) {
5585 printf("POSIX lock failed %s\n", nt_errstr(status));
5586 goto out;
5589 /* Punch a hole in the locked area. */
5590 status = cli_posix_unlock(cli1, fnum1, 10, 80);
5591 if (!NT_STATUS_IS_OK(status)) {
5592 printf("POSIX unlock failed %s\n", nt_errstr(status));
5593 goto out;
5596 cli_close(cli1, fnum1);
5598 /* Open the symlink for read - this should fail. A POSIX
5599 client should not be doing opens on a symlink. */
5600 status = cli_posix_open(cli1, sname, O_RDONLY, 0, &fnum1);
5601 if (NT_STATUS_IS_OK(status)) {
5602 printf("POSIX open of %s succeeded (should have failed)\n", sname);
5603 goto out;
5604 } else {
5605 if (!check_both_error(__LINE__, status, ERRDOS, ERRbadpath,
5606 NT_STATUS_OBJECT_PATH_NOT_FOUND)) {
5607 printf("POSIX open of %s should have failed "
5608 "with NT_STATUS_OBJECT_PATH_NOT_FOUND, "
5609 "failed with %s instead.\n",
5610 sname, nt_errstr(status));
5611 goto out;
5615 status = cli_posix_readlink(cli1, sname, namebuf, sizeof(namebuf));
5616 if (!NT_STATUS_IS_OK(status)) {
5617 printf("POSIX readlink on %s failed (%s)\n", sname, nt_errstr(status));
5618 goto out;
5621 if (strcmp(namebuf, fname) != 0) {
5622 printf("POSIX readlink on %s failed to match name %s (read %s)\n",
5623 sname, fname, namebuf);
5624 goto out;
5627 status = cli_posix_rmdir(cli1, dname);
5628 if (!NT_STATUS_IS_OK(status)) {
5629 printf("POSIX rmdir failed (%s)\n", nt_errstr(status));
5630 goto out;
5633 printf("Simple POSIX open test passed\n");
5634 correct = true;
5636 out:
5638 if (fnum1 != (uint16_t)-1) {
5639 cli_close(cli1, fnum1);
5640 fnum1 = (uint16_t)-1;
5643 cli_setatr(cli1, sname, 0, 0);
5644 cli_posix_unlink(cli1, sname);
5645 cli_setatr(cli1, hname, 0, 0);
5646 cli_posix_unlink(cli1, hname);
5647 cli_setatr(cli1, fname, 0, 0);
5648 cli_posix_unlink(cli1, fname);
5649 cli_setatr(cli1, dname, 0, 0);
5650 cli_posix_rmdir(cli1, dname);
5652 if (!torture_close_connection(cli1)) {
5653 correct = false;
5656 return correct;
5660 static uint32 open_attrs_table[] = {
5661 FILE_ATTRIBUTE_NORMAL,
5662 FILE_ATTRIBUTE_ARCHIVE,
5663 FILE_ATTRIBUTE_READONLY,
5664 FILE_ATTRIBUTE_HIDDEN,
5665 FILE_ATTRIBUTE_SYSTEM,
5667 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY,
5668 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN,
5669 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM,
5670 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN,
5671 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM,
5672 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM,
5674 FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN,
5675 FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM,
5676 FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM,
5677 FILE_ATTRIBUTE_HIDDEN,FILE_ATTRIBUTE_SYSTEM,
5680 struct trunc_open_results {
5681 unsigned int num;
5682 uint32 init_attr;
5683 uint32 trunc_attr;
5684 uint32 result_attr;
5687 static struct trunc_open_results attr_results[] = {
5688 { 0, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_ARCHIVE },
5689 { 1, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_ARCHIVE },
5690 { 2, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_READONLY, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY },
5691 { 16, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_ARCHIVE },
5692 { 17, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_ARCHIVE },
5693 { 18, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_READONLY, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY },
5694 { 51, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
5695 { 54, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
5696 { 56, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN },
5697 { 68, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
5698 { 71, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
5699 { 73, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM },
5700 { 99, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_HIDDEN,FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
5701 { 102, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
5702 { 104, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN },
5703 { 116, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
5704 { 119, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
5705 { 121, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM },
5706 { 170, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM|FILE_ATTRIBUTE_HIDDEN },
5707 { 173, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM },
5708 { 227, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
5709 { 230, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
5710 { 232, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN },
5711 { 244, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
5712 { 247, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
5713 { 249, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM }
5716 static bool run_openattrtest(int dummy)
5718 static struct cli_state *cli1;
5719 const char *fname = "\\openattr.file";
5720 uint16_t fnum1;
5721 bool correct = True;
5722 uint16 attr;
5723 unsigned int i, j, k, l;
5724 NTSTATUS status;
5726 printf("starting open attr test\n");
5728 if (!torture_open_connection(&cli1, 0)) {
5729 return False;
5732 cli_sockopt(cli1, sockops);
5734 for (k = 0, i = 0; i < sizeof(open_attrs_table)/sizeof(uint32); i++) {
5735 cli_setatr(cli1, fname, 0, 0);
5736 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5738 status = cli_ntcreate(cli1, fname, 0, FILE_WRITE_DATA,
5739 open_attrs_table[i], FILE_SHARE_NONE,
5740 FILE_OVERWRITE_IF, 0, 0, &fnum1);
5741 if (!NT_STATUS_IS_OK(status)) {
5742 printf("open %d (1) of %s failed (%s)\n", i, fname, nt_errstr(status));
5743 return False;
5746 status = cli_close(cli1, fnum1);
5747 if (!NT_STATUS_IS_OK(status)) {
5748 printf("close %d (1) of %s failed (%s)\n", i, fname, nt_errstr(status));
5749 return False;
5752 for (j = 0; j < sizeof(open_attrs_table)/sizeof(uint32); j++) {
5753 status = cli_ntcreate(cli1, fname, 0,
5754 FILE_READ_DATA|FILE_WRITE_DATA,
5755 open_attrs_table[j],
5756 FILE_SHARE_NONE, FILE_OVERWRITE,
5757 0, 0, &fnum1);
5758 if (!NT_STATUS_IS_OK(status)) {
5759 for (l = 0; l < sizeof(attr_results)/sizeof(struct trunc_open_results); l++) {
5760 if (attr_results[l].num == k) {
5761 printf("[%d] trunc open 0x%x -> 0x%x of %s failed - should have succeeded !(0x%x:%s)\n",
5762 k, open_attrs_table[i],
5763 open_attrs_table[j],
5764 fname, NT_STATUS_V(status), nt_errstr(status));
5765 correct = False;
5769 if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
5770 printf("[%d] trunc open 0x%x -> 0x%x failed with wrong error code %s\n",
5771 k, open_attrs_table[i], open_attrs_table[j],
5772 nt_errstr(status));
5773 correct = False;
5775 #if 0
5776 printf("[%d] trunc open 0x%x -> 0x%x failed\n", k, open_attrs_table[i], open_attrs_table[j]);
5777 #endif
5778 k++;
5779 continue;
5782 status = cli_close(cli1, fnum1);
5783 if (!NT_STATUS_IS_OK(status)) {
5784 printf("close %d (2) of %s failed (%s)\n", j, fname, nt_errstr(status));
5785 return False;
5788 status = cli_getatr(cli1, fname, &attr, NULL, NULL);
5789 if (!NT_STATUS_IS_OK(status)) {
5790 printf("getatr(2) failed (%s)\n", nt_errstr(status));
5791 return False;
5794 #if 0
5795 printf("[%d] getatr check [0x%x] trunc [0x%x] got attr 0x%x\n",
5796 k, open_attrs_table[i], open_attrs_table[j], attr );
5797 #endif
5799 for (l = 0; l < sizeof(attr_results)/sizeof(struct trunc_open_results); l++) {
5800 if (attr_results[l].num == k) {
5801 if (attr != attr_results[l].result_attr ||
5802 open_attrs_table[i] != attr_results[l].init_attr ||
5803 open_attrs_table[j] != attr_results[l].trunc_attr) {
5804 printf("getatr check failed. [0x%x] trunc [0x%x] got attr 0x%x, should be 0x%x\n",
5805 open_attrs_table[i],
5806 open_attrs_table[j],
5807 (unsigned int)attr,
5808 attr_results[l].result_attr);
5809 correct = False;
5811 break;
5814 k++;
5818 cli_setatr(cli1, fname, 0, 0);
5819 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5821 printf("open attr test %s.\n", correct ? "passed" : "failed");
5823 if (!torture_close_connection(cli1)) {
5824 correct = False;
5826 return correct;
5829 static NTSTATUS list_fn(const char *mnt, struct file_info *finfo,
5830 const char *name, void *state)
5832 int *matched = (int *)state;
5833 if (matched != NULL) {
5834 *matched += 1;
5836 return NT_STATUS_OK;
5840 test directory listing speed
5842 static bool run_dirtest(int dummy)
5844 int i;
5845 static struct cli_state *cli;
5846 uint16_t fnum;
5847 struct timeval core_start;
5848 bool correct = True;
5849 int matched;
5851 printf("starting directory test\n");
5853 if (!torture_open_connection(&cli, 0)) {
5854 return False;
5857 cli_sockopt(cli, sockops);
5859 srandom(0);
5860 for (i=0;i<torture_numops;i++) {
5861 fstring fname;
5862 slprintf(fname, sizeof(fname), "\\%x", (int)random());
5863 if (!NT_STATUS_IS_OK(cli_open(cli, fname, O_RDWR|O_CREAT, DENY_NONE, &fnum))) {
5864 fprintf(stderr,"Failed to open %s\n", fname);
5865 return False;
5867 cli_close(cli, fnum);
5870 core_start = timeval_current();
5872 matched = 0;
5873 cli_list(cli, "a*.*", 0, list_fn, &matched);
5874 printf("Matched %d\n", matched);
5876 matched = 0;
5877 cli_list(cli, "b*.*", 0, list_fn, &matched);
5878 printf("Matched %d\n", matched);
5880 matched = 0;
5881 cli_list(cli, "xyzabc", 0, list_fn, &matched);
5882 printf("Matched %d\n", matched);
5884 printf("dirtest core %g seconds\n", timeval_elapsed(&core_start));
5886 srandom(0);
5887 for (i=0;i<torture_numops;i++) {
5888 fstring fname;
5889 slprintf(fname, sizeof(fname), "\\%x", (int)random());
5890 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5893 if (!torture_close_connection(cli)) {
5894 correct = False;
5897 printf("finished dirtest\n");
5899 return correct;
5902 static NTSTATUS del_fn(const char *mnt, struct file_info *finfo, const char *mask,
5903 void *state)
5905 struct cli_state *pcli = (struct cli_state *)state;
5906 fstring fname;
5907 slprintf(fname, sizeof(fname), "\\LISTDIR\\%s", finfo->name);
5909 if (strcmp(finfo->name, ".") == 0 || strcmp(finfo->name, "..") == 0)
5910 return NT_STATUS_OK;
5912 if (finfo->mode & FILE_ATTRIBUTE_DIRECTORY) {
5913 if (!NT_STATUS_IS_OK(cli_rmdir(pcli, fname)))
5914 printf("del_fn: failed to rmdir %s\n,", fname );
5915 } else {
5916 if (!NT_STATUS_IS_OK(cli_unlink(pcli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN)))
5917 printf("del_fn: failed to unlink %s\n,", fname );
5919 return NT_STATUS_OK;
5924 sees what IOCTLs are supported
5926 bool torture_ioctl_test(int dummy)
5928 static struct cli_state *cli;
5929 uint16_t device, function;
5930 uint16_t fnum;
5931 const char *fname = "\\ioctl.dat";
5932 DATA_BLOB blob;
5933 NTSTATUS status;
5935 if (!torture_open_connection(&cli, 0)) {
5936 return False;
5939 printf("starting ioctl test\n");
5941 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5943 status = cli_open(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
5944 if (!NT_STATUS_IS_OK(status)) {
5945 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
5946 return False;
5949 status = cli_raw_ioctl(cli, fnum, 0x2d0000 | (0x0420<<2), &blob);
5950 printf("ioctl device info: %s\n", nt_errstr(status));
5952 status = cli_raw_ioctl(cli, fnum, IOCTL_QUERY_JOB_INFO, &blob);
5953 printf("ioctl job info: %s\n", nt_errstr(status));
5955 for (device=0;device<0x100;device++) {
5956 printf("ioctl test with device = 0x%x\n", device);
5957 for (function=0;function<0x100;function++) {
5958 uint32 code = (device<<16) | function;
5960 status = cli_raw_ioctl(cli, fnum, code, &blob);
5962 if (NT_STATUS_IS_OK(status)) {
5963 printf("ioctl 0x%x OK : %d bytes\n", (int)code,
5964 (int)blob.length);
5965 data_blob_free(&blob);
5970 if (!torture_close_connection(cli)) {
5971 return False;
5974 return True;
5979 tries varients of chkpath
5981 bool torture_chkpath_test(int dummy)
5983 static struct cli_state *cli;
5984 uint16_t fnum;
5985 bool ret;
5986 NTSTATUS status;
5988 if (!torture_open_connection(&cli, 0)) {
5989 return False;
5992 printf("starting chkpath test\n");
5994 /* cleanup from an old run */
5995 cli_rmdir(cli, "\\chkpath.dir\\dir2");
5996 cli_unlink(cli, "\\chkpath.dir\\*", FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5997 cli_rmdir(cli, "\\chkpath.dir");
5999 status = cli_mkdir(cli, "\\chkpath.dir");
6000 if (!NT_STATUS_IS_OK(status)) {
6001 printf("mkdir1 failed : %s\n", nt_errstr(status));
6002 return False;
6005 status = cli_mkdir(cli, "\\chkpath.dir\\dir2");
6006 if (!NT_STATUS_IS_OK(status)) {
6007 printf("mkdir2 failed : %s\n", nt_errstr(status));
6008 return False;
6011 status = cli_open(cli, "\\chkpath.dir\\foo.txt", O_RDWR|O_CREAT|O_EXCL,
6012 DENY_NONE, &fnum);
6013 if (!NT_STATUS_IS_OK(status)) {
6014 printf("open1 failed (%s)\n", nt_errstr(status));
6015 return False;
6017 cli_close(cli, fnum);
6019 status = cli_chkpath(cli, "\\chkpath.dir");
6020 if (!NT_STATUS_IS_OK(status)) {
6021 printf("chkpath1 failed: %s\n", nt_errstr(status));
6022 ret = False;
6025 status = cli_chkpath(cli, "\\chkpath.dir\\dir2");
6026 if (!NT_STATUS_IS_OK(status)) {
6027 printf("chkpath2 failed: %s\n", nt_errstr(status));
6028 ret = False;
6031 status = cli_chkpath(cli, "\\chkpath.dir\\foo.txt");
6032 if (!NT_STATUS_IS_OK(status)) {
6033 ret = check_error(__LINE__, status, ERRDOS, ERRbadpath,
6034 NT_STATUS_NOT_A_DIRECTORY);
6035 } else {
6036 printf("* chkpath on a file should fail\n");
6037 ret = False;
6040 status = cli_chkpath(cli, "\\chkpath.dir\\bar.txt");
6041 if (!NT_STATUS_IS_OK(status)) {
6042 ret = check_error(__LINE__, status, ERRDOS, ERRbadfile,
6043 NT_STATUS_OBJECT_NAME_NOT_FOUND);
6044 } else {
6045 printf("* chkpath on a non existant file should fail\n");
6046 ret = False;
6049 status = cli_chkpath(cli, "\\chkpath.dir\\dirxx\\bar.txt");
6050 if (!NT_STATUS_IS_OK(status)) {
6051 ret = check_error(__LINE__, status, ERRDOS, ERRbadpath,
6052 NT_STATUS_OBJECT_PATH_NOT_FOUND);
6053 } else {
6054 printf("* chkpath on a non existent component should fail\n");
6055 ret = False;
6058 cli_rmdir(cli, "\\chkpath.dir\\dir2");
6059 cli_unlink(cli, "\\chkpath.dir\\*", FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6060 cli_rmdir(cli, "\\chkpath.dir");
6062 if (!torture_close_connection(cli)) {
6063 return False;
6066 return ret;
6069 static bool run_eatest(int dummy)
6071 static struct cli_state *cli;
6072 const char *fname = "\\eatest.txt";
6073 bool correct = True;
6074 uint16_t fnum;
6075 int i;
6076 size_t num_eas;
6077 struct ea_struct *ea_list = NULL;
6078 TALLOC_CTX *mem_ctx = talloc_init("eatest");
6079 NTSTATUS status;
6081 printf("starting eatest\n");
6083 if (!torture_open_connection(&cli, 0)) {
6084 talloc_destroy(mem_ctx);
6085 return False;
6088 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6090 status = cli_ntcreate(cli, fname, 0,
6091 FIRST_DESIRED_ACCESS, FILE_ATTRIBUTE_ARCHIVE,
6092 FILE_SHARE_NONE, FILE_OVERWRITE_IF,
6093 0x4044, 0, &fnum);
6094 if (!NT_STATUS_IS_OK(status)) {
6095 printf("open failed - %s\n", nt_errstr(status));
6096 talloc_destroy(mem_ctx);
6097 return False;
6100 for (i = 0; i < 10; i++) {
6101 fstring ea_name, ea_val;
6103 slprintf(ea_name, sizeof(ea_name), "EA_%d", i);
6104 memset(ea_val, (char)i+1, i+1);
6105 status = cli_set_ea_fnum(cli, fnum, ea_name, ea_val, i+1);
6106 if (!NT_STATUS_IS_OK(status)) {
6107 printf("ea_set of name %s failed - %s\n", ea_name,
6108 nt_errstr(status));
6109 talloc_destroy(mem_ctx);
6110 return False;
6114 cli_close(cli, fnum);
6115 for (i = 0; i < 10; i++) {
6116 fstring ea_name, ea_val;
6118 slprintf(ea_name, sizeof(ea_name), "EA_%d", i+10);
6119 memset(ea_val, (char)i+1, i+1);
6120 status = cli_set_ea_path(cli, fname, ea_name, ea_val, i+1);
6121 if (!NT_STATUS_IS_OK(status)) {
6122 printf("ea_set of name %s failed - %s\n", ea_name,
6123 nt_errstr(status));
6124 talloc_destroy(mem_ctx);
6125 return False;
6129 status = cli_get_ea_list_path(cli, fname, mem_ctx, &num_eas, &ea_list);
6130 if (!NT_STATUS_IS_OK(status)) {
6131 printf("ea_get list failed - %s\n", nt_errstr(status));
6132 correct = False;
6135 printf("num_eas = %d\n", (int)num_eas);
6137 if (num_eas != 20) {
6138 printf("Should be 20 EA's stored... failing.\n");
6139 correct = False;
6142 for (i = 0; i < num_eas; i++) {
6143 printf("%d: ea_name = %s. Val = ", i, ea_list[i].name);
6144 dump_data(0, ea_list[i].value.data,
6145 ea_list[i].value.length);
6148 /* Setting EA's to zero length deletes them. Test this */
6149 printf("Now deleting all EA's - case indepenent....\n");
6151 #if 1
6152 cli_set_ea_path(cli, fname, "", "", 0);
6153 #else
6154 for (i = 0; i < 20; i++) {
6155 fstring ea_name;
6156 slprintf(ea_name, sizeof(ea_name), "ea_%d", i);
6157 status = cli_set_ea_path(cli, fname, ea_name, "", 0);
6158 if (!NT_STATUS_IS_OK(status)) {
6159 printf("ea_set of name %s failed - %s\n", ea_name,
6160 nt_errstr(status));
6161 talloc_destroy(mem_ctx);
6162 return False;
6165 #endif
6167 status = cli_get_ea_list_path(cli, fname, mem_ctx, &num_eas, &ea_list);
6168 if (!NT_STATUS_IS_OK(status)) {
6169 printf("ea_get list failed - %s\n", nt_errstr(status));
6170 correct = False;
6173 printf("num_eas = %d\n", (int)num_eas);
6174 for (i = 0; i < num_eas; i++) {
6175 printf("%d: ea_name = %s. Val = ", i, ea_list[i].name);
6176 dump_data(0, ea_list[i].value.data,
6177 ea_list[i].value.length);
6180 if (num_eas != 0) {
6181 printf("deleting EA's failed.\n");
6182 correct = False;
6185 /* Try and delete a non existant EA. */
6186 status = cli_set_ea_path(cli, fname, "foo", "", 0);
6187 if (!NT_STATUS_IS_OK(status)) {
6188 printf("deleting non-existant EA 'foo' should succeed. %s\n",
6189 nt_errstr(status));
6190 correct = False;
6193 talloc_destroy(mem_ctx);
6194 if (!torture_close_connection(cli)) {
6195 correct = False;
6198 return correct;
6201 static bool run_dirtest1(int dummy)
6203 int i;
6204 static struct cli_state *cli;
6205 uint16_t fnum;
6206 int num_seen;
6207 bool correct = True;
6209 printf("starting directory test\n");
6211 if (!torture_open_connection(&cli, 0)) {
6212 return False;
6215 cli_sockopt(cli, sockops);
6217 cli_list(cli, "\\LISTDIR\\*", 0, del_fn, cli);
6218 cli_list(cli, "\\LISTDIR\\*", FILE_ATTRIBUTE_DIRECTORY, del_fn, cli);
6219 cli_rmdir(cli, "\\LISTDIR");
6220 cli_mkdir(cli, "\\LISTDIR");
6222 /* Create 1000 files and 1000 directories. */
6223 for (i=0;i<1000;i++) {
6224 fstring fname;
6225 slprintf(fname, sizeof(fname), "\\LISTDIR\\f%d", i);
6226 if (!NT_STATUS_IS_OK(cli_ntcreate(cli, fname, 0, GENERIC_ALL_ACCESS, FILE_ATTRIBUTE_ARCHIVE,
6227 FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OVERWRITE_IF, 0, 0, &fnum))) {
6228 fprintf(stderr,"Failed to open %s\n", fname);
6229 return False;
6231 cli_close(cli, fnum);
6233 for (i=0;i<1000;i++) {
6234 fstring fname;
6235 slprintf(fname, sizeof(fname), "\\LISTDIR\\d%d", i);
6236 if (!NT_STATUS_IS_OK(cli_mkdir(cli, fname))) {
6237 fprintf(stderr,"Failed to open %s\n", fname);
6238 return False;
6242 /* Now ensure that doing an old list sees both files and directories. */
6243 num_seen = 0;
6244 cli_list_old(cli, "\\LISTDIR\\*", FILE_ATTRIBUTE_DIRECTORY, list_fn, &num_seen);
6245 printf("num_seen = %d\n", num_seen );
6246 /* We should see 100 files + 1000 directories + . and .. */
6247 if (num_seen != 2002)
6248 correct = False;
6250 /* Ensure if we have the "must have" bits we only see the
6251 * relevent entries.
6253 num_seen = 0;
6254 cli_list_old(cli, "\\LISTDIR\\*", (FILE_ATTRIBUTE_DIRECTORY<<8)|FILE_ATTRIBUTE_DIRECTORY, list_fn, &num_seen);
6255 printf("num_seen = %d\n", num_seen );
6256 if (num_seen != 1002)
6257 correct = False;
6259 num_seen = 0;
6260 cli_list_old(cli, "\\LISTDIR\\*", (FILE_ATTRIBUTE_ARCHIVE<<8)|FILE_ATTRIBUTE_DIRECTORY, list_fn, &num_seen);
6261 printf("num_seen = %d\n", num_seen );
6262 if (num_seen != 1000)
6263 correct = False;
6265 /* Delete everything. */
6266 cli_list(cli, "\\LISTDIR\\*", 0, del_fn, cli);
6267 cli_list(cli, "\\LISTDIR\\*", FILE_ATTRIBUTE_DIRECTORY, del_fn, cli);
6268 cli_rmdir(cli, "\\LISTDIR");
6270 #if 0
6271 printf("Matched %d\n", cli_list(cli, "a*.*", 0, list_fn, NULL));
6272 printf("Matched %d\n", cli_list(cli, "b*.*", 0, list_fn, NULL));
6273 printf("Matched %d\n", cli_list(cli, "xyzabc", 0, list_fn, NULL));
6274 #endif
6276 if (!torture_close_connection(cli)) {
6277 correct = False;
6280 printf("finished dirtest1\n");
6282 return correct;
6285 static bool run_error_map_extract(int dummy) {
6287 static struct cli_state *c_dos;
6288 static struct cli_state *c_nt;
6289 NTSTATUS status;
6291 uint32 error;
6293 uint32 errnum;
6294 uint8 errclass;
6296 NTSTATUS nt_status;
6298 fstring user;
6300 /* NT-Error connection */
6302 disable_spnego = true;
6303 if (!(c_nt = open_nbt_connection())) {
6304 disable_spnego = false;
6305 return False;
6307 disable_spnego = false;
6309 status = cli_negprot(c_nt, PROTOCOL_NT1);
6311 if (!NT_STATUS_IS_OK(status)) {
6312 printf("%s rejected the NT-error negprot (%s)\n", host,
6313 nt_errstr(status));
6314 cli_shutdown(c_nt);
6315 return False;
6318 status = cli_session_setup(c_nt, "", "", 0, "", 0, workgroup);
6319 if (!NT_STATUS_IS_OK(status)) {
6320 printf("%s rejected the NT-error initial session setup (%s)\n",host, nt_errstr(status));
6321 return False;
6324 /* DOS-Error connection */
6326 disable_spnego = true;
6327 force_dos_errors = true;
6328 if (!(c_dos = open_nbt_connection())) {
6329 disable_spnego = false;
6330 force_dos_errors = false;
6331 return False;
6333 disable_spnego = false;
6334 force_dos_errors = false;
6336 status = cli_negprot(c_dos, PROTOCOL_NT1);
6337 if (!NT_STATUS_IS_OK(status)) {
6338 printf("%s rejected the DOS-error negprot (%s)\n", host,
6339 nt_errstr(status));
6340 cli_shutdown(c_dos);
6341 return False;
6344 status = cli_session_setup(c_dos, "", "", 0, "", 0, workgroup);
6345 if (!NT_STATUS_IS_OK(status)) {
6346 printf("%s rejected the DOS-error initial session setup (%s)\n",
6347 host, nt_errstr(status));
6348 return False;
6351 c_nt->map_dos_errors = false;
6352 c_dos->map_dos_errors = false;
6354 for (error=(0xc0000000 | 0x1); error < (0xc0000000| 0xFFF); error++) {
6355 fstr_sprintf(user, "%X", error);
6357 status = cli_session_setup(c_nt, user,
6358 password, strlen(password),
6359 password, strlen(password),
6360 workgroup);
6361 if (NT_STATUS_IS_OK(status)) {
6362 printf("/** Session setup succeeded. This shouldn't happen...*/\n");
6365 /* Case #1: 32-bit NT errors */
6366 if (!NT_STATUS_IS_DOS(status)) {
6367 nt_status = status;
6368 } else {
6369 printf("/** Dos error on NT connection! (%s) */\n",
6370 nt_errstr(status));
6371 nt_status = NT_STATUS(0xc0000000);
6374 status = cli_session_setup(c_dos, user,
6375 password, strlen(password),
6376 password, strlen(password),
6377 workgroup);
6378 if (NT_STATUS_IS_OK(status)) {
6379 printf("/** Session setup succeeded. This shouldn't happen...*/\n");
6382 /* Case #1: 32-bit NT errors */
6383 if (NT_STATUS_IS_DOS(status)) {
6384 printf("/** NT error on DOS connection! (%s) */\n",
6385 nt_errstr(status));
6386 errnum = errclass = 0;
6387 } else {
6388 errclass = NT_STATUS_DOS_CLASS(status);
6389 errnum = NT_STATUS_DOS_CODE(status);
6392 if (NT_STATUS_V(nt_status) != error) {
6393 printf("/*\t{ This NT error code was 'sqashed'\n\t from %s to %s \n\t during the session setup }\n*/\n",
6394 get_nt_error_c_code(talloc_tos(), NT_STATUS(error)),
6395 get_nt_error_c_code(talloc_tos(), nt_status));
6398 printf("\t{%s,\t%s,\t%s},\n",
6399 smb_dos_err_class(errclass),
6400 smb_dos_err_name(errclass, errnum),
6401 get_nt_error_c_code(talloc_tos(), NT_STATUS(error)));
6403 return True;
6406 static bool run_sesssetup_bench(int dummy)
6408 static struct cli_state *c;
6409 const char *fname = "\\file.dat";
6410 uint16_t fnum;
6411 NTSTATUS status;
6412 int i;
6414 if (!torture_open_connection(&c, 0)) {
6415 return false;
6418 status = cli_ntcreate(c, fname, 0, GENERIC_ALL_ACCESS|DELETE_ACCESS,
6419 FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
6420 FILE_DELETE_ON_CLOSE, 0, &fnum);
6421 if (!NT_STATUS_IS_OK(status)) {
6422 d_printf("open %s failed: %s\n", fname, nt_errstr(status));
6423 return false;
6426 for (i=0; i<torture_numops; i++) {
6427 status = cli_session_setup(
6428 c, username,
6429 password, strlen(password),
6430 password, strlen(password),
6431 workgroup);
6432 if (!NT_STATUS_IS_OK(status)) {
6433 d_printf("(%s) cli_session_setup failed: %s\n",
6434 __location__, nt_errstr(status));
6435 return false;
6438 d_printf("\r%d ", (int)cli_state_get_uid(c));
6440 status = cli_ulogoff(c);
6441 if (!NT_STATUS_IS_OK(status)) {
6442 d_printf("(%s) cli_ulogoff failed: %s\n",
6443 __location__, nt_errstr(status));
6444 return false;
6448 return true;
6451 static bool subst_test(const char *str, const char *user, const char *domain,
6452 uid_t uid, gid_t gid, const char *expected)
6454 char *subst;
6455 bool result = true;
6457 subst = talloc_sub_specified(talloc_tos(), str, user, domain, uid, gid);
6459 if (strcmp(subst, expected) != 0) {
6460 printf("sub_specified(%s, %s, %s, %d, %d) returned [%s], expected "
6461 "[%s]\n", str, user, domain, (int)uid, (int)gid, subst,
6462 expected);
6463 result = false;
6466 TALLOC_FREE(subst);
6467 return result;
6470 static void chain1_open_completion(struct tevent_req *req)
6472 uint16_t fnum;
6473 NTSTATUS status;
6474 status = cli_open_recv(req, &fnum);
6475 TALLOC_FREE(req);
6477 d_printf("cli_open_recv returned %s: %d\n",
6478 nt_errstr(status),
6479 NT_STATUS_IS_OK(status) ? fnum : -1);
6482 static void chain1_write_completion(struct tevent_req *req)
6484 size_t written;
6485 NTSTATUS status;
6486 status = cli_write_andx_recv(req, &written);
6487 TALLOC_FREE(req);
6489 d_printf("cli_write_andx_recv returned %s: %d\n",
6490 nt_errstr(status),
6491 NT_STATUS_IS_OK(status) ? (int)written : -1);
6494 static void chain1_close_completion(struct tevent_req *req)
6496 NTSTATUS status;
6497 bool *done = (bool *)tevent_req_callback_data_void(req);
6499 status = cli_close_recv(req);
6500 *done = true;
6502 TALLOC_FREE(req);
6504 d_printf("cli_close returned %s\n", nt_errstr(status));
6507 static bool run_chain1(int dummy)
6509 struct cli_state *cli1;
6510 struct event_context *evt = event_context_init(NULL);
6511 struct tevent_req *reqs[3], *smbreqs[3];
6512 bool done = false;
6513 const char *str = "foobar";
6514 NTSTATUS status;
6516 printf("starting chain1 test\n");
6517 if (!torture_open_connection(&cli1, 0)) {
6518 return False;
6521 cli_sockopt(cli1, sockops);
6523 reqs[0] = cli_open_create(talloc_tos(), evt, cli1, "\\test",
6524 O_CREAT|O_RDWR, 0, &smbreqs[0]);
6525 if (reqs[0] == NULL) return false;
6526 tevent_req_set_callback(reqs[0], chain1_open_completion, NULL);
6529 reqs[1] = cli_write_andx_create(talloc_tos(), evt, cli1, 0, 0,
6530 (const uint8_t *)str, 0, strlen(str)+1,
6531 smbreqs, 1, &smbreqs[1]);
6532 if (reqs[1] == NULL) return false;
6533 tevent_req_set_callback(reqs[1], chain1_write_completion, NULL);
6535 reqs[2] = cli_close_create(talloc_tos(), evt, cli1, 0, &smbreqs[2]);
6536 if (reqs[2] == NULL) return false;
6537 tevent_req_set_callback(reqs[2], chain1_close_completion, &done);
6539 status = cli_smb_chain_send(smbreqs, ARRAY_SIZE(smbreqs));
6540 if (!NT_STATUS_IS_OK(status)) {
6541 return false;
6544 while (!done) {
6545 tevent_loop_once(evt);
6548 torture_close_connection(cli1);
6549 return True;
6552 static void chain2_sesssetup_completion(struct tevent_req *req)
6554 NTSTATUS status;
6555 status = cli_session_setup_guest_recv(req);
6556 d_printf("sesssetup returned %s\n", nt_errstr(status));
6559 static void chain2_tcon_completion(struct tevent_req *req)
6561 bool *done = (bool *)tevent_req_callback_data_void(req);
6562 NTSTATUS status;
6563 status = cli_tcon_andx_recv(req);
6564 d_printf("tcon_and_x returned %s\n", nt_errstr(status));
6565 *done = true;
6568 static bool run_chain2(int dummy)
6570 struct cli_state *cli1;
6571 struct event_context *evt = event_context_init(NULL);
6572 struct tevent_req *reqs[2], *smbreqs[2];
6573 bool done = false;
6574 NTSTATUS status;
6576 printf("starting chain2 test\n");
6577 status = cli_start_connection(&cli1, lp_netbios_name(), host, NULL,
6578 port_to_use, SMB_SIGNING_DEFAULT, 0);
6579 if (!NT_STATUS_IS_OK(status)) {
6580 return False;
6583 cli_sockopt(cli1, sockops);
6585 reqs[0] = cli_session_setup_guest_create(talloc_tos(), evt, cli1,
6586 &smbreqs[0]);
6587 if (reqs[0] == NULL) return false;
6588 tevent_req_set_callback(reqs[0], chain2_sesssetup_completion, NULL);
6590 reqs[1] = cli_tcon_andx_create(talloc_tos(), evt, cli1, "IPC$",
6591 "?????", NULL, 0, &smbreqs[1]);
6592 if (reqs[1] == NULL) return false;
6593 tevent_req_set_callback(reqs[1], chain2_tcon_completion, &done);
6595 status = cli_smb_chain_send(smbreqs, ARRAY_SIZE(smbreqs));
6596 if (!NT_STATUS_IS_OK(status)) {
6597 return false;
6600 while (!done) {
6601 tevent_loop_once(evt);
6604 torture_close_connection(cli1);
6605 return True;
6609 struct torture_createdel_state {
6610 struct tevent_context *ev;
6611 struct cli_state *cli;
6614 static void torture_createdel_created(struct tevent_req *subreq);
6615 static void torture_createdel_closed(struct tevent_req *subreq);
6617 static struct tevent_req *torture_createdel_send(TALLOC_CTX *mem_ctx,
6618 struct tevent_context *ev,
6619 struct cli_state *cli,
6620 const char *name)
6622 struct tevent_req *req, *subreq;
6623 struct torture_createdel_state *state;
6625 req = tevent_req_create(mem_ctx, &state,
6626 struct torture_createdel_state);
6627 if (req == NULL) {
6628 return NULL;
6630 state->ev = ev;
6631 state->cli = cli;
6633 subreq = cli_ntcreate_send(
6634 state, ev, cli, name, 0,
6635 FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
6636 FILE_ATTRIBUTE_NORMAL,
6637 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6638 FILE_OPEN_IF, FILE_DELETE_ON_CLOSE, 0);
6640 if (tevent_req_nomem(subreq, req)) {
6641 return tevent_req_post(req, ev);
6643 tevent_req_set_callback(subreq, torture_createdel_created, req);
6644 return req;
6647 static void torture_createdel_created(struct tevent_req *subreq)
6649 struct tevent_req *req = tevent_req_callback_data(
6650 subreq, struct tevent_req);
6651 struct torture_createdel_state *state = tevent_req_data(
6652 req, struct torture_createdel_state);
6653 NTSTATUS status;
6654 uint16_t fnum;
6656 status = cli_ntcreate_recv(subreq, &fnum);
6657 TALLOC_FREE(subreq);
6658 if (!NT_STATUS_IS_OK(status)) {
6659 DEBUG(10, ("cli_ntcreate_recv returned %s\n",
6660 nt_errstr(status)));
6661 tevent_req_nterror(req, status);
6662 return;
6665 subreq = cli_close_send(state, state->ev, state->cli, fnum);
6666 if (tevent_req_nomem(subreq, req)) {
6667 return;
6669 tevent_req_set_callback(subreq, torture_createdel_closed, req);
6672 static void torture_createdel_closed(struct tevent_req *subreq)
6674 struct tevent_req *req = tevent_req_callback_data(
6675 subreq, struct tevent_req);
6676 NTSTATUS status;
6678 status = cli_close_recv(subreq);
6679 if (!NT_STATUS_IS_OK(status)) {
6680 DEBUG(10, ("cli_close_recv returned %s\n", nt_errstr(status)));
6681 tevent_req_nterror(req, status);
6682 return;
6684 tevent_req_done(req);
6687 static NTSTATUS torture_createdel_recv(struct tevent_req *req)
6689 return tevent_req_simple_recv_ntstatus(req);
6692 struct torture_createdels_state {
6693 struct tevent_context *ev;
6694 struct cli_state *cli;
6695 const char *base_name;
6696 int sent;
6697 int received;
6698 int num_files;
6699 struct tevent_req **reqs;
6702 static void torture_createdels_done(struct tevent_req *subreq);
6704 static struct tevent_req *torture_createdels_send(TALLOC_CTX *mem_ctx,
6705 struct tevent_context *ev,
6706 struct cli_state *cli,
6707 const char *base_name,
6708 int num_parallel,
6709 int num_files)
6711 struct tevent_req *req;
6712 struct torture_createdels_state *state;
6713 int i;
6715 req = tevent_req_create(mem_ctx, &state,
6716 struct torture_createdels_state);
6717 if (req == NULL) {
6718 return NULL;
6720 state->ev = ev;
6721 state->cli = cli;
6722 state->base_name = talloc_strdup(state, base_name);
6723 if (tevent_req_nomem(state->base_name, req)) {
6724 return tevent_req_post(req, ev);
6726 state->num_files = MAX(num_parallel, num_files);
6727 state->sent = 0;
6728 state->received = 0;
6730 state->reqs = talloc_array(state, struct tevent_req *, num_parallel);
6731 if (tevent_req_nomem(state->reqs, req)) {
6732 return tevent_req_post(req, ev);
6735 for (i=0; i<num_parallel; i++) {
6736 char *name;
6738 name = talloc_asprintf(state, "%s%8.8d", state->base_name,
6739 state->sent);
6740 if (tevent_req_nomem(name, req)) {
6741 return tevent_req_post(req, ev);
6743 state->reqs[i] = torture_createdel_send(
6744 state->reqs, state->ev, state->cli, name);
6745 if (tevent_req_nomem(state->reqs[i], req)) {
6746 return tevent_req_post(req, ev);
6748 name = talloc_move(state->reqs[i], &name);
6749 tevent_req_set_callback(state->reqs[i],
6750 torture_createdels_done, req);
6751 state->sent += 1;
6753 return req;
6756 static void torture_createdels_done(struct tevent_req *subreq)
6758 struct tevent_req *req = tevent_req_callback_data(
6759 subreq, struct tevent_req);
6760 struct torture_createdels_state *state = tevent_req_data(
6761 req, struct torture_createdels_state);
6762 size_t num_parallel = talloc_array_length(state->reqs);
6763 NTSTATUS status;
6764 char *name;
6765 int i;
6767 status = torture_createdel_recv(subreq);
6768 if (!NT_STATUS_IS_OK(status)){
6769 DEBUG(10, ("torture_createdel_recv returned %s\n",
6770 nt_errstr(status)));
6771 TALLOC_FREE(subreq);
6772 tevent_req_nterror(req, status);
6773 return;
6776 for (i=0; i<num_parallel; i++) {
6777 if (subreq == state->reqs[i]) {
6778 break;
6781 if (i == num_parallel) {
6782 DEBUG(10, ("received something we did not send\n"));
6783 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
6784 return;
6786 TALLOC_FREE(state->reqs[i]);
6788 if (state->sent >= state->num_files) {
6789 tevent_req_done(req);
6790 return;
6793 name = talloc_asprintf(state, "%s%8.8d", state->base_name,
6794 state->sent);
6795 if (tevent_req_nomem(name, req)) {
6796 return;
6798 state->reqs[i] = torture_createdel_send(state->reqs, state->ev,
6799 state->cli, name);
6800 if (tevent_req_nomem(state->reqs[i], req)) {
6801 return;
6803 name = talloc_move(state->reqs[i], &name);
6804 tevent_req_set_callback(state->reqs[i], torture_createdels_done, req);
6805 state->sent += 1;
6808 static NTSTATUS torture_createdels_recv(struct tevent_req *req)
6810 return tevent_req_simple_recv_ntstatus(req);
6813 struct swallow_notify_state {
6814 struct tevent_context *ev;
6815 struct cli_state *cli;
6816 uint16_t fnum;
6817 uint32_t completion_filter;
6818 bool recursive;
6819 bool (*fn)(uint32_t action, const char *name, void *priv);
6820 void *priv;
6823 static void swallow_notify_done(struct tevent_req *subreq);
6825 static struct tevent_req *swallow_notify_send(TALLOC_CTX *mem_ctx,
6826 struct tevent_context *ev,
6827 struct cli_state *cli,
6828 uint16_t fnum,
6829 uint32_t completion_filter,
6830 bool recursive,
6831 bool (*fn)(uint32_t action,
6832 const char *name,
6833 void *priv),
6834 void *priv)
6836 struct tevent_req *req, *subreq;
6837 struct swallow_notify_state *state;
6839 req = tevent_req_create(mem_ctx, &state,
6840 struct swallow_notify_state);
6841 if (req == NULL) {
6842 return NULL;
6844 state->ev = ev;
6845 state->cli = cli;
6846 state->fnum = fnum;
6847 state->completion_filter = completion_filter;
6848 state->recursive = recursive;
6849 state->fn = fn;
6850 state->priv = priv;
6852 subreq = cli_notify_send(state, state->ev, state->cli, state->fnum,
6853 0xffff, state->completion_filter,
6854 state->recursive);
6855 if (tevent_req_nomem(subreq, req)) {
6856 return tevent_req_post(req, ev);
6858 tevent_req_set_callback(subreq, swallow_notify_done, req);
6859 return req;
6862 static void swallow_notify_done(struct tevent_req *subreq)
6864 struct tevent_req *req = tevent_req_callback_data(
6865 subreq, struct tevent_req);
6866 struct swallow_notify_state *state = tevent_req_data(
6867 req, struct swallow_notify_state);
6868 NTSTATUS status;
6869 uint32_t i, num_changes;
6870 struct notify_change *changes;
6872 status = cli_notify_recv(subreq, state, &num_changes, &changes);
6873 TALLOC_FREE(subreq);
6874 if (!NT_STATUS_IS_OK(status)) {
6875 DEBUG(10, ("cli_notify_recv returned %s\n",
6876 nt_errstr(status)));
6877 tevent_req_nterror(req, status);
6878 return;
6881 for (i=0; i<num_changes; i++) {
6882 state->fn(changes[i].action, changes[i].name, state->priv);
6884 TALLOC_FREE(changes);
6886 subreq = cli_notify_send(state, state->ev, state->cli, state->fnum,
6887 0xffff, state->completion_filter,
6888 state->recursive);
6889 if (tevent_req_nomem(subreq, req)) {
6890 return;
6892 tevent_req_set_callback(subreq, swallow_notify_done, req);
6895 static bool print_notifies(uint32_t action, const char *name, void *priv)
6897 if (DEBUGLEVEL > 5) {
6898 d_printf("%d %s\n", (int)action, name);
6900 return true;
6903 static void notify_bench_done(struct tevent_req *req)
6905 int *num_finished = (int *)tevent_req_callback_data_void(req);
6906 *num_finished += 1;
6909 static bool run_notify_bench(int dummy)
6911 const char *dname = "\\notify-bench";
6912 struct tevent_context *ev;
6913 NTSTATUS status;
6914 uint16_t dnum;
6915 struct tevent_req *req1;
6916 struct tevent_req *req2 = NULL;
6917 int i, num_unc_names;
6918 int num_finished = 0;
6920 printf("starting notify-bench test\n");
6922 if (use_multishare_conn) {
6923 char **unc_list;
6924 unc_list = file_lines_load(multishare_conn_fname,
6925 &num_unc_names, 0, NULL);
6926 if (!unc_list || num_unc_names <= 0) {
6927 d_printf("Failed to load unc names list from '%s'\n",
6928 multishare_conn_fname);
6929 return false;
6931 TALLOC_FREE(unc_list);
6932 } else {
6933 num_unc_names = 1;
6936 ev = tevent_context_init(talloc_tos());
6937 if (ev == NULL) {
6938 d_printf("tevent_context_init failed\n");
6939 return false;
6942 for (i=0; i<num_unc_names; i++) {
6943 struct cli_state *cli;
6944 char *base_fname;
6946 base_fname = talloc_asprintf(talloc_tos(), "%s\\file%3.3d.",
6947 dname, i);
6948 if (base_fname == NULL) {
6949 return false;
6952 if (!torture_open_connection(&cli, i)) {
6953 return false;
6956 status = cli_ntcreate(cli, dname, 0,
6957 MAXIMUM_ALLOWED_ACCESS,
6958 0, FILE_SHARE_READ|FILE_SHARE_WRITE|
6959 FILE_SHARE_DELETE,
6960 FILE_OPEN_IF, FILE_DIRECTORY_FILE, 0,
6961 &dnum);
6963 if (!NT_STATUS_IS_OK(status)) {
6964 d_printf("Could not create %s: %s\n", dname,
6965 nt_errstr(status));
6966 return false;
6969 req1 = swallow_notify_send(talloc_tos(), ev, cli, dnum,
6970 FILE_NOTIFY_CHANGE_FILE_NAME |
6971 FILE_NOTIFY_CHANGE_DIR_NAME |
6972 FILE_NOTIFY_CHANGE_ATTRIBUTES |
6973 FILE_NOTIFY_CHANGE_LAST_WRITE,
6974 false, print_notifies, NULL);
6975 if (req1 == NULL) {
6976 d_printf("Could not create notify request\n");
6977 return false;
6980 req2 = torture_createdels_send(talloc_tos(), ev, cli,
6981 base_fname, 10, torture_numops);
6982 if (req2 == NULL) {
6983 d_printf("Could not create createdels request\n");
6984 return false;
6986 TALLOC_FREE(base_fname);
6988 tevent_req_set_callback(req2, notify_bench_done,
6989 &num_finished);
6992 while (num_finished < num_unc_names) {
6993 int ret;
6994 ret = tevent_loop_once(ev);
6995 if (ret != 0) {
6996 d_printf("tevent_loop_once failed\n");
6997 return false;
7001 if (!tevent_req_poll(req2, ev)) {
7002 d_printf("tevent_req_poll failed\n");
7005 status = torture_createdels_recv(req2);
7006 d_printf("torture_createdels_recv returned %s\n", nt_errstr(status));
7008 return true;
7011 static bool run_mangle1(int dummy)
7013 struct cli_state *cli;
7014 const char *fname = "this_is_a_long_fname_to_be_mangled.txt";
7015 uint16_t fnum;
7016 fstring alt_name;
7017 NTSTATUS status;
7018 time_t change_time, access_time, write_time;
7019 SMB_OFF_T size;
7020 uint16_t mode;
7022 printf("starting mangle1 test\n");
7023 if (!torture_open_connection(&cli, 0)) {
7024 return False;
7027 cli_sockopt(cli, sockops);
7029 status = cli_ntcreate(cli, fname, 0, GENERIC_ALL_ACCESS|DELETE_ACCESS,
7030 FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
7031 0, 0, &fnum);
7032 if (!NT_STATUS_IS_OK(status)) {
7033 d_printf("open %s failed: %s\n", fname, nt_errstr(status));
7034 return false;
7036 cli_close(cli, fnum);
7038 status = cli_qpathinfo_alt_name(cli, fname, alt_name);
7039 if (!NT_STATUS_IS_OK(status)) {
7040 d_printf("cli_qpathinfo_alt_name failed: %s\n",
7041 nt_errstr(status));
7042 return false;
7044 d_printf("alt_name: %s\n", alt_name);
7046 status = cli_open(cli, alt_name, O_RDONLY, DENY_NONE, &fnum);
7047 if (!NT_STATUS_IS_OK(status)) {
7048 d_printf("cli_open(%s) failed: %s\n", alt_name,
7049 nt_errstr(status));
7050 return false;
7052 cli_close(cli, fnum);
7054 status = cli_qpathinfo1(cli, alt_name, &change_time, &access_time,
7055 &write_time, &size, &mode);
7056 if (!NT_STATUS_IS_OK(status)) {
7057 d_printf("cli_qpathinfo1(%s) failed: %s\n", alt_name,
7058 nt_errstr(status));
7059 return false;
7062 return true;
7065 static size_t null_source(uint8_t *buf, size_t n, void *priv)
7067 size_t *to_pull = (size_t *)priv;
7068 size_t thistime = *to_pull;
7070 thistime = MIN(thistime, n);
7071 if (thistime == 0) {
7072 return 0;
7075 memset(buf, 0, thistime);
7076 *to_pull -= thistime;
7077 return thistime;
7080 static bool run_windows_write(int dummy)
7082 struct cli_state *cli1;
7083 uint16_t fnum;
7084 int i;
7085 bool ret = false;
7086 const char *fname = "\\writetest.txt";
7087 struct timeval start_time;
7088 double seconds;
7089 double kbytes;
7090 NTSTATUS status;
7092 printf("starting windows_write test\n");
7093 if (!torture_open_connection(&cli1, 0)) {
7094 return False;
7097 status = cli_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
7098 if (!NT_STATUS_IS_OK(status)) {
7099 printf("open failed (%s)\n", nt_errstr(status));
7100 return False;
7103 cli_sockopt(cli1, sockops);
7105 start_time = timeval_current();
7107 for (i=0; i<torture_numops; i++) {
7108 uint8_t c = 0;
7109 off_t start = i * torture_blocksize;
7110 size_t to_pull = torture_blocksize - 1;
7112 status = cli_writeall(cli1, fnum, 0, &c,
7113 start + torture_blocksize - 1, 1, NULL);
7114 if (!NT_STATUS_IS_OK(status)) {
7115 printf("cli_write failed: %s\n", nt_errstr(status));
7116 goto fail;
7119 status = cli_push(cli1, fnum, 0, i * torture_blocksize, torture_blocksize,
7120 null_source, &to_pull);
7121 if (!NT_STATUS_IS_OK(status)) {
7122 printf("cli_push returned: %s\n", nt_errstr(status));
7123 goto fail;
7127 seconds = timeval_elapsed(&start_time);
7128 kbytes = (double)torture_blocksize * torture_numops;
7129 kbytes /= 1024;
7131 printf("Wrote %d kbytes in %.2f seconds: %d kb/sec\n", (int)kbytes,
7132 (double)seconds, (int)(kbytes/seconds));
7134 ret = true;
7135 fail:
7136 cli_close(cli1, fnum);
7137 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7138 torture_close_connection(cli1);
7139 return ret;
7142 static bool run_cli_echo(int dummy)
7144 struct cli_state *cli;
7145 NTSTATUS status;
7147 printf("starting cli_echo test\n");
7148 if (!torture_open_connection(&cli, 0)) {
7149 return false;
7151 cli_sockopt(cli, sockops);
7153 status = cli_echo(cli, 5, data_blob_const("hello", 5));
7155 d_printf("cli_echo returned %s\n", nt_errstr(status));
7157 torture_close_connection(cli);
7158 return NT_STATUS_IS_OK(status);
7161 static bool run_uid_regression_test(int dummy)
7163 static struct cli_state *cli;
7164 int16_t old_vuid;
7165 int16_t old_cnum;
7166 bool correct = True;
7167 NTSTATUS status;
7169 printf("starting uid regression test\n");
7171 if (!torture_open_connection(&cli, 0)) {
7172 return False;
7175 cli_sockopt(cli, sockops);
7177 /* Ok - now save then logoff our current user. */
7178 old_vuid = cli_state_get_uid(cli);
7180 status = cli_ulogoff(cli);
7181 if (!NT_STATUS_IS_OK(status)) {
7182 d_printf("(%s) cli_ulogoff failed: %s\n",
7183 __location__, nt_errstr(status));
7184 correct = false;
7185 goto out;
7188 cli_state_set_uid(cli, old_vuid);
7190 /* Try an operation. */
7191 status = cli_mkdir(cli, "\\uid_reg_test");
7192 if (NT_STATUS_IS_OK(status)) {
7193 d_printf("(%s) cli_mkdir succeeded\n",
7194 __location__);
7195 correct = false;
7196 goto out;
7197 } else {
7198 /* Should be bad uid. */
7199 if (!check_error(__LINE__, status, ERRSRV, ERRbaduid,
7200 NT_STATUS_USER_SESSION_DELETED)) {
7201 correct = false;
7202 goto out;
7206 old_cnum = cli_state_get_tid(cli);
7208 /* Now try a SMBtdis with the invald vuid set to zero. */
7209 cli_state_set_uid(cli, 0);
7211 /* This should succeed. */
7212 status = cli_tdis(cli);
7214 if (NT_STATUS_IS_OK(status)) {
7215 d_printf("First tdis with invalid vuid should succeed.\n");
7216 } else {
7217 d_printf("First tdis failed (%s)\n", nt_errstr(status));
7218 correct = false;
7219 goto out;
7222 cli_state_set_uid(cli, old_vuid);
7223 cli_state_set_tid(cli, old_cnum);
7225 /* This should fail. */
7226 status = cli_tdis(cli);
7227 if (NT_STATUS_IS_OK(status)) {
7228 d_printf("Second tdis with invalid vuid should fail - succeeded instead !.\n");
7229 correct = false;
7230 goto out;
7231 } else {
7232 /* Should be bad tid. */
7233 if (!check_error(__LINE__, status, ERRSRV, ERRinvnid,
7234 NT_STATUS_NETWORK_NAME_DELETED)) {
7235 correct = false;
7236 goto out;
7240 cli_rmdir(cli, "\\uid_reg_test");
7242 out:
7244 cli_shutdown(cli);
7245 return correct;
7249 static const char *illegal_chars = "*\\/?<>|\":";
7250 static char force_shortname_chars[] = " +,.[];=\177";
7252 static NTSTATUS shortname_del_fn(const char *mnt, struct file_info *finfo,
7253 const char *mask, void *state)
7255 struct cli_state *pcli = (struct cli_state *)state;
7256 fstring fname;
7257 NTSTATUS status = NT_STATUS_OK;
7259 slprintf(fname, sizeof(fname), "\\shortname\\%s", finfo->name);
7261 if (strcmp(finfo->name, ".") == 0 || strcmp(finfo->name, "..") == 0)
7262 return NT_STATUS_OK;
7264 if (finfo->mode & FILE_ATTRIBUTE_DIRECTORY) {
7265 status = cli_rmdir(pcli, fname);
7266 if (!NT_STATUS_IS_OK(status)) {
7267 printf("del_fn: failed to rmdir %s\n,", fname );
7269 } else {
7270 status = cli_unlink(pcli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7271 if (!NT_STATUS_IS_OK(status)) {
7272 printf("del_fn: failed to unlink %s\n,", fname );
7275 return status;
7278 struct sn_state {
7279 int matched;
7280 int i;
7281 bool val;
7284 static NTSTATUS shortname_list_fn(const char *mnt, struct file_info *finfo,
7285 const char *name, void *state)
7287 struct sn_state *s = (struct sn_state *)state;
7288 int i = s->i;
7290 #if 0
7291 printf("shortname list: i = %d, name = |%s|, shortname = |%s|\n",
7292 i, finfo->name, finfo->short_name);
7293 #endif
7295 if (strchr(force_shortname_chars, i)) {
7296 if (!finfo->short_name) {
7297 /* Shortname not created when it should be. */
7298 d_printf("(%s) ERROR: Shortname was not created for file %s containing %d\n",
7299 __location__, finfo->name, i);
7300 s->val = true;
7302 } else if (finfo->short_name){
7303 /* Shortname created when it should not be. */
7304 d_printf("(%s) ERROR: Shortname %s was created for file %s\n",
7305 __location__, finfo->short_name, finfo->name);
7306 s->val = true;
7308 s->matched += 1;
7309 return NT_STATUS_OK;
7312 static bool run_shortname_test(int dummy)
7314 static struct cli_state *cli;
7315 bool correct = True;
7316 int i;
7317 struct sn_state s;
7318 char fname[20];
7319 NTSTATUS status;
7321 printf("starting shortname test\n");
7323 if (!torture_open_connection(&cli, 0)) {
7324 return False;
7327 cli_sockopt(cli, sockops);
7329 cli_list(cli, "\\shortname\\*", 0, shortname_del_fn, cli);
7330 cli_list(cli, "\\shortname\\*", FILE_ATTRIBUTE_DIRECTORY, shortname_del_fn, cli);
7331 cli_rmdir(cli, "\\shortname");
7333 status = cli_mkdir(cli, "\\shortname");
7334 if (!NT_STATUS_IS_OK(status)) {
7335 d_printf("(%s) cli_mkdir of \\shortname failed: %s\n",
7336 __location__, nt_errstr(status));
7337 correct = false;
7338 goto out;
7341 strlcpy(fname, "\\shortname\\", sizeof(fname));
7342 strlcat(fname, "test .txt", sizeof(fname));
7344 s.val = false;
7346 for (i = 32; i < 128; i++) {
7347 uint16_t fnum = (uint16_t)-1;
7349 s.i = i;
7351 if (strchr(illegal_chars, i)) {
7352 continue;
7354 fname[15] = i;
7356 status = cli_ntcreate(cli, fname, 0, GENERIC_ALL_ACCESS, FILE_ATTRIBUTE_NORMAL,
7357 FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OVERWRITE_IF, 0, 0, &fnum);
7358 if (!NT_STATUS_IS_OK(status)) {
7359 d_printf("(%s) cli_nt_create of %s failed: %s\n",
7360 __location__, fname, nt_errstr(status));
7361 correct = false;
7362 goto out;
7364 cli_close(cli, fnum);
7366 s.matched = 0;
7367 status = cli_list(cli, "\\shortname\\test*.*", 0,
7368 shortname_list_fn, &s);
7369 if (s.matched != 1) {
7370 d_printf("(%s) failed to list %s: %s\n",
7371 __location__, fname, nt_errstr(status));
7372 correct = false;
7373 goto out;
7376 status = cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7377 if (!NT_STATUS_IS_OK(status)) {
7378 d_printf("(%s) failed to delete %s: %s\n",
7379 __location__, fname, nt_errstr(status));
7380 correct = false;
7381 goto out;
7384 if (s.val) {
7385 correct = false;
7386 goto out;
7390 out:
7392 cli_list(cli, "\\shortname\\*", 0, shortname_del_fn, cli);
7393 cli_list(cli, "\\shortname\\*", FILE_ATTRIBUTE_DIRECTORY, shortname_del_fn, cli);
7394 cli_rmdir(cli, "\\shortname");
7395 torture_close_connection(cli);
7396 return correct;
7399 static void pagedsearch_cb(struct tevent_req *req)
7401 int rc;
7402 struct tldap_message *msg;
7403 char *dn;
7405 rc = tldap_search_paged_recv(req, talloc_tos(), &msg);
7406 if (rc != TLDAP_SUCCESS) {
7407 d_printf("tldap_search_paged_recv failed: %s\n",
7408 tldap_err2string(rc));
7409 return;
7411 if (tldap_msg_type(msg) != TLDAP_RES_SEARCH_ENTRY) {
7412 TALLOC_FREE(msg);
7413 return;
7415 if (!tldap_entry_dn(msg, &dn)) {
7416 d_printf("tldap_entry_dn failed\n");
7417 return;
7419 d_printf("%s\n", dn);
7420 TALLOC_FREE(msg);
7423 static bool run_tldap(int dummy)
7425 struct tldap_context *ld;
7426 int fd, rc;
7427 NTSTATUS status;
7428 struct sockaddr_storage addr;
7429 struct tevent_context *ev;
7430 struct tevent_req *req;
7431 char *basedn;
7432 const char *filter;
7434 if (!resolve_name(host, &addr, 0, false)) {
7435 d_printf("could not find host %s\n", host);
7436 return false;
7438 status = open_socket_out(&addr, 389, 9999, &fd);
7439 if (!NT_STATUS_IS_OK(status)) {
7440 d_printf("open_socket_out failed: %s\n", nt_errstr(status));
7441 return false;
7444 ld = tldap_context_create(talloc_tos(), fd);
7445 if (ld == NULL) {
7446 close(fd);
7447 d_printf("tldap_context_create failed\n");
7448 return false;
7451 rc = tldap_fetch_rootdse(ld);
7452 if (rc != TLDAP_SUCCESS) {
7453 d_printf("tldap_fetch_rootdse failed: %s\n",
7454 tldap_errstr(talloc_tos(), ld, rc));
7455 return false;
7458 basedn = tldap_talloc_single_attribute(
7459 tldap_rootdse(ld), "defaultNamingContext", talloc_tos());
7460 if (basedn == NULL) {
7461 d_printf("no defaultNamingContext\n");
7462 return false;
7464 d_printf("defaultNamingContext: %s\n", basedn);
7466 ev = tevent_context_init(talloc_tos());
7467 if (ev == NULL) {
7468 d_printf("tevent_context_init failed\n");
7469 return false;
7472 req = tldap_search_paged_send(talloc_tos(), ev, ld, basedn,
7473 TLDAP_SCOPE_SUB, "(objectclass=*)",
7474 NULL, 0, 0,
7475 NULL, 0, NULL, 0, 0, 0, 0, 5);
7476 if (req == NULL) {
7477 d_printf("tldap_search_paged_send failed\n");
7478 return false;
7480 tevent_req_set_callback(req, pagedsearch_cb, NULL);
7482 tevent_req_poll(req, ev);
7484 TALLOC_FREE(req);
7486 /* test search filters against rootDSE */
7487 filter = "(&(|(name=samba)(nextRid<=10000000)(usnChanged>=10)(samba~=ambas)(!(name=s*m*a)))"
7488 "(|(name:=samba)(name:dn:2.5.13.5:=samba)(:dn:2.5.13.5:=samba)(!(name=*samba))))";
7490 rc = tldap_search(ld, "", TLDAP_SCOPE_BASE, filter,
7491 NULL, 0, 0, NULL, 0, NULL, 0, 0, 0, 0,
7492 talloc_tos(), NULL, NULL);
7493 if (rc != TLDAP_SUCCESS) {
7494 d_printf("tldap_search with complex filter failed: %s\n",
7495 tldap_errstr(talloc_tos(), ld, rc));
7496 return false;
7499 TALLOC_FREE(ld);
7500 return true;
7503 /* Torture test to ensure no regression of :
7504 https://bugzilla.samba.org/show_bug.cgi?id=7084
7507 static bool run_dir_createtime(int dummy)
7509 struct cli_state *cli;
7510 const char *dname = "\\testdir";
7511 const char *fname = "\\testdir\\testfile";
7512 NTSTATUS status;
7513 struct timespec create_time;
7514 struct timespec create_time1;
7515 uint16_t fnum;
7516 bool ret = false;
7518 if (!torture_open_connection(&cli, 0)) {
7519 return false;
7522 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7523 cli_rmdir(cli, dname);
7525 status = cli_mkdir(cli, dname);
7526 if (!NT_STATUS_IS_OK(status)) {
7527 printf("mkdir failed: %s\n", nt_errstr(status));
7528 goto out;
7531 status = cli_qpathinfo2(cli, dname, &create_time, NULL, NULL, NULL,
7532 NULL, NULL, NULL);
7533 if (!NT_STATUS_IS_OK(status)) {
7534 printf("cli_qpathinfo2 returned %s\n",
7535 nt_errstr(status));
7536 goto out;
7539 /* Sleep 3 seconds, then create a file. */
7540 sleep(3);
7542 status = cli_open(cli, fname, O_RDWR | O_CREAT | O_EXCL,
7543 DENY_NONE, &fnum);
7544 if (!NT_STATUS_IS_OK(status)) {
7545 printf("cli_open failed: %s\n", nt_errstr(status));
7546 goto out;
7549 status = cli_qpathinfo2(cli, dname, &create_time1, NULL, NULL, NULL,
7550 NULL, NULL, NULL);
7551 if (!NT_STATUS_IS_OK(status)) {
7552 printf("cli_qpathinfo2 (2) returned %s\n",
7553 nt_errstr(status));
7554 goto out;
7557 if (timespec_compare(&create_time1, &create_time)) {
7558 printf("run_dir_createtime: create time was updated (error)\n");
7559 } else {
7560 printf("run_dir_createtime: create time was not updated (correct)\n");
7561 ret = true;
7564 out:
7566 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7567 cli_rmdir(cli, dname);
7568 if (!torture_close_connection(cli)) {
7569 ret = false;
7571 return ret;
7575 static bool run_streamerror(int dummy)
7577 struct cli_state *cli;
7578 const char *dname = "\\testdir";
7579 const char *streamname =
7580 "testdir:{4c8cc155-6c1e-11d1-8e41-00c04fb9386d}:$DATA";
7581 NTSTATUS status;
7582 time_t change_time, access_time, write_time;
7583 SMB_OFF_T size;
7584 uint16_t mode, fnum;
7585 bool ret = true;
7587 if (!torture_open_connection(&cli, 0)) {
7588 return false;
7591 cli_unlink(cli, "\\testdir\\*", FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7592 cli_rmdir(cli, dname);
7594 status = cli_mkdir(cli, dname);
7595 if (!NT_STATUS_IS_OK(status)) {
7596 printf("mkdir failed: %s\n", nt_errstr(status));
7597 return false;
7600 status = cli_qpathinfo1(cli, streamname, &change_time, &access_time,
7601 &write_time, &size, &mode);
7602 if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
7603 printf("pathinfo returned %s, expected "
7604 "NT_STATUS_OBJECT_NAME_NOT_FOUND\n",
7605 nt_errstr(status));
7606 ret = false;
7609 status = cli_ntcreate(cli, streamname, 0x16,
7610 FILE_READ_DATA|FILE_READ_EA|
7611 FILE_READ_ATTRIBUTES|READ_CONTROL_ACCESS,
7612 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ,
7613 FILE_OPEN, 0, 0, &fnum);
7615 if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
7616 printf("ntcreate returned %s, expected "
7617 "NT_STATUS_OBJECT_NAME_NOT_FOUND\n",
7618 nt_errstr(status));
7619 ret = false;
7623 cli_rmdir(cli, dname);
7624 return ret;
7627 static bool run_local_substitute(int dummy)
7629 bool ok = true;
7631 ok &= subst_test("%U", "bla", "", -1, -1, "bla");
7632 ok &= subst_test("%u%U", "bla", "", -1, -1, "blabla");
7633 ok &= subst_test("%g", "", "", -1, -1, "NO_GROUP");
7634 ok &= subst_test("%G", "", "", -1, -1, "NO_GROUP");
7635 ok &= subst_test("%g", "", "", -1, 0, gidtoname(0));
7636 ok &= subst_test("%G", "", "", -1, 0, gidtoname(0));
7637 ok &= subst_test("%D%u", "u", "dom", -1, 0, "domu");
7638 ok &= subst_test("%i %I", "", "", -1, -1, "0.0.0.0 0.0.0.0");
7640 /* Different captialization rules in sub_basic... */
7642 ok &= (strcmp(talloc_sub_basic(talloc_tos(), "BLA", "dom", "%U%D"),
7643 "blaDOM") == 0);
7645 return ok;
7648 static bool run_local_base64(int dummy)
7650 int i;
7651 bool ret = true;
7653 for (i=1; i<2000; i++) {
7654 DATA_BLOB blob1, blob2;
7655 char *b64;
7657 blob1.data = talloc_array(talloc_tos(), uint8_t, i);
7658 blob1.length = i;
7659 generate_random_buffer(blob1.data, blob1.length);
7661 b64 = base64_encode_data_blob(talloc_tos(), blob1);
7662 if (b64 == NULL) {
7663 d_fprintf(stderr, "base64_encode_data_blob failed "
7664 "for %d bytes\n", i);
7665 ret = false;
7667 blob2 = base64_decode_data_blob(b64);
7668 TALLOC_FREE(b64);
7670 if (data_blob_cmp(&blob1, &blob2)) {
7671 d_fprintf(stderr, "data_blob_cmp failed for %d "
7672 "bytes\n", i);
7673 ret = false;
7675 TALLOC_FREE(blob1.data);
7676 data_blob_free(&blob2);
7678 return ret;
7681 static bool run_local_gencache(int dummy)
7683 char *val;
7684 time_t tm;
7685 DATA_BLOB blob;
7687 if (!gencache_set("foo", "bar", time(NULL) + 1000)) {
7688 d_printf("%s: gencache_set() failed\n", __location__);
7689 return False;
7692 if (!gencache_get("foo", NULL, NULL)) {
7693 d_printf("%s: gencache_get() failed\n", __location__);
7694 return False;
7697 if (!gencache_get("foo", &val, &tm)) {
7698 d_printf("%s: gencache_get() failed\n", __location__);
7699 return False;
7702 if (strcmp(val, "bar") != 0) {
7703 d_printf("%s: gencache_get() returned %s, expected %s\n",
7704 __location__, val, "bar");
7705 SAFE_FREE(val);
7706 return False;
7709 SAFE_FREE(val);
7711 if (!gencache_del("foo")) {
7712 d_printf("%s: gencache_del() failed\n", __location__);
7713 return False;
7715 if (gencache_del("foo")) {
7716 d_printf("%s: second gencache_del() succeeded\n",
7717 __location__);
7718 return False;
7721 if (gencache_get("foo", &val, &tm)) {
7722 d_printf("%s: gencache_get() on deleted entry "
7723 "succeeded\n", __location__);
7724 return False;
7727 blob = data_blob_string_const_null("bar");
7728 tm = time(NULL) + 60;
7730 if (!gencache_set_data_blob("foo", &blob, tm)) {
7731 d_printf("%s: gencache_set_data_blob() failed\n", __location__);
7732 return False;
7735 if (!gencache_get_data_blob("foo", &blob, NULL, NULL)) {
7736 d_printf("%s: gencache_get_data_blob() failed\n", __location__);
7737 return False;
7740 if (strcmp((const char *)blob.data, "bar") != 0) {
7741 d_printf("%s: gencache_get_data_blob() returned %s, expected %s\n",
7742 __location__, (const char *)blob.data, "bar");
7743 data_blob_free(&blob);
7744 return False;
7747 data_blob_free(&blob);
7749 if (!gencache_del("foo")) {
7750 d_printf("%s: gencache_del() failed\n", __location__);
7751 return False;
7753 if (gencache_del("foo")) {
7754 d_printf("%s: second gencache_del() succeeded\n",
7755 __location__);
7756 return False;
7759 if (gencache_get_data_blob("foo", &blob, NULL, NULL)) {
7760 d_printf("%s: gencache_get_data_blob() on deleted entry "
7761 "succeeded\n", __location__);
7762 return False;
7765 return True;
7768 static bool rbt_testval(struct db_context *db, const char *key,
7769 const char *value)
7771 struct db_record *rec;
7772 TDB_DATA data = string_tdb_data(value);
7773 bool ret = false;
7774 NTSTATUS status;
7775 TDB_DATA dbvalue;
7777 rec = dbwrap_fetch_locked(db, db, string_tdb_data(key));
7778 if (rec == NULL) {
7779 d_fprintf(stderr, "fetch_locked failed\n");
7780 goto done;
7782 status = dbwrap_record_store(rec, data, 0);
7783 if (!NT_STATUS_IS_OK(status)) {
7784 d_fprintf(stderr, "store failed: %s\n", nt_errstr(status));
7785 goto done;
7787 TALLOC_FREE(rec);
7789 rec = dbwrap_fetch_locked(db, db, string_tdb_data(key));
7790 if (rec == NULL) {
7791 d_fprintf(stderr, "second fetch_locked failed\n");
7792 goto done;
7795 dbvalue = dbwrap_record_get_value(rec);
7796 if ((dbvalue.dsize != data.dsize)
7797 || (memcmp(dbvalue.dptr, data.dptr, data.dsize) != 0)) {
7798 d_fprintf(stderr, "Got wrong data back\n");
7799 goto done;
7802 ret = true;
7803 done:
7804 TALLOC_FREE(rec);
7805 return ret;
7808 static bool run_local_rbtree(int dummy)
7810 struct db_context *db;
7811 bool ret = false;
7812 int i;
7814 db = db_open_rbt(NULL);
7816 if (db == NULL) {
7817 d_fprintf(stderr, "db_open_rbt failed\n");
7818 return false;
7821 for (i=0; i<1000; i++) {
7822 char *key, *value;
7824 if (asprintf(&key, "key%ld", random()) == -1) {
7825 goto done;
7827 if (asprintf(&value, "value%ld", random()) == -1) {
7828 SAFE_FREE(key);
7829 goto done;
7832 if (!rbt_testval(db, key, value)) {
7833 SAFE_FREE(key);
7834 SAFE_FREE(value);
7835 goto done;
7838 SAFE_FREE(value);
7839 if (asprintf(&value, "value%ld", random()) == -1) {
7840 SAFE_FREE(key);
7841 goto done;
7844 if (!rbt_testval(db, key, value)) {
7845 SAFE_FREE(key);
7846 SAFE_FREE(value);
7847 goto done;
7850 SAFE_FREE(key);
7851 SAFE_FREE(value);
7854 ret = true;
7856 done:
7857 TALLOC_FREE(db);
7858 return ret;
7863 local test for character set functions
7865 This is a very simple test for the functionality in convert_string_error()
7867 static bool run_local_convert_string(int dummy)
7869 TALLOC_CTX *tmp_ctx = talloc_new(NULL);
7870 const char *test_strings[2] = { "March", "M\303\244rz" };
7871 char dst[7];
7872 int i;
7874 for (i=0; i<2; i++) {
7875 const char *str = test_strings[i];
7876 int len = strlen(str);
7877 size_t converted_size;
7878 bool ret;
7880 memset(dst, 'X', sizeof(dst));
7882 /* first try with real source length */
7883 ret = convert_string_error(CH_UNIX, CH_UTF8,
7884 str, len,
7885 dst, sizeof(dst),
7886 &converted_size);
7887 if (ret != true) {
7888 d_fprintf(stderr, "Failed to convert '%s' to CH_DISPLAY\n", str);
7889 goto failed;
7892 if (converted_size != len) {
7893 d_fprintf(stderr, "Converted size of '%s' should be %d - got %d\n",
7894 str, len, (int)converted_size);
7895 goto failed;
7898 if (strncmp(str, dst, converted_size) != 0) {
7899 d_fprintf(stderr, "Expected '%s' to match '%s'\n", str, dst);
7900 goto failed;
7903 if (strlen(str) != converted_size) {
7904 d_fprintf(stderr, "Expected '%s' length %d - got %d\n", str,
7905 (int)strlen(str), (int)converted_size);
7906 goto failed;
7909 if (dst[converted_size] != 'X') {
7910 d_fprintf(stderr, "Expected no termination of '%s'\n", dst);
7911 goto failed;
7914 /* now with srclen==-1, this causes the nul to be
7915 * converted too */
7916 ret = convert_string_error(CH_UNIX, CH_UTF8,
7917 str, -1,
7918 dst, sizeof(dst),
7919 &converted_size);
7920 if (ret != true) {
7921 d_fprintf(stderr, "Failed to convert '%s' to CH_DISPLAY\n", str);
7922 goto failed;
7925 if (converted_size != len+1) {
7926 d_fprintf(stderr, "Converted size of '%s' should be %d - got %d\n",
7927 str, len, (int)converted_size);
7928 goto failed;
7931 if (strncmp(str, dst, converted_size) != 0) {
7932 d_fprintf(stderr, "Expected '%s' to match '%s'\n", str, dst);
7933 goto failed;
7936 if (len+1 != converted_size) {
7937 d_fprintf(stderr, "Expected '%s' length %d - got %d\n", str,
7938 len+1, (int)converted_size);
7939 goto failed;
7942 if (dst[converted_size] != 'X') {
7943 d_fprintf(stderr, "Expected no termination of '%s'\n", dst);
7944 goto failed;
7950 TALLOC_FREE(tmp_ctx);
7951 return true;
7952 failed:
7953 TALLOC_FREE(tmp_ctx);
7954 return false;
7958 struct talloc_dict_test {
7959 int content;
7962 static int talloc_dict_traverse_fn(DATA_BLOB key, void *data, void *priv)
7964 int *count = (int *)priv;
7965 *count += 1;
7966 return 0;
7969 static bool run_local_talloc_dict(int dummy)
7971 struct talloc_dict *dict;
7972 struct talloc_dict_test *t;
7973 int key, count;
7975 dict = talloc_dict_init(talloc_tos());
7976 if (dict == NULL) {
7977 return false;
7980 t = talloc(talloc_tos(), struct talloc_dict_test);
7981 if (t == NULL) {
7982 return false;
7985 key = 1;
7986 t->content = 1;
7987 if (!talloc_dict_set(dict, data_blob_const(&key, sizeof(key)), t)) {
7988 return false;
7991 count = 0;
7992 if (talloc_dict_traverse(dict, talloc_dict_traverse_fn, &count) != 0) {
7993 return false;
7996 if (count != 1) {
7997 return false;
8000 TALLOC_FREE(dict);
8002 return true;
8005 static bool run_local_string_to_sid(int dummy) {
8006 struct dom_sid sid;
8008 if (string_to_sid(&sid, "S--1-5-32-545")) {
8009 printf("allowing S--1-5-32-545\n");
8010 return false;
8012 if (string_to_sid(&sid, "S-1-5-32-+545")) {
8013 printf("allowing S-1-5-32-+545\n");
8014 return false;
8016 if (string_to_sid(&sid, "S-1-2-3-4-5-6-7-8-9-0-1-2-3-4-5-6-7-8-9-0")) {
8017 printf("allowing S-1-2-3-4-5-6-7-8-9-0-1-2-3-4-5-6-7-8-9-0\n");
8018 return false;
8020 if (string_to_sid(&sid, "S-1-5-32-545-abc")) {
8021 printf("allowing S-1-5-32-545-abc\n");
8022 return false;
8024 if (!string_to_sid(&sid, "S-1-5-32-545")) {
8025 printf("could not parse S-1-5-32-545\n");
8026 return false;
8028 if (!dom_sid_equal(&sid, &global_sid_Builtin_Users)) {
8029 printf("mis-parsed S-1-5-32-545 as %s\n",
8030 sid_string_tos(&sid));
8031 return false;
8033 return true;
8036 static bool run_local_binary_to_sid(int dummy) {
8037 struct dom_sid *sid = talloc(NULL, struct dom_sid);
8038 static const char good_binary_sid[] = {
8039 0x1, /* revision number */
8040 15, /* num auths */
8041 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, /* id_auth */
8042 0x1, 0x1, 0x1, 0x1, /* auth[0] */
8043 0x1, 0x1, 0x1, 0x1, /* auth[1] */
8044 0x1, 0x1, 0x1, 0x1, /* auth[2] */
8045 0x1, 0x1, 0x1, 0x1, /* auth[3] */
8046 0x1, 0x1, 0x1, 0x1, /* auth[4] */
8047 0x1, 0x1, 0x1, 0x1, /* auth[5] */
8048 0x1, 0x1, 0x1, 0x1, /* auth[6] */
8049 0x1, 0x1, 0x1, 0x1, /* auth[7] */
8050 0x1, 0x1, 0x1, 0x1, /* auth[8] */
8051 0x1, 0x1, 0x1, 0x1, /* auth[9] */
8052 0x1, 0x1, 0x1, 0x1, /* auth[10] */
8053 0x1, 0x1, 0x1, 0x1, /* auth[11] */
8054 0x1, 0x1, 0x1, 0x1, /* auth[12] */
8055 0x1, 0x1, 0x1, 0x1, /* auth[13] */
8056 0x1, 0x1, 0x1, 0x1, /* auth[14] */
8059 static const char long_binary_sid[] = {
8060 0x1, /* revision number */
8061 15, /* num auths */
8062 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, /* id_auth */
8063 0x1, 0x1, 0x1, 0x1, /* auth[0] */
8064 0x1, 0x1, 0x1, 0x1, /* auth[1] */
8065 0x1, 0x1, 0x1, 0x1, /* auth[2] */
8066 0x1, 0x1, 0x1, 0x1, /* auth[3] */
8067 0x1, 0x1, 0x1, 0x1, /* auth[4] */
8068 0x1, 0x1, 0x1, 0x1, /* auth[5] */
8069 0x1, 0x1, 0x1, 0x1, /* auth[6] */
8070 0x1, 0x1, 0x1, 0x1, /* auth[7] */
8071 0x1, 0x1, 0x1, 0x1, /* auth[8] */
8072 0x1, 0x1, 0x1, 0x1, /* auth[9] */
8073 0x1, 0x1, 0x1, 0x1, /* auth[10] */
8074 0x1, 0x1, 0x1, 0x1, /* auth[11] */
8075 0x1, 0x1, 0x1, 0x1, /* auth[12] */
8076 0x1, 0x1, 0x1, 0x1, /* auth[13] */
8077 0x1, 0x1, 0x1, 0x1, /* auth[14] */
8078 0x1, 0x1, 0x1, 0x1, /* auth[15] */
8079 0x1, 0x1, 0x1, 0x1, /* auth[16] */
8080 0x1, 0x1, 0x1, 0x1, /* auth[17] */
8083 static const char long_binary_sid2[] = {
8084 0x1, /* revision number */
8085 32, /* num auths */
8086 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, /* id_auth */
8087 0x1, 0x1, 0x1, 0x1, /* auth[0] */
8088 0x1, 0x1, 0x1, 0x1, /* auth[1] */
8089 0x1, 0x1, 0x1, 0x1, /* auth[2] */
8090 0x1, 0x1, 0x1, 0x1, /* auth[3] */
8091 0x1, 0x1, 0x1, 0x1, /* auth[4] */
8092 0x1, 0x1, 0x1, 0x1, /* auth[5] */
8093 0x1, 0x1, 0x1, 0x1, /* auth[6] */
8094 0x1, 0x1, 0x1, 0x1, /* auth[7] */
8095 0x1, 0x1, 0x1, 0x1, /* auth[8] */
8096 0x1, 0x1, 0x1, 0x1, /* auth[9] */
8097 0x1, 0x1, 0x1, 0x1, /* auth[10] */
8098 0x1, 0x1, 0x1, 0x1, /* auth[11] */
8099 0x1, 0x1, 0x1, 0x1, /* auth[12] */
8100 0x1, 0x1, 0x1, 0x1, /* auth[13] */
8101 0x1, 0x1, 0x1, 0x1, /* auth[14] */
8102 0x1, 0x1, 0x1, 0x1, /* auth[15] */
8103 0x1, 0x1, 0x1, 0x1, /* auth[16] */
8104 0x1, 0x1, 0x1, 0x1, /* auth[17] */
8105 0x1, 0x1, 0x1, 0x1, /* auth[18] */
8106 0x1, 0x1, 0x1, 0x1, /* auth[19] */
8107 0x1, 0x1, 0x1, 0x1, /* auth[20] */
8108 0x1, 0x1, 0x1, 0x1, /* auth[21] */
8109 0x1, 0x1, 0x1, 0x1, /* auth[22] */
8110 0x1, 0x1, 0x1, 0x1, /* auth[23] */
8111 0x1, 0x1, 0x1, 0x1, /* auth[24] */
8112 0x1, 0x1, 0x1, 0x1, /* auth[25] */
8113 0x1, 0x1, 0x1, 0x1, /* auth[26] */
8114 0x1, 0x1, 0x1, 0x1, /* auth[27] */
8115 0x1, 0x1, 0x1, 0x1, /* auth[28] */
8116 0x1, 0x1, 0x1, 0x1, /* auth[29] */
8117 0x1, 0x1, 0x1, 0x1, /* auth[30] */
8118 0x1, 0x1, 0x1, 0x1, /* auth[31] */
8121 if (!sid_parse(good_binary_sid, sizeof(good_binary_sid), sid)) {
8122 return false;
8124 if (sid_parse(long_binary_sid2, sizeof(long_binary_sid2), sid)) {
8125 return false;
8127 if (sid_parse(long_binary_sid, sizeof(long_binary_sid), sid)) {
8128 return false;
8130 return true;
8133 /* Split a path name into filename and stream name components. Canonicalise
8134 * such that an implicit $DATA token is always explicit.
8136 * The "specification" of this function can be found in the
8137 * run_local_stream_name() function in torture.c, I've tried those
8138 * combinations against a W2k3 server.
8141 static NTSTATUS split_ntfs_stream_name(TALLOC_CTX *mem_ctx, const char *fname,
8142 char **pbase, char **pstream)
8144 char *base = NULL;
8145 char *stream = NULL;
8146 char *sname; /* stream name */
8147 const char *stype; /* stream type */
8149 DEBUG(10, ("split_ntfs_stream_name called for [%s]\n", fname));
8151 sname = strchr_m(fname, ':');
8153 if (lp_posix_pathnames() || (sname == NULL)) {
8154 if (pbase != NULL) {
8155 base = talloc_strdup(mem_ctx, fname);
8156 NT_STATUS_HAVE_NO_MEMORY(base);
8158 goto done;
8161 if (pbase != NULL) {
8162 base = talloc_strndup(mem_ctx, fname, PTR_DIFF(sname, fname));
8163 NT_STATUS_HAVE_NO_MEMORY(base);
8166 sname += 1;
8168 stype = strchr_m(sname, ':');
8170 if (stype == NULL) {
8171 sname = talloc_strdup(mem_ctx, sname);
8172 stype = "$DATA";
8174 else {
8175 if (strcasecmp_m(stype, ":$DATA") != 0) {
8177 * If there is an explicit stream type, so far we only
8178 * allow $DATA. Is there anything else allowed? -- vl
8180 DEBUG(10, ("[%s] is an invalid stream type\n", stype));
8181 TALLOC_FREE(base);
8182 return NT_STATUS_OBJECT_NAME_INVALID;
8184 sname = talloc_strndup(mem_ctx, sname, PTR_DIFF(stype, sname));
8185 stype += 1;
8188 if (sname == NULL) {
8189 TALLOC_FREE(base);
8190 return NT_STATUS_NO_MEMORY;
8193 if (sname[0] == '\0') {
8195 * no stream name, so no stream
8197 goto done;
8200 if (pstream != NULL) {
8201 stream = talloc_asprintf(mem_ctx, "%s:%s", sname, stype);
8202 if (stream == NULL) {
8203 TALLOC_FREE(sname);
8204 TALLOC_FREE(base);
8205 return NT_STATUS_NO_MEMORY;
8208 * upper-case the type field
8210 strupper_m(strchr_m(stream, ':')+1);
8213 done:
8214 if (pbase != NULL) {
8215 *pbase = base;
8217 if (pstream != NULL) {
8218 *pstream = stream;
8220 return NT_STATUS_OK;
8223 static bool test_stream_name(const char *fname, const char *expected_base,
8224 const char *expected_stream,
8225 NTSTATUS expected_status)
8227 NTSTATUS status;
8228 char *base = NULL;
8229 char *stream = NULL;
8231 status = split_ntfs_stream_name(talloc_tos(), fname, &base, &stream);
8232 if (!NT_STATUS_EQUAL(status, expected_status)) {
8233 goto error;
8236 if (!NT_STATUS_IS_OK(status)) {
8237 return true;
8240 if (base == NULL) goto error;
8242 if (strcmp(expected_base, base) != 0) goto error;
8244 if ((expected_stream != NULL) && (stream == NULL)) goto error;
8245 if ((expected_stream == NULL) && (stream != NULL)) goto error;
8247 if ((stream != NULL) && (strcmp(expected_stream, stream) != 0))
8248 goto error;
8250 TALLOC_FREE(base);
8251 TALLOC_FREE(stream);
8252 return true;
8254 error:
8255 d_fprintf(stderr, "Do test_stream(%s, %s, %s, %s)\n",
8256 fname, expected_base ? expected_base : "<NULL>",
8257 expected_stream ? expected_stream : "<NULL>",
8258 nt_errstr(expected_status));
8259 d_fprintf(stderr, "-> base=%s, stream=%s, status=%s\n",
8260 base ? base : "<NULL>", stream ? stream : "<NULL>",
8261 nt_errstr(status));
8262 TALLOC_FREE(base);
8263 TALLOC_FREE(stream);
8264 return false;
8267 static bool run_local_stream_name(int dummy)
8269 bool ret = true;
8271 ret &= test_stream_name(
8272 "bla", "bla", NULL, NT_STATUS_OK);
8273 ret &= test_stream_name(
8274 "bla::$DATA", "bla", NULL, NT_STATUS_OK);
8275 ret &= test_stream_name(
8276 "bla:blub:", "bla", NULL, NT_STATUS_OBJECT_NAME_INVALID);
8277 ret &= test_stream_name(
8278 "bla::", NULL, NULL, NT_STATUS_OBJECT_NAME_INVALID);
8279 ret &= test_stream_name(
8280 "bla::123", "bla", NULL, NT_STATUS_OBJECT_NAME_INVALID);
8281 ret &= test_stream_name(
8282 "bla:$DATA", "bla", "$DATA:$DATA", NT_STATUS_OK);
8283 ret &= test_stream_name(
8284 "bla:x:$DATA", "bla", "x:$DATA", NT_STATUS_OK);
8285 ret &= test_stream_name(
8286 "bla:x", "bla", "x:$DATA", NT_STATUS_OK);
8288 return ret;
8291 static bool data_blob_equal(DATA_BLOB a, DATA_BLOB b)
8293 if (a.length != b.length) {
8294 printf("a.length=%d != b.length=%d\n",
8295 (int)a.length, (int)b.length);
8296 return false;
8298 if (memcmp(a.data, b.data, a.length) != 0) {
8299 printf("a.data and b.data differ\n");
8300 return false;
8302 return true;
8305 static bool run_local_memcache(int dummy)
8307 struct memcache *cache;
8308 DATA_BLOB k1, k2;
8309 DATA_BLOB d1, d2, d3;
8310 DATA_BLOB v1, v2, v3;
8312 TALLOC_CTX *mem_ctx;
8313 char *str1, *str2;
8314 size_t size1, size2;
8315 bool ret = false;
8317 cache = memcache_init(NULL, 100);
8319 if (cache == NULL) {
8320 printf("memcache_init failed\n");
8321 return false;
8324 d1 = data_blob_const("d1", 2);
8325 d2 = data_blob_const("d2", 2);
8326 d3 = data_blob_const("d3", 2);
8328 k1 = data_blob_const("d1", 2);
8329 k2 = data_blob_const("d2", 2);
8331 memcache_add(cache, STAT_CACHE, k1, d1);
8332 memcache_add(cache, GETWD_CACHE, k2, d2);
8334 if (!memcache_lookup(cache, STAT_CACHE, k1, &v1)) {
8335 printf("could not find k1\n");
8336 return false;
8338 if (!data_blob_equal(d1, v1)) {
8339 return false;
8342 if (!memcache_lookup(cache, GETWD_CACHE, k2, &v2)) {
8343 printf("could not find k2\n");
8344 return false;
8346 if (!data_blob_equal(d2, v2)) {
8347 return false;
8350 memcache_add(cache, STAT_CACHE, k1, d3);
8352 if (!memcache_lookup(cache, STAT_CACHE, k1, &v3)) {
8353 printf("could not find replaced k1\n");
8354 return false;
8356 if (!data_blob_equal(d3, v3)) {
8357 return false;
8360 memcache_add(cache, GETWD_CACHE, k1, d1);
8362 if (memcache_lookup(cache, GETWD_CACHE, k2, &v2)) {
8363 printf("Did find k2, should have been purged\n");
8364 return false;
8367 TALLOC_FREE(cache);
8369 cache = memcache_init(NULL, 0);
8371 mem_ctx = talloc_init("foo");
8373 str1 = talloc_strdup(mem_ctx, "string1");
8374 str2 = talloc_strdup(mem_ctx, "string2");
8376 memcache_add_talloc(cache, SINGLETON_CACHE_TALLOC,
8377 data_blob_string_const("torture"), &str1);
8378 size1 = talloc_total_size(cache);
8380 memcache_add_talloc(cache, SINGLETON_CACHE_TALLOC,
8381 data_blob_string_const("torture"), &str2);
8382 size2 = talloc_total_size(cache);
8384 printf("size1=%d, size2=%d\n", (int)size1, (int)size2);
8386 if (size2 > size1) {
8387 printf("memcache leaks memory!\n");
8388 goto fail;
8391 ret = true;
8392 fail:
8393 TALLOC_FREE(cache);
8394 return ret;
8397 static void wbclient_done(struct tevent_req *req)
8399 wbcErr wbc_err;
8400 struct winbindd_response *wb_resp;
8401 int *i = (int *)tevent_req_callback_data_void(req);
8403 wbc_err = wb_trans_recv(req, req, &wb_resp);
8404 TALLOC_FREE(req);
8405 *i += 1;
8406 d_printf("wb_trans_recv %d returned %s\n", *i, wbcErrorString(wbc_err));
8409 static bool run_local_wbclient(int dummy)
8411 struct event_context *ev;
8412 struct wb_context **wb_ctx;
8413 struct winbindd_request wb_req;
8414 bool result = false;
8415 int i, j;
8417 BlockSignals(True, SIGPIPE);
8419 ev = tevent_context_init_byname(talloc_tos(), "epoll");
8420 if (ev == NULL) {
8421 goto fail;
8424 wb_ctx = talloc_array(ev, struct wb_context *, nprocs);
8425 if (wb_ctx == NULL) {
8426 goto fail;
8429 ZERO_STRUCT(wb_req);
8430 wb_req.cmd = WINBINDD_PING;
8432 d_printf("nprocs=%d, numops=%d\n", (int)nprocs, (int)torture_numops);
8434 for (i=0; i<nprocs; i++) {
8435 wb_ctx[i] = wb_context_init(ev, NULL);
8436 if (wb_ctx[i] == NULL) {
8437 goto fail;
8439 for (j=0; j<torture_numops; j++) {
8440 struct tevent_req *req;
8441 req = wb_trans_send(ev, ev, wb_ctx[i],
8442 (j % 2) == 0, &wb_req);
8443 if (req == NULL) {
8444 goto fail;
8446 tevent_req_set_callback(req, wbclient_done, &i);
8450 i = 0;
8452 while (i < nprocs * torture_numops) {
8453 tevent_loop_once(ev);
8456 result = true;
8457 fail:
8458 TALLOC_FREE(ev);
8459 return result;
8462 static void getaddrinfo_finished(struct tevent_req *req)
8464 char *name = (char *)tevent_req_callback_data_void(req);
8465 struct addrinfo *ainfo;
8466 int res;
8468 res = getaddrinfo_recv(req, &ainfo);
8469 if (res != 0) {
8470 d_printf("gai(%s) returned %s\n", name, gai_strerror(res));
8471 return;
8473 d_printf("gai(%s) succeeded\n", name);
8474 freeaddrinfo(ainfo);
8477 static bool run_getaddrinfo_send(int dummy)
8479 TALLOC_CTX *frame = talloc_stackframe();
8480 struct fncall_context *ctx;
8481 struct tevent_context *ev;
8482 bool result = false;
8483 const char *names[4] = { "www.samba.org", "notfound.samba.org",
8484 "www.slashdot.org", "heise.de" };
8485 struct tevent_req *reqs[4];
8486 int i;
8488 ev = event_context_init(frame);
8489 if (ev == NULL) {
8490 goto fail;
8493 ctx = fncall_context_init(frame, 4);
8495 for (i=0; i<ARRAY_SIZE(names); i++) {
8496 reqs[i] = getaddrinfo_send(frame, ev, ctx, names[i], NULL,
8497 NULL);
8498 if (reqs[i] == NULL) {
8499 goto fail;
8501 tevent_req_set_callback(reqs[i], getaddrinfo_finished,
8502 discard_const_p(void, names[i]));
8505 for (i=0; i<ARRAY_SIZE(reqs); i++) {
8506 tevent_loop_once(ev);
8509 result = true;
8510 fail:
8511 TALLOC_FREE(frame);
8512 return result;
8515 static bool dbtrans_inc(struct db_context *db)
8517 struct db_record *rec;
8518 uint32_t *val;
8519 bool ret = false;
8520 NTSTATUS status;
8521 TDB_DATA value;
8523 rec = dbwrap_fetch_locked(db, db, string_term_tdb_data("transtest"));
8524 if (rec == NULL) {
8525 printf(__location__ "fetch_lock failed\n");
8526 return false;
8529 value = dbwrap_record_get_value(rec);
8531 if (value.dsize != sizeof(uint32_t)) {
8532 printf(__location__ "value.dsize = %d\n",
8533 (int)value.dsize);
8534 goto fail;
8537 val = (uint32_t *)value.dptr;
8538 *val += 1;
8540 status = dbwrap_record_store(rec, make_tdb_data((uint8_t *)val,
8541 sizeof(uint32_t)),
8543 if (!NT_STATUS_IS_OK(status)) {
8544 printf(__location__ "store failed: %s\n",
8545 nt_errstr(status));
8546 goto fail;
8549 ret = true;
8550 fail:
8551 TALLOC_FREE(rec);
8552 return ret;
8555 static bool run_local_dbtrans(int dummy)
8557 struct db_context *db;
8558 struct db_record *rec;
8559 NTSTATUS status;
8560 uint32_t initial;
8561 int res;
8562 TDB_DATA value;
8564 db = db_open(talloc_tos(), "transtest.tdb", 0, TDB_DEFAULT,
8565 O_RDWR|O_CREAT, 0600);
8566 if (db == NULL) {
8567 printf("Could not open transtest.db\n");
8568 return false;
8571 res = dbwrap_transaction_start(db);
8572 if (res != 0) {
8573 printf(__location__ "transaction_start failed\n");
8574 return false;
8577 rec = dbwrap_fetch_locked(db, db, string_term_tdb_data("transtest"));
8578 if (rec == NULL) {
8579 printf(__location__ "fetch_lock failed\n");
8580 return false;
8583 value = dbwrap_record_get_value(rec);
8585 if (value.dptr == NULL) {
8586 initial = 0;
8587 status = dbwrap_record_store(
8588 rec, make_tdb_data((uint8_t *)&initial,
8589 sizeof(initial)),
8591 if (!NT_STATUS_IS_OK(status)) {
8592 printf(__location__ "store returned %s\n",
8593 nt_errstr(status));
8594 return false;
8598 TALLOC_FREE(rec);
8600 res = dbwrap_transaction_commit(db);
8601 if (res != 0) {
8602 printf(__location__ "transaction_commit failed\n");
8603 return false;
8606 while (true) {
8607 uint32_t val, val2;
8608 int i;
8610 res = dbwrap_transaction_start(db);
8611 if (res != 0) {
8612 printf(__location__ "transaction_start failed\n");
8613 break;
8616 status = dbwrap_fetch_uint32(db, "transtest", &val);
8617 if (!NT_STATUS_IS_OK(status)) {
8618 printf(__location__ "dbwrap_fetch_uint32 failed: %s\n",
8619 nt_errstr(status));
8620 break;
8623 for (i=0; i<10; i++) {
8624 if (!dbtrans_inc(db)) {
8625 return false;
8629 status = dbwrap_fetch_uint32(db, "transtest", &val2);
8630 if (!NT_STATUS_IS_OK(status)) {
8631 printf(__location__ "dbwrap_fetch_uint32 failed: %s\n",
8632 nt_errstr(status));
8633 break;
8636 if (val2 != val + 10) {
8637 printf(__location__ "val=%d, val2=%d\n",
8638 (int)val, (int)val2);
8639 break;
8642 printf("val2=%d\r", val2);
8644 res = dbwrap_transaction_commit(db);
8645 if (res != 0) {
8646 printf(__location__ "transaction_commit failed\n");
8647 break;
8651 TALLOC_FREE(db);
8652 return true;
8656 * Just a dummy test to be run under a debugger. There's no real way
8657 * to inspect the tevent_select specific function from outside of
8658 * tevent_select.c.
8661 static bool run_local_tevent_select(int dummy)
8663 struct tevent_context *ev;
8664 struct tevent_fd *fd1, *fd2;
8665 bool result = false;
8667 ev = tevent_context_init_byname(NULL, "select");
8668 if (ev == NULL) {
8669 d_fprintf(stderr, "tevent_context_init_byname failed\n");
8670 goto fail;
8673 fd1 = tevent_add_fd(ev, ev, 2, 0, NULL, NULL);
8674 if (fd1 == NULL) {
8675 d_fprintf(stderr, "tevent_add_fd failed\n");
8676 goto fail;
8678 fd2 = tevent_add_fd(ev, ev, 3, 0, NULL, NULL);
8679 if (fd2 == NULL) {
8680 d_fprintf(stderr, "tevent_add_fd failed\n");
8681 goto fail;
8683 TALLOC_FREE(fd2);
8685 fd2 = tevent_add_fd(ev, ev, 1, 0, NULL, NULL);
8686 if (fd2 == NULL) {
8687 d_fprintf(stderr, "tevent_add_fd failed\n");
8688 goto fail;
8691 result = true;
8692 fail:
8693 TALLOC_FREE(ev);
8694 return result;
8697 static double create_procs(bool (*fn)(int), bool *result)
8699 int i, status;
8700 volatile pid_t *child_status;
8701 volatile bool *child_status_out;
8702 int synccount;
8703 int tries = 8;
8704 struct timeval start;
8706 synccount = 0;
8708 child_status = (volatile pid_t *)shm_setup(sizeof(pid_t)*nprocs);
8709 if (!child_status) {
8710 printf("Failed to setup shared memory\n");
8711 return -1;
8714 child_status_out = (volatile bool *)shm_setup(sizeof(bool)*nprocs);
8715 if (!child_status_out) {
8716 printf("Failed to setup result status shared memory\n");
8717 return -1;
8720 for (i = 0; i < nprocs; i++) {
8721 child_status[i] = 0;
8722 child_status_out[i] = True;
8725 start = timeval_current();
8727 for (i=0;i<nprocs;i++) {
8728 procnum = i;
8729 if (fork() == 0) {
8730 pid_t mypid = getpid();
8731 sys_srandom(((int)mypid) ^ ((int)time(NULL)));
8733 slprintf(myname,sizeof(myname),"CLIENT%d", i);
8735 while (1) {
8736 if (torture_open_connection(&current_cli, i)) break;
8737 if (tries-- == 0) {
8738 printf("pid %d failed to start\n", (int)getpid());
8739 _exit(1);
8741 smb_msleep(10);
8744 child_status[i] = getpid();
8746 while (child_status[i] && timeval_elapsed(&start) < 5) smb_msleep(2);
8748 child_status_out[i] = fn(i);
8749 _exit(0);
8753 do {
8754 synccount = 0;
8755 for (i=0;i<nprocs;i++) {
8756 if (child_status[i]) synccount++;
8758 if (synccount == nprocs) break;
8759 smb_msleep(10);
8760 } while (timeval_elapsed(&start) < 30);
8762 if (synccount != nprocs) {
8763 printf("FAILED TO START %d CLIENTS (started %d)\n", nprocs, synccount);
8764 *result = False;
8765 return timeval_elapsed(&start);
8768 /* start the client load */
8769 start = timeval_current();
8771 for (i=0;i<nprocs;i++) {
8772 child_status[i] = 0;
8775 printf("%d clients started\n", nprocs);
8777 for (i=0;i<nprocs;i++) {
8778 while (waitpid(0, &status, 0) == -1 && errno == EINTR) /* noop */ ;
8781 printf("\n");
8783 for (i=0;i<nprocs;i++) {
8784 if (!child_status_out[i]) {
8785 *result = False;
8788 return timeval_elapsed(&start);
8791 #define FLAG_MULTIPROC 1
8793 static struct {
8794 const char *name;
8795 bool (*fn)(int);
8796 unsigned flags;
8797 } torture_ops[] = {
8798 {"FDPASS", run_fdpasstest, 0},
8799 {"LOCK1", run_locktest1, 0},
8800 {"LOCK2", run_locktest2, 0},
8801 {"LOCK3", run_locktest3, 0},
8802 {"LOCK4", run_locktest4, 0},
8803 {"LOCK5", run_locktest5, 0},
8804 {"LOCK6", run_locktest6, 0},
8805 {"LOCK7", run_locktest7, 0},
8806 {"LOCK8", run_locktest8, 0},
8807 {"LOCK9", run_locktest9, 0},
8808 {"UNLINK", run_unlinktest, 0},
8809 {"BROWSE", run_browsetest, 0},
8810 {"ATTR", run_attrtest, 0},
8811 {"TRANS2", run_trans2test, 0},
8812 {"MAXFID", run_maxfidtest, FLAG_MULTIPROC},
8813 {"TORTURE",run_torture, FLAG_MULTIPROC},
8814 {"RANDOMIPC", run_randomipc, 0},
8815 {"NEGNOWAIT", run_negprot_nowait, 0},
8816 {"NBENCH", run_nbench, 0},
8817 {"NBENCH2", run_nbench2, 0},
8818 {"OPLOCK1", run_oplock1, 0},
8819 {"OPLOCK2", run_oplock2, 0},
8820 {"OPLOCK4", run_oplock4, 0},
8821 {"DIR", run_dirtest, 0},
8822 {"DIR1", run_dirtest1, 0},
8823 {"DIR-CREATETIME", run_dir_createtime, 0},
8824 {"DENY1", torture_denytest1, 0},
8825 {"DENY2", torture_denytest2, 0},
8826 {"TCON", run_tcon_test, 0},
8827 {"TCONDEV", run_tcon_devtype_test, 0},
8828 {"RW1", run_readwritetest, 0},
8829 {"RW2", run_readwritemulti, FLAG_MULTIPROC},
8830 {"RW3", run_readwritelarge, 0},
8831 {"RW-SIGNING", run_readwritelarge_signtest, 0},
8832 {"OPEN", run_opentest, 0},
8833 {"POSIX", run_simple_posix_open_test, 0},
8834 {"POSIX-APPEND", run_posix_append, 0},
8835 {"CASE-INSENSITIVE-CREATE", run_case_insensitive_create, 0},
8836 {"ASYNC-ECHO", run_async_echo, 0},
8837 { "UID-REGRESSION-TEST", run_uid_regression_test, 0},
8838 { "SHORTNAME-TEST", run_shortname_test, 0},
8839 { "ADDRCHANGE", run_addrchange, 0},
8840 #if 1
8841 {"OPENATTR", run_openattrtest, 0},
8842 #endif
8843 {"XCOPY", run_xcopy, 0},
8844 {"RENAME", run_rename, 0},
8845 {"DELETE", run_deletetest, 0},
8846 {"DELETE-LN", run_deletetest_ln, 0},
8847 {"PROPERTIES", run_properties, 0},
8848 {"MANGLE", torture_mangle, 0},
8849 {"MANGLE1", run_mangle1, 0},
8850 {"W2K", run_w2ktest, 0},
8851 {"TRANS2SCAN", torture_trans2_scan, 0},
8852 {"NTTRANSSCAN", torture_nttrans_scan, 0},
8853 {"UTABLE", torture_utable, 0},
8854 {"CASETABLE", torture_casetable, 0},
8855 {"ERRMAPEXTRACT", run_error_map_extract, 0},
8856 {"PIPE_NUMBER", run_pipe_number, 0},
8857 {"TCON2", run_tcon2_test, 0},
8858 {"IOCTL", torture_ioctl_test, 0},
8859 {"CHKPATH", torture_chkpath_test, 0},
8860 {"FDSESS", run_fdsesstest, 0},
8861 { "EATEST", run_eatest, 0},
8862 { "SESSSETUP_BENCH", run_sesssetup_bench, 0},
8863 { "CHAIN1", run_chain1, 0},
8864 { "CHAIN2", run_chain2, 0},
8865 { "WINDOWS-WRITE", run_windows_write, 0},
8866 { "NTTRANS-CREATE", run_nttrans_create, 0},
8867 { "NTTRANS-FSCTL", run_nttrans_fsctl, 0},
8868 { "CLI_ECHO", run_cli_echo, 0},
8869 { "GETADDRINFO", run_getaddrinfo_send, 0},
8870 { "TLDAP", run_tldap },
8871 { "STREAMERROR", run_streamerror },
8872 { "NOTIFY-BENCH", run_notify_bench },
8873 { "BAD-NBT-SESSION", run_bad_nbt_session },
8874 { "SMB-ANY-CONNECT", run_smb_any_connect },
8875 { "NOTIFY-ONLINE", run_notify_online },
8876 { "SMB2-BASIC", run_smb2_basic },
8877 { "SMB2-NEGPROT", run_smb2_negprot },
8878 { "LOCAL-SUBSTITUTE", run_local_substitute, 0},
8879 { "LOCAL-GENCACHE", run_local_gencache, 0},
8880 { "LOCAL-TALLOC-DICT", run_local_talloc_dict, 0},
8881 { "LOCAL-BASE64", run_local_base64, 0},
8882 { "LOCAL-RBTREE", run_local_rbtree, 0},
8883 { "LOCAL-MEMCACHE", run_local_memcache, 0},
8884 { "LOCAL-STREAM-NAME", run_local_stream_name, 0},
8885 { "LOCAL-WBCLIENT", run_local_wbclient, 0},
8886 { "LOCAL-string_to_sid", run_local_string_to_sid, 0},
8887 { "LOCAL-binary_to_sid", run_local_binary_to_sid, 0},
8888 { "LOCAL-DBTRANS", run_local_dbtrans, 0},
8889 { "LOCAL-TEVENT-SELECT", run_local_tevent_select, 0},
8890 { "LOCAL-CONVERT-STRING", run_local_convert_string, 0},
8891 { "LOCAL-CONV-AUTH-INFO", run_local_conv_auth_info, 0},
8892 { "LOCAL-sprintf_append", run_local_sprintf_append, 0},
8893 {NULL, NULL, 0}};
8897 /****************************************************************************
8898 run a specified test or "ALL"
8899 ****************************************************************************/
8900 static bool run_test(const char *name)
8902 bool ret = True;
8903 bool result = True;
8904 bool found = False;
8905 int i;
8906 double t;
8907 if (strequal(name,"ALL")) {
8908 for (i=0;torture_ops[i].name;i++) {
8909 run_test(torture_ops[i].name);
8911 found = True;
8914 for (i=0;torture_ops[i].name;i++) {
8915 fstr_sprintf(randomfname, "\\XX%x",
8916 (unsigned)random());
8918 if (strequal(name, torture_ops[i].name)) {
8919 found = True;
8920 printf("Running %s\n", name);
8921 if (torture_ops[i].flags & FLAG_MULTIPROC) {
8922 t = create_procs(torture_ops[i].fn, &result);
8923 if (!result) {
8924 ret = False;
8925 printf("TEST %s FAILED!\n", name);
8927 } else {
8928 struct timeval start;
8929 start = timeval_current();
8930 if (!torture_ops[i].fn(0)) {
8931 ret = False;
8932 printf("TEST %s FAILED!\n", name);
8934 t = timeval_elapsed(&start);
8936 printf("%s took %g secs\n\n", name, t);
8940 if (!found) {
8941 printf("Did not find a test named %s\n", name);
8942 ret = False;
8945 return ret;
8949 static void usage(void)
8951 int i;
8953 printf("WARNING samba4 test suite is much more complete nowadays.\n");
8954 printf("Please use samba4 torture.\n\n");
8956 printf("Usage: smbtorture //server/share <options> TEST1 TEST2 ...\n");
8958 printf("\t-d debuglevel\n");
8959 printf("\t-U user%%pass\n");
8960 printf("\t-k use kerberos\n");
8961 printf("\t-N numprocs\n");
8962 printf("\t-n my_netbios_name\n");
8963 printf("\t-W workgroup\n");
8964 printf("\t-o num_operations\n");
8965 printf("\t-O socket_options\n");
8966 printf("\t-m maximum protocol\n");
8967 printf("\t-L use oplocks\n");
8968 printf("\t-c CLIENT.TXT specify client load file for NBENCH\n");
8969 printf("\t-A showall\n");
8970 printf("\t-p port\n");
8971 printf("\t-s seed\n");
8972 printf("\t-b unclist_filename specify multiple shares for multiple connections\n");
8973 printf("\t-f filename filename to test\n");
8974 printf("\n\n");
8976 printf("tests are:");
8977 for (i=0;torture_ops[i].name;i++) {
8978 printf(" %s", torture_ops[i].name);
8980 printf("\n");
8982 printf("default test is ALL\n");
8984 exit(1);
8987 /****************************************************************************
8988 main program
8989 ****************************************************************************/
8990 int main(int argc,char *argv[])
8992 int opt, i;
8993 char *p;
8994 int gotuser = 0;
8995 int gotpass = 0;
8996 bool correct = True;
8997 TALLOC_CTX *frame = talloc_stackframe();
8998 int seed = time(NULL);
9000 #ifdef HAVE_SETBUFFER
9001 setbuffer(stdout, NULL, 0);
9002 #endif
9004 setup_logging("smbtorture", DEBUG_STDOUT);
9006 load_case_tables();
9008 if (is_default_dyn_CONFIGFILE()) {
9009 if(getenv("SMB_CONF_PATH")) {
9010 set_dyn_CONFIGFILE(getenv("SMB_CONF_PATH"));
9013 lp_load_global(get_dyn_CONFIGFILE());
9014 load_interfaces();
9016 if (argc < 2) {
9017 usage();
9020 for(p = argv[1]; *p; p++)
9021 if(*p == '\\')
9022 *p = '/';
9024 if (strncmp(argv[1], "//", 2)) {
9025 usage();
9028 fstrcpy(host, &argv[1][2]);
9029 p = strchr_m(&host[2],'/');
9030 if (!p) {
9031 usage();
9033 *p = 0;
9034 fstrcpy(share, p+1);
9036 fstrcpy(myname, get_myname(talloc_tos()));
9037 if (!*myname) {
9038 fprintf(stderr, "Failed to get my hostname.\n");
9039 return 1;
9042 if (*username == 0 && getenv("LOGNAME")) {
9043 fstrcpy(username,getenv("LOGNAME"));
9046 argc--;
9047 argv++;
9049 fstrcpy(workgroup, lp_workgroup());
9051 while ((opt = getopt(argc, argv, "p:hW:U:n:N:O:o:m:Ll:d:Aec:ks:b:B:f:"))
9052 != EOF) {
9053 switch (opt) {
9054 case 'p':
9055 port_to_use = atoi(optarg);
9056 break;
9057 case 's':
9058 seed = atoi(optarg);
9059 break;
9060 case 'W':
9061 fstrcpy(workgroup,optarg);
9062 break;
9063 case 'm':
9064 max_protocol = interpret_protocol(optarg, max_protocol);
9065 break;
9066 case 'N':
9067 nprocs = atoi(optarg);
9068 break;
9069 case 'o':
9070 torture_numops = atoi(optarg);
9071 break;
9072 case 'd':
9073 lp_set_cmdline("log level", optarg);
9074 break;
9075 case 'O':
9076 sockops = optarg;
9077 break;
9078 case 'L':
9079 use_oplocks = True;
9080 break;
9081 case 'l':
9082 local_path = optarg;
9083 break;
9084 case 'A':
9085 torture_showall = True;
9086 break;
9087 case 'n':
9088 fstrcpy(myname, optarg);
9089 break;
9090 case 'c':
9091 client_txt = optarg;
9092 break;
9093 case 'e':
9094 do_encrypt = true;
9095 break;
9096 case 'k':
9097 #ifdef HAVE_KRB5
9098 use_kerberos = True;
9099 #else
9100 d_printf("No kerberos support compiled in\n");
9101 exit(1);
9102 #endif
9103 break;
9104 case 'U':
9105 gotuser = 1;
9106 fstrcpy(username,optarg);
9107 p = strchr_m(username,'%');
9108 if (p) {
9109 *p = 0;
9110 fstrcpy(password, p+1);
9111 gotpass = 1;
9113 break;
9114 case 'b':
9115 fstrcpy(multishare_conn_fname, optarg);
9116 use_multishare_conn = True;
9117 break;
9118 case 'B':
9119 torture_blocksize = atoi(optarg);
9120 break;
9121 case 'f':
9122 test_filename = SMB_STRDUP(optarg);
9123 break;
9124 default:
9125 printf("Unknown option %c (%d)\n", (char)opt, opt);
9126 usage();
9130 d_printf("using seed %d\n", seed);
9132 srandom(seed);
9134 if(use_kerberos && !gotuser) gotpass = True;
9136 while (!gotpass) {
9137 p = getpass("Password:");
9138 if (p) {
9139 fstrcpy(password, p);
9140 gotpass = 1;
9144 printf("host=%s share=%s user=%s myname=%s\n",
9145 host, share, username, myname);
9147 if (argc == optind) {
9148 correct = run_test("ALL");
9149 } else {
9150 for (i=optind;i<argc;i++) {
9151 if (!run_test(argv[i])) {
9152 correct = False;
9157 TALLOC_FREE(frame);
9159 if (correct) {
9160 return(0);
9161 } else {
9162 return(1);