2 Unix SMB/CIFS implementation.
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/>.
22 #include "system/shmem.h"
23 #include "libsmb/namequery.h"
24 #include "wbc_async.h"
25 #include "torture/proto.h"
26 #include "libcli/security/security.h"
28 #include "tldap_util.h"
29 #include "tldap_gensec_bind.h"
30 #include "../librpc/gen_ndr/svcctl.h"
31 #include "../lib/util/memcache.h"
32 #include "nsswitch/winbind_client.h"
33 #include "dbwrap/dbwrap.h"
34 #include "dbwrap/dbwrap_open.h"
35 #include "dbwrap/dbwrap_rbt.h"
36 #include "async_smb.h"
37 #include "libsmb/libsmb.h"
38 #include "libsmb/clirap.h"
40 #include "libsmb/nmblib.h"
41 #include "../lib/util/tevent_ntstatus.h"
43 #include "../libcli/smb/read_smb.h"
44 #include "../libcli/smb/smbXcli_base.h"
45 #include "lib/util/sys_rw_data.h"
46 #include "lib/util/base64.h"
47 #include "lib/util/time.h"
48 #include "lib/gencache.h"
49 #include "lib/util/sys_rw.h"
50 #include "lib/util/asn1.h"
51 #include "lib/util/util_file.h"
52 #include "lib/param/param.h"
53 #include "auth/gensec/gensec.h"
54 #include "lib/util/string_wrappers.h"
55 #include "source3/lib/substitute.h"
57 #include <gnutls/gnutls.h>
58 #include <gnutls/crypto.h>
63 fstring host, workgroup, share, password, username, myname;
64 struct cli_credentials *torture_creds;
65 static const char *sockops="TCP_NODELAY";
67 static int port_to_use=0;
68 int torture_numops=100;
69 int torture_blocksize=1024*1024;
70 static int procnum; /* records process count number when forking */
71 static struct cli_state *current_cli;
72 static fstring randomfname;
73 static bool use_oplocks;
74 static bool use_level_II_oplocks;
75 static const char *client_txt = "client_oplocks.txt";
76 static bool disable_spnego;
77 static bool use_kerberos;
78 static bool force_dos_errors;
79 static fstring multishare_conn_fname;
80 static bool use_multishare_conn = False;
81 static bool do_encrypt;
82 static const char *local_path = NULL;
83 static enum smb_signing_setting signing_state = SMB_SIGNING_DEFAULT;
86 bool torture_showall = False;
88 static double create_procs(bool (*fn)(int), bool *result);
90 /********************************************************************
91 Ensure a connection is encrypted.
92 ********************************************************************/
94 static bool force_cli_encryption(struct cli_state *c,
95 const char *sharename)
97 uint16_t major, minor;
98 uint32_t caplow, caphigh;
101 if (!SERVER_HAS_UNIX_CIFS(c)) {
102 d_printf("Encryption required and "
103 "server that doesn't support "
104 "UNIX extensions - failing connect\n");
108 status = cli_unix_extensions_version(c, &major, &minor, &caplow,
110 if (!NT_STATUS_IS_OK(status)) {
111 d_printf("Encryption required and "
112 "can't get UNIX CIFS extensions "
113 "version from server: %s\n", nt_errstr(status));
117 if (!(caplow & CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP)) {
118 d_printf("Encryption required and "
119 "share %s doesn't support "
120 "encryption.\n", sharename);
124 status = cli_smb1_setup_encryption(c, torture_creds);
125 if (!NT_STATUS_IS_OK(status)) {
126 d_printf("Encryption required and "
127 "setup failed with error %s.\n",
136 static struct cli_state *open_nbt_connection(void)
142 if (disable_spnego) {
143 flags |= CLI_FULL_CONNECTION_DONT_SPNEGO;
147 flags |= CLI_FULL_CONNECTION_OPLOCKS;
150 if (use_level_II_oplocks) {
151 flags |= CLI_FULL_CONNECTION_LEVEL_II_OPLOCKS;
154 if (force_dos_errors) {
155 flags |= CLI_FULL_CONNECTION_FORCE_DOS_ERRORS;
158 status = cli_connect_nb(host, NULL, port_to_use, 0x20, myname,
159 signing_state, flags, &c);
160 if (!NT_STATUS_IS_OK(status)) {
161 printf("Failed to connect with %s. Error %s\n", host, nt_errstr(status) );
165 cli_set_timeout(c, 120000); /* set a really long timeout (2 minutes) */
170 /****************************************************************************
171 Send a corrupt session request. See rfc1002.txt 4.3 and 4.3.2.
172 ****************************************************************************/
174 static bool cli_bad_session_request(int fd,
175 struct nmb_name *calling, struct nmb_name *called)
184 uint8_t message_type;
186 struct tevent_context *ev;
187 struct tevent_req *req;
189 frame = talloc_stackframe();
191 iov[0].iov_base = len_buf;
192 iov[0].iov_len = sizeof(len_buf);
194 /* put in the destination name */
196 iov[1].iov_base = name_mangle(talloc_tos(), called->name,
198 if (iov[1].iov_base == NULL) {
201 iov[1].iov_len = name_len((unsigned char *)iov[1].iov_base,
202 talloc_get_size(iov[1].iov_base));
206 iov[2].iov_base = name_mangle(talloc_tos(), calling->name,
208 if (iov[2].iov_base == NULL) {
211 iov[2].iov_len = name_len((unsigned char *)iov[2].iov_base,
212 talloc_get_size(iov[2].iov_base));
214 /* Deliberately corrupt the name len (first byte) */
215 *((uint8_t *)iov[2].iov_base) = 100;
217 /* send a session request (RFC 1002) */
218 /* setup the packet length
219 * Remove four bytes from the length count, since the length
220 * field in the NBT Session Service header counts the number
221 * of bytes which follow. The cli_send_smb() function knows
222 * about this and accounts for those four bytes.
226 _smb_setlen(len_buf, iov[1].iov_len + iov[2].iov_len);
227 SCVAL(len_buf,0,0x81);
229 len = write_data_iov(fd, iov, 3);
234 ev = samba_tevent_context_init(frame);
238 req = read_smb_send(frame, ev, fd);
242 if (!tevent_req_poll(req, ev)) {
245 len = read_smb_recv(req, talloc_tos(), &inbuf, &err);
252 message_type = CVAL(inbuf, 0);
253 if (message_type != 0x83) {
254 d_fprintf(stderr, "Expected msg type 0x83, got 0x%2.2x\n",
259 if (smb_len(inbuf) != 1) {
260 d_fprintf(stderr, "Expected smb_len 1, got %d\n",
261 (int)smb_len(inbuf));
265 error = CVAL(inbuf, 4);
267 d_fprintf(stderr, "Expected error 0x82, got %d\n",
278 /* Insert a NULL at the first separator of the given path and return a pointer
279 * to the remainder of the string.
282 terminate_path_at_separator(char * path)
290 if ((p = strchr_m(path, '/'))) {
295 if ((p = strchr_m(path, '\\'))) {
305 parse a //server/share type UNC name
307 bool smbcli_parse_unc(const char *unc_name, TALLOC_CTX *mem_ctx,
308 char **hostname, char **sharename)
312 *hostname = *sharename = NULL;
314 if (strncmp(unc_name, "\\\\", 2) &&
315 strncmp(unc_name, "//", 2)) {
319 *hostname = talloc_strdup(mem_ctx, &unc_name[2]);
320 p = terminate_path_at_separator(*hostname);
323 *sharename = talloc_strdup(mem_ctx, p);
324 terminate_path_at_separator(*sharename);
327 if (*hostname && *sharename) {
331 TALLOC_FREE(*hostname);
332 TALLOC_FREE(*sharename);
336 static bool torture_open_connection_share(struct cli_state **c,
337 const char *hostname,
338 const char *sharename,
343 status = cli_full_connection_creds(c,
352 if (!NT_STATUS_IS_OK(status)) {
353 printf("failed to open share connection: //%s/%s port:%d - %s\n",
354 hostname, sharename, port_to_use, nt_errstr(status));
358 cli_set_timeout(*c, 120000); /* set a really long timeout (2 minutes) */
361 return force_cli_encryption(*c,
367 bool torture_open_connection_flags(struct cli_state **c, int conn_index, int flags)
369 char **unc_list = NULL;
370 int num_unc_names = 0;
373 if (use_multishare_conn==True) {
375 unc_list = file_lines_load(multishare_conn_fname, &num_unc_names, 0, NULL);
376 if (!unc_list || num_unc_names <= 0) {
377 printf("Failed to load unc names list from '%s'\n", multishare_conn_fname);
381 if (!smbcli_parse_unc(unc_list[conn_index % num_unc_names],
383 printf("Failed to parse UNC name %s\n",
384 unc_list[conn_index % num_unc_names]);
385 TALLOC_FREE(unc_list);
389 result = torture_open_connection_share(c, h, s, flags);
391 /* h, s were copied earlier */
392 TALLOC_FREE(unc_list);
396 return torture_open_connection_share(c, host, share, flags);
399 bool torture_open_connection(struct cli_state **c, int conn_index)
401 int flags = CLI_FULL_CONNECTION_FORCE_SMB1;
404 flags |= CLI_FULL_CONNECTION_OPLOCKS;
406 if (use_level_II_oplocks) {
407 flags |= CLI_FULL_CONNECTION_LEVEL_II_OPLOCKS;
410 return torture_open_connection_flags(c, conn_index, flags);
413 bool torture_init_connection(struct cli_state **pcli)
415 struct cli_state *cli;
417 cli = open_nbt_connection();
426 bool torture_cli_session_setup2(struct cli_state *cli, uint16_t *new_vuid)
428 uint16_t old_vuid = cli_state_get_uid(cli);
432 cli_state_set_uid(cli, 0);
433 status = cli_session_setup_creds(cli, torture_creds);
434 ret = NT_STATUS_IS_OK(status);
435 *new_vuid = cli_state_get_uid(cli);
436 cli_state_set_uid(cli, old_vuid);
441 bool torture_close_connection(struct cli_state *c)
446 status = cli_tdis(c);
447 if (!NT_STATUS_IS_OK(status)) {
448 printf("tdis failed (%s)\n", nt_errstr(status));
457 void torture_conn_set_sockopt(struct cli_state *cli)
459 smbXcli_conn_set_sockopt(cli->conn, sockops);
462 static NTSTATUS torture_delete_fn(struct file_info *finfo,
467 char *filename = NULL;
468 char *dirname = NULL;
470 TALLOC_CTX *frame = talloc_stackframe();
471 struct cli_state *cli = (struct cli_state *)state;
473 if (ISDOT(finfo->name) || ISDOTDOT(finfo->name)) {
478 dirname = talloc_strdup(frame, pattern);
479 if (dirname == NULL) {
481 return NT_STATUS_NO_MEMORY;
483 p = strrchr_m(dirname, '\\');
485 /* Remove the terminating '\' */
488 if (dirname[0] != '\0') {
489 filename = talloc_asprintf(frame,
494 filename = talloc_asprintf(frame,
498 if (filename == NULL) {
500 return NT_STATUS_NO_MEMORY;
502 if (finfo->attr & FILE_ATTRIBUTE_DIRECTORY) {
503 char *subdirname = talloc_asprintf(frame,
506 if (subdirname == NULL) {
508 return NT_STATUS_NO_MEMORY;
510 status = cli_list(cli,
512 FILE_ATTRIBUTE_DIRECTORY |
513 FILE_ATTRIBUTE_HIDDEN |
514 FILE_ATTRIBUTE_SYSTEM,
517 if (!NT_STATUS_IS_OK(status)) {
518 printf("torture_delete_fn: cli_list "
519 "of %s failed (%s)\n",
525 status = cli_rmdir(cli, filename);
527 status = cli_unlink(cli,
529 FILE_ATTRIBUTE_SYSTEM |
530 FILE_ATTRIBUTE_HIDDEN);
532 if (!NT_STATUS_IS_OK(status)) {
533 if (finfo->attr & FILE_ATTRIBUTE_DIRECTORY) {
534 printf("torture_delete_fn: cli_rmdir"
535 " of %s failed (%s)\n",
539 printf("torture_delete_fn: cli_unlink"
540 " of %s failed (%s)\n",
549 void torture_deltree(struct cli_state *cli, const char *dname)
554 /* It might be a file */
555 (void)cli_unlink(cli,
557 FILE_ATTRIBUTE_SYSTEM |
558 FILE_ATTRIBUTE_HIDDEN);
560 mask = talloc_asprintf(cli,
564 printf("torture_deltree: talloc_asprintf failed\n");
568 status = cli_list(cli,
570 FILE_ATTRIBUTE_DIRECTORY |
571 FILE_ATTRIBUTE_HIDDEN|
572 FILE_ATTRIBUTE_SYSTEM,
575 if (!NT_STATUS_IS_OK(status)) {
576 printf("torture_deltree: cli_list of %s failed (%s)\n",
581 status = cli_rmdir(cli, dname);
582 if (!NT_STATUS_IS_OK(status)) {
583 printf("torture_deltree: cli_rmdir of %s failed (%s)\n",
589 /* check if the server produced the expected dos or nt error code */
590 static bool check_both_error(int line, NTSTATUS status,
591 uint8_t eclass, uint32_t ecode, NTSTATUS nterr)
593 if (NT_STATUS_IS_DOS(status)) {
597 /* Check DOS error */
598 cclass = NT_STATUS_DOS_CLASS(status);
599 num = NT_STATUS_DOS_CODE(status);
601 if (eclass != cclass || ecode != num) {
602 printf("unexpected error code class=%d code=%d\n",
603 (int)cclass, (int)num);
604 printf(" expected %d/%d %s (line=%d)\n",
605 (int)eclass, (int)ecode, nt_errstr(nterr), line);
610 if (!NT_STATUS_EQUAL(nterr, status)) {
611 printf("unexpected error code %s\n",
613 printf(" expected %s (line=%d)\n",
614 nt_errstr(nterr), line);
623 /* check if the server produced the expected error code */
624 static bool check_error(int line, NTSTATUS status,
625 uint8_t eclass, uint32_t ecode, NTSTATUS nterr)
627 if (NT_STATUS_IS_DOS(status)) {
631 /* Check DOS error */
633 cclass = NT_STATUS_DOS_CLASS(status);
634 num = NT_STATUS_DOS_CODE(status);
636 if (eclass != cclass || ecode != num) {
637 printf("unexpected error code class=%d code=%d\n",
638 (int)cclass, (int)num);
639 printf(" expected %d/%d %s (line=%d)\n",
640 (int)eclass, (int)ecode, nt_errstr(nterr),
648 if (NT_STATUS_V(nterr) != NT_STATUS_V(status)) {
649 printf("unexpected error code %s\n",
651 printf(" expected %s (line=%d)\n", nt_errstr(nterr),
660 NTSTATUS cli_qpathinfo1(struct cli_state *cli,
668 int timezone = smb1cli_conn_server_time_zone(cli->conn);
669 time_t (*date_fn)(const void *buf, int serverzone) = NULL;
670 uint8_t *rdata = NULL;
674 status = cli_qpathinfo(talloc_tos(),
682 if (!NT_STATUS_IS_OK(status)) {
686 date_fn = make_unix_date;
688 date_fn = make_unix_date2;
692 *change_time = date_fn(rdata + 0, timezone);
695 *access_time = date_fn(rdata + 4, timezone);
698 *write_time = date_fn(rdata + 8, timezone);
701 *size = PULL_LE_U32(rdata, 12);
704 *pattr = PULL_LE_U16(rdata, l1_attrFile);
709 static bool wait_lock(struct cli_state *c, int fnum, uint32_t offset, uint32_t len)
713 status = cli_lock32(c, fnum, offset, len, -1, WRITE_LOCK);
715 while (!NT_STATUS_IS_OK(status)) {
716 if (!check_both_error(__LINE__, status, ERRDOS,
717 ERRlock, NT_STATUS_LOCK_NOT_GRANTED)) {
721 status = cli_lock32(c, fnum, offset, len, -1, WRITE_LOCK);
728 static bool rw_torture(struct cli_state *c)
730 const char *lockfname = "\\torture.lck";
734 pid_t pid2, pid = getpid();
741 memset(buf, '\0', sizeof(buf));
743 status = cli_openx(c, lockfname, O_RDWR | O_CREAT | O_EXCL,
745 if (!NT_STATUS_IS_OK(status)) {
746 status = cli_openx(c, lockfname, O_RDWR, DENY_NONE, &fnum2);
748 if (!NT_STATUS_IS_OK(status)) {
749 printf("open of %s failed (%s)\n",
750 lockfname, nt_errstr(status));
754 for (i=0;i<torture_numops;i++) {
755 unsigned n = (unsigned)sys_random()%10;
758 printf("%d\r", i); fflush(stdout);
760 slprintf(fname, sizeof(fstring) - 1, "\\torture.%u", n);
762 if (!wait_lock(c, fnum2, n*sizeof(int), sizeof(int))) {
766 status = cli_openx(c, fname, O_RDWR | O_CREAT | O_TRUNC,
768 if (!NT_STATUS_IS_OK(status)) {
769 printf("open failed (%s)\n", nt_errstr(status));
774 status = cli_writeall(c, fnum, 0, (uint8_t *)&pid, 0,
776 if (!NT_STATUS_IS_OK(status)) {
777 printf("write failed (%s)\n", nt_errstr(status));
782 status = cli_writeall(c, fnum, 0, (uint8_t *)buf,
783 sizeof(pid)+(j*sizeof(buf)),
785 if (!NT_STATUS_IS_OK(status)) {
786 printf("write failed (%s)\n",
794 status = cli_read(c, fnum, (char *)&pid2, 0, sizeof(pid),
796 if (!NT_STATUS_IS_OK(status)) {
797 printf("read failed (%s)\n", nt_errstr(status));
799 } else if (nread != sizeof(pid)) {
800 printf("read/write compare failed: "
801 "recv %ld req %ld\n", (unsigned long)nread,
802 (unsigned long)sizeof(pid));
807 printf("data corruption!\n");
811 status = cli_close(c, fnum);
812 if (!NT_STATUS_IS_OK(status)) {
813 printf("close failed (%s)\n", nt_errstr(status));
817 status = cli_unlink(c, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
818 if (!NT_STATUS_IS_OK(status)) {
819 printf("unlink failed (%s)\n", nt_errstr(status));
823 status = cli_unlock(c, fnum2, n*sizeof(int), sizeof(int));
824 if (!NT_STATUS_IS_OK(status)) {
825 printf("unlock failed (%s)\n", nt_errstr(status));
831 cli_unlink(c, lockfname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
838 static bool run_torture(int dummy)
840 struct cli_state *cli;
845 smbXcli_conn_set_sockopt(cli->conn, sockops);
847 ret = rw_torture(cli);
849 if (!torture_close_connection(cli)) {
856 static bool rw_torture3(struct cli_state *c, char *lockfname)
858 uint16_t fnum = (uint16_t)-1;
863 unsigned countprev = 0;
866 NTSTATUS status = NT_STATUS_OK;
869 for (i = 0; i < sizeof(buf); i += sizeof(uint32_t))
871 SIVAL(buf, i, sys_random());
878 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
879 if (!NT_STATUS_IS_OK(status)) {
880 printf("unlink failed (%s) (normal, this file should "
881 "not exist)\n", nt_errstr(status));
884 status = cli_openx(c, lockfname, O_RDWR | O_CREAT | O_EXCL,
886 if (!NT_STATUS_IS_OK(status)) {
887 printf("first open read/write of %s failed (%s)\n",
888 lockfname, nt_errstr(status));
894 for (i = 0; i < 500 && fnum == (uint16_t)-1; i++)
896 status = cli_openx(c, lockfname, O_RDONLY,
898 if (NT_STATUS_IS_OK(status)) {
903 if (!NT_STATUS_IS_OK(status)) {
904 printf("second open read-only of %s failed (%s)\n",
905 lockfname, nt_errstr(status));
911 for (count = 0; count < sizeof(buf); count += sent)
913 if (count >= countprev) {
914 printf("%d %8d\r", i, count);
917 countprev += (sizeof(buf) / 20);
922 sent = ((unsigned)sys_random()%(20))+ 1;
923 if (sent > sizeof(buf) - count)
925 sent = sizeof(buf) - count;
928 status = cli_writeall(c, fnum, 0, (uint8_t *)buf+count,
930 if (!NT_STATUS_IS_OK(status)) {
931 printf("write failed (%s)\n",
938 status = cli_read(c, fnum, buf_rd+count, count,
939 sizeof(buf)-count, &sent);
940 if(!NT_STATUS_IS_OK(status)) {
941 printf("read failed offset:%d size:%ld (%s)\n",
942 count, (unsigned long)sizeof(buf)-count,
946 } else if (sent > 0) {
947 if (memcmp(buf_rd+count, buf+count, sent) != 0)
949 printf("read/write compare failed\n");
950 printf("offset: %d req %ld recvd %ld\n", count, (unsigned long)sizeof(buf)-count, (unsigned long)sent);
959 status = cli_close(c, fnum);
960 if (!NT_STATUS_IS_OK(status)) {
961 printf("close failed (%s)\n", nt_errstr(status));
968 static bool rw_torture2(struct cli_state *c1, struct cli_state *c2)
970 const char *lockfname = "\\torture2.lck";
980 status = cli_unlink(c1, lockfname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
981 if (!NT_STATUS_IS_OK(status)) {
982 printf("unlink failed (%s) (normal, this file should not exist)\n", nt_errstr(status));
985 status = cli_openx(c1, lockfname, O_RDWR | O_CREAT | O_EXCL,
987 if (!NT_STATUS_IS_OK(status)) {
988 printf("first open read/write of %s failed (%s)\n",
989 lockfname, nt_errstr(status));
993 status = cli_openx(c2, lockfname, O_RDONLY, DENY_NONE, &fnum2);
994 if (!NT_STATUS_IS_OK(status)) {
995 printf("second open read-only of %s failed (%s)\n",
996 lockfname, nt_errstr(status));
997 cli_close(c1, fnum1);
1001 for (i = 0; i < torture_numops; i++)
1003 size_t buf_size = ((unsigned)sys_random()%(sizeof(buf)-1))+ 1;
1005 printf("%d\r", i); fflush(stdout);
1008 generate_random_buffer((unsigned char *)buf, buf_size);
1010 status = cli_writeall(c1, fnum1, 0, (uint8_t *)buf, 0,
1012 if (!NT_STATUS_IS_OK(status)) {
1013 printf("write failed (%s)\n", nt_errstr(status));
1018 status = cli_read(c2, fnum2, buf_rd, 0, buf_size, &bytes_read);
1019 if(!NT_STATUS_IS_OK(status)) {
1020 printf("read failed (%s)\n", nt_errstr(status));
1023 } else if (bytes_read != buf_size) {
1024 printf("read failed\n");
1025 printf("read %ld, expected %ld\n",
1026 (unsigned long)bytes_read,
1027 (unsigned long)buf_size);
1032 if (memcmp(buf_rd, buf, buf_size) != 0)
1034 printf("read/write compare failed\n");
1040 status = cli_close(c2, fnum2);
1041 if (!NT_STATUS_IS_OK(status)) {
1042 printf("close failed (%s)\n", nt_errstr(status));
1046 status = cli_close(c1, fnum1);
1047 if (!NT_STATUS_IS_OK(status)) {
1048 printf("close failed (%s)\n", nt_errstr(status));
1052 status = cli_unlink(c1, lockfname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1053 if (!NT_STATUS_IS_OK(status)) {
1054 printf("unlink failed (%s)\n", nt_errstr(status));
1061 static bool run_readwritetest(int dummy)
1063 struct cli_state *cli1, *cli2;
1064 bool test1, test2 = False;
1066 if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
1069 smbXcli_conn_set_sockopt(cli1->conn, sockops);
1070 smbXcli_conn_set_sockopt(cli2->conn, sockops);
1072 printf("starting readwritetest\n");
1074 test1 = rw_torture2(cli1, cli2);
1075 printf("Passed readwritetest v1: %s\n", BOOLSTR(test1));
1078 test2 = rw_torture2(cli1, cli1);
1079 printf("Passed readwritetest v2: %s\n", BOOLSTR(test2));
1082 if (!torture_close_connection(cli1)) {
1086 if (!torture_close_connection(cli2)) {
1090 return (test1 && test2);
1093 static bool run_readwritemulti(int dummy)
1095 struct cli_state *cli;
1100 smbXcli_conn_set_sockopt(cli->conn, sockops);
1102 printf("run_readwritemulti: fname %s\n", randomfname);
1103 test = rw_torture3(cli, randomfname);
1105 if (!torture_close_connection(cli)) {
1112 static bool run_readwritelarge_internal(void)
1114 static struct cli_state *cli1;
1116 const char *lockfname = "\\large.dat";
1119 bool correct = True;
1122 if (!torture_open_connection(&cli1, 0)) {
1125 smbXcli_conn_set_sockopt(cli1->conn, sockops);
1126 memset(buf,'\0',sizeof(buf));
1128 printf("starting readwritelarge_internal\n");
1130 cli_unlink(cli1, lockfname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1132 status = cli_openx(cli1, lockfname, O_RDWR | O_CREAT | O_EXCL,
1134 if (!NT_STATUS_IS_OK(status)) {
1135 printf("open read/write of %s failed (%s)\n", lockfname, nt_errstr(status));
1139 cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 0, sizeof(buf), NULL);
1141 status = cli_qfileinfo_basic(cli1, fnum1, NULL, &fsize, NULL, NULL,
1143 if (!NT_STATUS_IS_OK(status)) {
1144 printf("qfileinfo failed (%s)\n", nt_errstr(status));
1148 if (fsize == sizeof(buf))
1149 printf("readwritelarge_internal test 1 succeeded (size = %lx)\n",
1150 (unsigned long)fsize);
1152 printf("readwritelarge_internal test 1 failed (size = %lx)\n",
1153 (unsigned long)fsize);
1157 status = cli_close(cli1, fnum1);
1158 if (!NT_STATUS_IS_OK(status)) {
1159 printf("close failed (%s)\n", nt_errstr(status));
1163 status = cli_unlink(cli1, lockfname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1164 if (!NT_STATUS_IS_OK(status)) {
1165 printf("unlink failed (%s)\n", nt_errstr(status));
1169 status = cli_openx(cli1, lockfname, O_RDWR | O_CREAT | O_EXCL,
1171 if (!NT_STATUS_IS_OK(status)) {
1172 printf("open read/write of %s failed (%s)\n", lockfname, nt_errstr(status));
1176 cli_smbwrite(cli1, fnum1, buf, 0, sizeof(buf), NULL);
1178 status = cli_qfileinfo_basic(cli1, fnum1, NULL, &fsize, NULL, NULL,
1180 if (!NT_STATUS_IS_OK(status)) {
1181 printf("qfileinfo failed (%s)\n", nt_errstr(status));
1185 if (fsize == sizeof(buf))
1186 printf("readwritelarge_internal test 2 succeeded (size = %lx)\n",
1187 (unsigned long)fsize);
1189 printf("readwritelarge_internal test 2 failed (size = %lx)\n",
1190 (unsigned long)fsize);
1194 status = cli_close(cli1, fnum1);
1195 if (!NT_STATUS_IS_OK(status)) {
1196 printf("close failed (%s)\n", nt_errstr(status));
1200 if (!torture_close_connection(cli1)) {
1206 static bool run_readwritelarge(int dummy)
1208 return run_readwritelarge_internal();
1211 static bool run_readwritelarge_signtest(int dummy)
1214 signing_state = SMB_SIGNING_REQUIRED;
1215 ret = run_readwritelarge_internal();
1216 signing_state = SMB_SIGNING_DEFAULT;
1223 #define ival(s) strtol(s, NULL, 0)
1225 /* run a test that simulates an approximate netbench client load */
1226 static bool run_netbench(int client)
1228 struct cli_state *cli;
1233 const char *params[20];
1234 bool correct = True;
1240 smbXcli_conn_set_sockopt(cli->conn, sockops);
1244 slprintf(cname,sizeof(cname)-1, "client%d", client);
1246 f = fopen(client_txt, "r");
1253 while (fgets(line, sizeof(line)-1, f)) {
1257 line[strlen(line)-1] = 0;
1259 /* printf("[%d] %s\n", line_count, line); */
1261 all_string_sub(line,"client1", cname, sizeof(line));
1263 /* parse the command parameters */
1264 params[0] = strtok_r(line, " ", &saveptr);
1266 while (params[i]) params[++i] = strtok_r(NULL, " ", &saveptr);
1270 if (i < 2) continue;
1272 if (!strncmp(params[0],"SMB", 3)) {
1273 printf("ERROR: You are using a dbench 1 load file\n");
1277 if (!strcmp(params[0],"NTCreateX")) {
1278 nb_createx(params[1], ival(params[2]), ival(params[3]),
1280 } else if (!strcmp(params[0],"Close")) {
1281 nb_close(ival(params[1]));
1282 } else if (!strcmp(params[0],"Rename")) {
1283 nb_rename(params[1], params[2]);
1284 } else if (!strcmp(params[0],"Unlink")) {
1285 nb_unlink(params[1]);
1286 } else if (!strcmp(params[0],"Deltree")) {
1287 nb_deltree(params[1]);
1288 } else if (!strcmp(params[0],"Rmdir")) {
1289 nb_rmdir(params[1]);
1290 } else if (!strcmp(params[0],"QUERY_PATH_INFORMATION")) {
1291 nb_qpathinfo(params[1]);
1292 } else if (!strcmp(params[0],"QUERY_FILE_INFORMATION")) {
1293 nb_qfileinfo(ival(params[1]));
1294 } else if (!strcmp(params[0],"QUERY_FS_INFORMATION")) {
1295 nb_qfsinfo(ival(params[1]));
1296 } else if (!strcmp(params[0],"FIND_FIRST")) {
1297 nb_findfirst(params[1]);
1298 } else if (!strcmp(params[0],"WriteX")) {
1299 nb_writex(ival(params[1]),
1300 ival(params[2]), ival(params[3]), ival(params[4]));
1301 } else if (!strcmp(params[0],"ReadX")) {
1302 nb_readx(ival(params[1]),
1303 ival(params[2]), ival(params[3]), ival(params[4]));
1304 } else if (!strcmp(params[0],"Flush")) {
1305 nb_flush(ival(params[1]));
1307 printf("Unknown operation %s\n", params[0]);
1315 if (!torture_close_connection(cli)) {
1323 /* run a test that simulates an approximate netbench client load */
1324 static bool run_nbench(int dummy)
1327 bool correct = True;
1329 nbio_shmem(torture_nprocs);
1333 signal(SIGALRM, nb_alarm);
1335 t = create_procs(run_netbench, &correct);
1338 printf("\nThroughput %g MB/sec\n",
1339 1.0e-6 * nbio_total() / t);
1345 This test checks for two things:
1347 1) correct support for retaining locks over a close (ie. the server
1348 must not use posix semantics)
1349 2) support for lock timeouts
1351 static bool run_locktest1(int dummy)
1353 struct cli_state *cli1, *cli2;
1354 const char *fname = "\\lockt1.lck";
1355 uint16_t fnum1, fnum2, fnum3;
1357 unsigned lock_timeout;
1360 if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
1363 smbXcli_conn_set_sockopt(cli1->conn, sockops);
1364 smbXcli_conn_set_sockopt(cli2->conn, sockops);
1366 printf("starting locktest1\n");
1368 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1370 status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
1372 if (!NT_STATUS_IS_OK(status)) {
1373 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
1377 status = cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum2);
1378 if (!NT_STATUS_IS_OK(status)) {
1379 printf("open2 of %s failed (%s)\n", fname, nt_errstr(status));
1383 status = cli_openx(cli2, fname, O_RDWR, DENY_NONE, &fnum3);
1384 if (!NT_STATUS_IS_OK(status)) {
1385 printf("open3 of %s failed (%s)\n", fname, nt_errstr(status));
1389 status = cli_lock32(cli1, fnum1, 0, 4, 0, WRITE_LOCK);
1390 if (!NT_STATUS_IS_OK(status)) {
1391 printf("lock1 failed (%s)\n", nt_errstr(status));
1395 status = cli_lock32(cli2, fnum3, 0, 4, 0, WRITE_LOCK);
1396 if (NT_STATUS_IS_OK(status)) {
1397 printf("lock2 succeeded! This is a locking bug\n");
1400 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1401 NT_STATUS_LOCK_NOT_GRANTED)) {
1406 lock_timeout = (1 + (random() % 20));
1407 printf("Testing lock timeout with timeout=%u\n", lock_timeout);
1409 status = cli_lock32(cli2, fnum3, 0, 4, lock_timeout * 1000, WRITE_LOCK);
1410 if (NT_STATUS_IS_OK(status)) {
1411 printf("lock3 succeeded! This is a locking bug\n");
1414 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1415 NT_STATUS_FILE_LOCK_CONFLICT)) {
1421 if (ABS(t2 - t1) < lock_timeout-1) {
1422 printf("error: This server appears not to support timed lock requests\n");
1425 printf("server slept for %u seconds for a %u second timeout\n",
1426 (unsigned int)(t2-t1), lock_timeout);
1428 status = cli_close(cli1, fnum2);
1429 if (!NT_STATUS_IS_OK(status)) {
1430 printf("close1 failed (%s)\n", nt_errstr(status));
1434 status = cli_lock32(cli2, fnum3, 0, 4, 0, WRITE_LOCK);
1435 if (NT_STATUS_IS_OK(status)) {
1436 printf("lock4 succeeded! This is a locking bug\n");
1439 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1440 NT_STATUS_FILE_LOCK_CONFLICT)) {
1445 status = cli_close(cli1, fnum1);
1446 if (!NT_STATUS_IS_OK(status)) {
1447 printf("close2 failed (%s)\n", nt_errstr(status));
1451 status = cli_close(cli2, fnum3);
1452 if (!NT_STATUS_IS_OK(status)) {
1453 printf("close3 failed (%s)\n", nt_errstr(status));
1457 status = cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1458 if (!NT_STATUS_IS_OK(status)) {
1459 printf("unlink failed (%s)\n", nt_errstr(status));
1464 if (!torture_close_connection(cli1)) {
1468 if (!torture_close_connection(cli2)) {
1472 printf("Passed locktest1\n");
1477 this checks to see if a secondary tconx can use open files from an
1480 static bool run_tcon_test(int dummy)
1482 static struct cli_state *cli;
1483 const char *fname = "\\tcontest.tmp";
1485 uint32_t cnum1, cnum2, cnum3;
1486 struct smbXcli_tcon *orig_tcon = NULL;
1487 char *orig_share = NULL;
1488 uint16_t vuid1, vuid2;
1493 memset(buf, '\0', sizeof(buf));
1495 if (!torture_open_connection(&cli, 0)) {
1498 smbXcli_conn_set_sockopt(cli->conn, sockops);
1500 printf("starting tcontest\n");
1502 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1504 status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
1505 if (!NT_STATUS_IS_OK(status)) {
1506 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
1510 cnum1 = cli_state_get_tid(cli);
1511 vuid1 = cli_state_get_uid(cli);
1513 status = cli_writeall(cli, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
1514 if (!NT_STATUS_IS_OK(status)) {
1515 printf("initial write failed (%s)", nt_errstr(status));
1519 cli_state_save_tcon_share(cli, &orig_tcon, &orig_share);
1521 status = cli_tree_connect_creds(cli, share, "?????", torture_creds);
1522 if (!NT_STATUS_IS_OK(status)) {
1523 printf("%s refused 2nd tree connect (%s)\n", host,
1525 cli_state_restore_tcon_share(cli, orig_tcon, orig_share);
1530 cnum2 = cli_state_get_tid(cli);
1531 cnum3 = MAX(cnum1, cnum2) + 1; /* any invalid number */
1532 vuid2 = cli_state_get_uid(cli) + 1;
1534 /* try a write with the wrong tid */
1535 cli_state_set_tid(cli, cnum2);
1537 status = cli_writeall(cli, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
1538 if (NT_STATUS_IS_OK(status)) {
1539 printf("* server allows write with wrong TID\n");
1542 printf("server fails write with wrong TID : %s\n",
1547 /* try a write with an invalid tid */
1548 cli_state_set_tid(cli, cnum3);
1550 status = cli_writeall(cli, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
1551 if (NT_STATUS_IS_OK(status)) {
1552 printf("* server allows write with invalid TID\n");
1555 printf("server fails write with invalid TID : %s\n",
1559 /* try a write with an invalid vuid */
1560 cli_state_set_uid(cli, vuid2);
1561 cli_state_set_tid(cli, cnum1);
1563 status = cli_writeall(cli, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
1564 if (NT_STATUS_IS_OK(status)) {
1565 printf("* server allows write with invalid VUID\n");
1568 printf("server fails write with invalid VUID : %s\n",
1572 cli_state_set_tid(cli, cnum1);
1573 cli_state_set_uid(cli, vuid1);
1575 status = cli_close(cli, fnum1);
1576 if (!NT_STATUS_IS_OK(status)) {
1577 printf("close failed (%s)\n", nt_errstr(status));
1578 cli_state_restore_tcon_share(cli, orig_tcon, orig_share);
1583 cli_state_set_tid(cli, cnum2);
1585 status = cli_tdis(cli);
1586 if (!NT_STATUS_IS_OK(status)) {
1587 printf("secondary tdis failed (%s)\n", nt_errstr(status));
1588 cli_state_restore_tcon_share(cli, orig_tcon, orig_share);
1593 cli_state_restore_tcon_share(cli, orig_tcon, orig_share);
1595 cli_state_set_tid(cli, cnum1);
1597 if (!torture_close_connection(cli)) {
1606 checks for old style tcon support
1608 static bool run_tcon2_test(int dummy)
1610 static struct cli_state *cli;
1611 uint16_t cnum, max_xmit;
1615 if (!torture_open_connection(&cli, 0)) {
1618 smbXcli_conn_set_sockopt(cli->conn, sockops);
1620 printf("starting tcon2 test\n");
1622 if (asprintf(&service, "\\\\%s\\%s", host, share) == -1) {
1626 status = cli_raw_tcon(cli, service, password, "?????", &max_xmit, &cnum);
1630 if (!NT_STATUS_IS_OK(status)) {
1631 printf("tcon2 failed : %s\n", nt_errstr(status));
1633 printf("tcon OK : max_xmit=%d cnum=%d\n",
1634 (int)max_xmit, (int)cnum);
1637 if (!torture_close_connection(cli)) {
1641 printf("Passed tcon2 test\n");
1645 static bool tcon_devtest(struct cli_state *cli,
1646 const char *myshare, const char *devtype,
1647 const char *return_devtype,
1648 NTSTATUS expected_error)
1653 status = cli_tree_connect_creds(cli, myshare, devtype, torture_creds);
1655 if (NT_STATUS_IS_OK(expected_error)) {
1656 if (NT_STATUS_IS_OK(status)) {
1657 if (return_devtype != NULL &&
1658 strequal(cli->dev, return_devtype)) {
1661 printf("tconX to share %s with type %s "
1662 "succeeded but returned the wrong "
1663 "device type (got [%s] but should have got [%s])\n",
1664 myshare, devtype, cli->dev, return_devtype);
1668 printf("tconX to share %s with type %s "
1669 "should have succeeded but failed\n",
1675 if (NT_STATUS_IS_OK(status)) {
1676 printf("tconx to share %s with type %s "
1677 "should have failed but succeeded\n",
1681 if (NT_STATUS_EQUAL(status, expected_error)) {
1684 printf("Returned unexpected error\n");
1693 checks for correct tconX support
1695 static bool run_tcon_devtype_test(int dummy)
1697 static struct cli_state *cli1 = NULL;
1698 int flags = CLI_FULL_CONNECTION_FORCE_SMB1;
1702 status = cli_full_connection_creds(&cli1,
1708 NULL, /* service_type */
1712 if (!NT_STATUS_IS_OK(status)) {
1713 printf("could not open connection\n");
1717 if (!tcon_devtest(cli1, "IPC$", "A:", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1720 if (!tcon_devtest(cli1, "IPC$", "?????", "IPC", NT_STATUS_OK))
1723 if (!tcon_devtest(cli1, "IPC$", "LPT:", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1726 if (!tcon_devtest(cli1, "IPC$", "IPC", "IPC", NT_STATUS_OK))
1729 if (!tcon_devtest(cli1, "IPC$", "FOOBA", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1732 if (!tcon_devtest(cli1, share, "A:", "A:", NT_STATUS_OK))
1735 if (!tcon_devtest(cli1, share, "?????", "A:", NT_STATUS_OK))
1738 if (!tcon_devtest(cli1, share, "LPT:", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1741 if (!tcon_devtest(cli1, share, "IPC", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1744 if (!tcon_devtest(cli1, share, "FOOBA", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1750 printf("Passed tcondevtest\n");
1757 This test checks that
1759 1) the server supports multiple locking contexts on the one SMB
1760 connection, distinguished by PID.
1762 2) the server correctly fails overlapping locks made by the same PID (this
1763 goes against POSIX behaviour, which is why it is tricky to implement)
1765 3) the server denies unlock requests by an incorrect client PID
1767 static bool run_locktest2(int dummy)
1769 static struct cli_state *cli;
1770 const char *fname = "\\lockt2.lck";
1771 uint16_t fnum1, fnum2, fnum3;
1772 bool correct = True;
1775 if (!torture_open_connection(&cli, 0)) {
1779 smbXcli_conn_set_sockopt(cli->conn, sockops);
1781 printf("starting locktest2\n");
1783 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1787 status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
1788 if (!NT_STATUS_IS_OK(status)) {
1789 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
1793 status = cli_openx(cli, fname, O_RDWR, DENY_NONE, &fnum2);
1794 if (!NT_STATUS_IS_OK(status)) {
1795 printf("open2 of %s failed (%s)\n", fname, nt_errstr(status));
1801 status = cli_openx(cli, fname, O_RDWR, DENY_NONE, &fnum3);
1802 if (!NT_STATUS_IS_OK(status)) {
1803 printf("open3 of %s failed (%s)\n", fname, nt_errstr(status));
1809 status = cli_lock32(cli, fnum1, 0, 4, 0, WRITE_LOCK);
1810 if (!NT_STATUS_IS_OK(status)) {
1811 printf("lock1 failed (%s)\n", nt_errstr(status));
1815 status = cli_lock32(cli, fnum1, 0, 4, 0, WRITE_LOCK);
1816 if (NT_STATUS_IS_OK(status)) {
1817 printf("WRITE lock1 succeeded! This is a locking bug\n");
1820 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1821 NT_STATUS_LOCK_NOT_GRANTED)) {
1826 status = cli_lock32(cli, fnum2, 0, 4, 0, WRITE_LOCK);
1827 if (NT_STATUS_IS_OK(status)) {
1828 printf("WRITE lock2 succeeded! This is a locking bug\n");
1831 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1832 NT_STATUS_LOCK_NOT_GRANTED)) {
1837 status = cli_lock32(cli, fnum2, 0, 4, 0, READ_LOCK);
1838 if (NT_STATUS_IS_OK(status)) {
1839 printf("READ lock2 succeeded! This is a locking bug\n");
1842 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1843 NT_STATUS_FILE_LOCK_CONFLICT)) {
1848 status = cli_lock32(cli, fnum1, 100, 4, 0, WRITE_LOCK);
1849 if (!NT_STATUS_IS_OK(status)) {
1850 printf("lock at 100 failed (%s)\n", nt_errstr(status));
1853 if (NT_STATUS_IS_OK(cli_unlock(cli, fnum1, 100, 4))) {
1854 printf("unlock at 100 succeeded! This is a locking bug\n");
1858 status = cli_unlock(cli, fnum1, 0, 4);
1859 if (NT_STATUS_IS_OK(status)) {
1860 printf("unlock1 succeeded! This is a locking bug\n");
1863 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1864 NT_STATUS_RANGE_NOT_LOCKED)) {
1869 status = cli_unlock(cli, fnum1, 0, 8);
1870 if (NT_STATUS_IS_OK(status)) {
1871 printf("unlock2 succeeded! This is a locking bug\n");
1874 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1875 NT_STATUS_RANGE_NOT_LOCKED)) {
1880 status = cli_lock32(cli, fnum3, 0, 4, 0, WRITE_LOCK);
1881 if (NT_STATUS_IS_OK(status)) {
1882 printf("lock3 succeeded! This is a locking bug\n");
1885 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1886 NT_STATUS_LOCK_NOT_GRANTED)) {
1893 status = cli_close(cli, fnum1);
1894 if (!NT_STATUS_IS_OK(status)) {
1895 printf("close1 failed (%s)\n", nt_errstr(status));
1899 status = cli_close(cli, fnum2);
1900 if (!NT_STATUS_IS_OK(status)) {
1901 printf("close2 failed (%s)\n", nt_errstr(status));
1905 status = cli_close(cli, fnum3);
1906 if (!NT_STATUS_IS_OK(status)) {
1907 printf("close3 failed (%s)\n", nt_errstr(status));
1911 if (!torture_close_connection(cli)) {
1915 printf("locktest2 finished\n");
1922 This test checks that
1924 1) the server supports the full offset range in lock requests
1926 static bool run_locktest3(int dummy)
1928 static struct cli_state *cli1, *cli2;
1929 const char *fname = "\\lockt3.lck";
1930 uint16_t fnum1, fnum2;
1933 bool correct = True;
1936 #define NEXT_OFFSET offset += (~(uint32_t)0) / torture_numops
1938 if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
1941 smbXcli_conn_set_sockopt(cli1->conn, sockops);
1942 smbXcli_conn_set_sockopt(cli2->conn, sockops);
1944 printf("starting locktest3\n");
1946 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1948 status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
1950 if (!NT_STATUS_IS_OK(status)) {
1951 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
1955 status = cli_openx(cli2, fname, O_RDWR, DENY_NONE, &fnum2);
1956 if (!NT_STATUS_IS_OK(status)) {
1957 printf("open2 of %s failed (%s)\n", fname, nt_errstr(status));
1961 for (offset=i=0;i<torture_numops;i++) {
1964 status = cli_lock32(cli1, fnum1, offset-1, 1, 0, WRITE_LOCK);
1965 if (!NT_STATUS_IS_OK(status)) {
1966 printf("lock1 %d failed (%s)\n",
1972 status = cli_lock32(cli2, fnum2, offset-2, 1, 0, WRITE_LOCK);
1973 if (!NT_STATUS_IS_OK(status)) {
1974 printf("lock2 %d failed (%s)\n",
1981 for (offset=i=0;i<torture_numops;i++) {
1984 status = cli_lock32(cli1, fnum1, offset-2, 1, 0, WRITE_LOCK);
1985 if (NT_STATUS_IS_OK(status)) {
1986 printf("error: lock1 %d succeeded!\n", i);
1990 status = cli_lock32(cli2, fnum2, offset-1, 1, 0, WRITE_LOCK);
1991 if (NT_STATUS_IS_OK(status)) {
1992 printf("error: lock2 %d succeeded!\n", i);
1996 status = cli_lock32(cli1, fnum1, offset-1, 1, 0, WRITE_LOCK);
1997 if (NT_STATUS_IS_OK(status)) {
1998 printf("error: lock3 %d succeeded!\n", i);
2002 status = cli_lock32(cli2, fnum2, offset-2, 1, 0, WRITE_LOCK);
2003 if (NT_STATUS_IS_OK(status)) {
2004 printf("error: lock4 %d succeeded!\n", i);
2009 for (offset=i=0;i<torture_numops;i++) {
2012 status = cli_unlock(cli1, fnum1, offset-1, 1);
2013 if (!NT_STATUS_IS_OK(status)) {
2014 printf("unlock1 %d failed (%s)\n",
2020 status = cli_unlock(cli2, fnum2, offset-2, 1);
2021 if (!NT_STATUS_IS_OK(status)) {
2022 printf("unlock2 %d failed (%s)\n",
2029 status = cli_close(cli1, fnum1);
2030 if (!NT_STATUS_IS_OK(status)) {
2031 printf("close1 failed (%s)\n", nt_errstr(status));
2035 status = cli_close(cli2, fnum2);
2036 if (!NT_STATUS_IS_OK(status)) {
2037 printf("close2 failed (%s)\n", nt_errstr(status));
2041 status = cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2042 if (!NT_STATUS_IS_OK(status)) {
2043 printf("unlink failed (%s)\n", nt_errstr(status));
2047 if (!torture_close_connection(cli1)) {
2051 if (!torture_close_connection(cli2)) {
2055 printf("finished locktest3\n");
2060 static bool test_cli_read(struct cli_state *cli, uint16_t fnum,
2061 char *buf, off_t offset, size_t size,
2062 size_t *nread, size_t expect)
2067 status = cli_read(cli, fnum, buf, offset, size, &l_nread);
2069 if(!NT_STATUS_IS_OK(status)) {
2071 } else if (l_nread != expect) {
2082 #define EXPECTED(ret, v) if ((ret) != (v)) { \
2083 printf("** "); correct = False; \
2087 looks at overlapping locks
2089 static bool run_locktest4(int dummy)
2091 static struct cli_state *cli1, *cli2;
2092 const char *fname = "\\lockt4.lck";
2093 uint16_t fnum1, fnum2, f;
2096 bool correct = True;
2099 if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
2103 smbXcli_conn_set_sockopt(cli1->conn, sockops);
2104 smbXcli_conn_set_sockopt(cli2->conn, sockops);
2106 printf("starting locktest4\n");
2108 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2110 cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
2111 cli_openx(cli2, fname, O_RDWR, DENY_NONE, &fnum2);
2113 memset(buf, 0, sizeof(buf));
2115 status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 0, sizeof(buf),
2117 if (!NT_STATUS_IS_OK(status)) {
2118 printf("Failed to create file: %s\n", nt_errstr(status));
2123 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 4, 0, WRITE_LOCK)) &&
2124 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 2, 4, 0, WRITE_LOCK));
2125 EXPECTED(ret, False);
2126 printf("the same process %s set overlapping write locks\n", ret?"can":"cannot");
2128 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 10, 4, 0, READ_LOCK)) &&
2129 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 12, 4, 0, READ_LOCK));
2130 EXPECTED(ret, True);
2131 printf("the same process %s set overlapping read locks\n", ret?"can":"cannot");
2133 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 20, 4, 0, WRITE_LOCK)) &&
2134 NT_STATUS_IS_OK(cli_lock32(cli2, fnum2, 22, 4, 0, WRITE_LOCK));
2135 EXPECTED(ret, False);
2136 printf("a different connection %s set overlapping write locks\n", ret?"can":"cannot");
2138 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 30, 4, 0, READ_LOCK)) &&
2139 NT_STATUS_IS_OK(cli_lock32(cli2, fnum2, 32, 4, 0, READ_LOCK));
2140 EXPECTED(ret, True);
2141 printf("a different connection %s set overlapping read locks\n", ret?"can":"cannot");
2143 ret = (cli_setpid(cli1, 1),
2144 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 40, 4, 0, WRITE_LOCK))) &&
2145 (cli_setpid(cli1, 2),
2146 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 42, 4, 0, WRITE_LOCK)));
2147 EXPECTED(ret, False);
2148 printf("a different pid %s set overlapping write locks\n", ret?"can":"cannot");
2150 ret = (cli_setpid(cli1, 1),
2151 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 50, 4, 0, READ_LOCK))) &&
2152 (cli_setpid(cli1, 2),
2153 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 52, 4, 0, READ_LOCK)));
2154 EXPECTED(ret, True);
2155 printf("a different pid %s set overlapping read locks\n", ret?"can":"cannot");
2157 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 60, 4, 0, READ_LOCK)) &&
2158 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 60, 4, 0, READ_LOCK));
2159 EXPECTED(ret, True);
2160 printf("the same process %s set the same read lock twice\n", ret?"can":"cannot");
2162 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 70, 4, 0, WRITE_LOCK)) &&
2163 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 70, 4, 0, WRITE_LOCK));
2164 EXPECTED(ret, False);
2165 printf("the same process %s set the same write lock twice\n", ret?"can":"cannot");
2167 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 80, 4, 0, READ_LOCK)) &&
2168 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 80, 4, 0, WRITE_LOCK));
2169 EXPECTED(ret, False);
2170 printf("the same process %s overlay a read lock with a write lock\n", ret?"can":"cannot");
2172 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 90, 4, 0, WRITE_LOCK)) &&
2173 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 90, 4, 0, READ_LOCK));
2174 EXPECTED(ret, True);
2175 printf("the same process %s overlay a write lock with a read lock\n", ret?"can":"cannot");
2177 ret = (cli_setpid(cli1, 1),
2178 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 100, 4, 0, WRITE_LOCK))) &&
2179 (cli_setpid(cli1, 2),
2180 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 100, 4, 0, READ_LOCK)));
2181 EXPECTED(ret, False);
2182 printf("a different pid %s overlay a write lock with a read lock\n", ret?"can":"cannot");
2184 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 110, 4, 0, READ_LOCK)) &&
2185 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 112, 4, 0, READ_LOCK)) &&
2186 NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 110, 6));
2187 EXPECTED(ret, False);
2188 printf("the same process %s coalesce read locks\n", ret?"can":"cannot");
2191 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 120, 4, 0, WRITE_LOCK)) &&
2192 test_cli_read(cli2, fnum2, buf, 120, 4, NULL, 4);
2193 EXPECTED(ret, False);
2194 printf("this server %s strict write locking\n", ret?"doesn't do":"does");
2196 status = cli_lock32(cli1, fnum1, 130, 4, 0, READ_LOCK);
2197 ret = NT_STATUS_IS_OK(status);
2199 status = cli_writeall(cli2, fnum2, 0, (uint8_t *)buf, 130, 4,
2201 ret = NT_STATUS_IS_OK(status);
2203 EXPECTED(ret, False);
2204 printf("this server %s strict read locking\n", ret?"doesn't do":"does");
2207 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 140, 4, 0, READ_LOCK)) &&
2208 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 140, 4, 0, READ_LOCK)) &&
2209 NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 140, 4)) &&
2210 NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 140, 4));
2211 EXPECTED(ret, True);
2212 printf("this server %s do recursive read locking\n", ret?"does":"doesn't");
2215 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 150, 4, 0, WRITE_LOCK)) &&
2216 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 150, 4, 0, READ_LOCK)) &&
2217 NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 150, 4)) &&
2218 test_cli_read(cli2, fnum2, buf, 150, 4, NULL, 4) &&
2219 !(NT_STATUS_IS_OK(cli_writeall(cli2, fnum2, 0, (uint8_t *)buf,
2221 NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 150, 4));
2222 EXPECTED(ret, True);
2223 printf("this server %s do recursive lock overlays\n", ret?"does":"doesn't");
2225 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 160, 4, 0, READ_LOCK)) &&
2226 NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 160, 4)) &&
2227 NT_STATUS_IS_OK(cli_writeall(cli2, fnum2, 0, (uint8_t *)buf,
2229 test_cli_read(cli2, fnum2, buf, 160, 4, NULL, 4);
2230 EXPECTED(ret, True);
2231 printf("the same process %s remove a read lock using write locking\n", ret?"can":"cannot");
2233 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 170, 4, 0, WRITE_LOCK)) &&
2234 NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 170, 4)) &&
2235 NT_STATUS_IS_OK(cli_writeall(cli2, fnum2, 0, (uint8_t *)buf,
2237 test_cli_read(cli2, fnum2, buf, 170, 4, NULL, 4);
2238 EXPECTED(ret, True);
2239 printf("the same process %s remove a write lock using read locking\n", ret?"can":"cannot");
2241 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 190, 4, 0, WRITE_LOCK)) &&
2242 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 190, 4, 0, READ_LOCK)) &&
2243 NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 190, 4)) &&
2244 !NT_STATUS_IS_OK(cli_writeall(cli2, fnum2, 0, (uint8_t *)buf,
2246 test_cli_read(cli2, fnum2, buf, 190, 4, NULL, 4);
2247 EXPECTED(ret, True);
2248 printf("the same process %s remove the first lock first\n", ret?"does":"doesn't");
2250 cli_close(cli1, fnum1);
2251 cli_close(cli2, fnum2);
2252 cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
2253 cli_openx(cli1, fname, O_RDWR, DENY_NONE, &f);
2254 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 8, 0, READ_LOCK)) &&
2255 NT_STATUS_IS_OK(cli_lock32(cli1, f, 0, 1, 0, READ_LOCK)) &&
2256 NT_STATUS_IS_OK(cli_close(cli1, fnum1)) &&
2257 NT_STATUS_IS_OK(cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1)) &&
2258 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 7, 1, 0, WRITE_LOCK));
2260 cli_close(cli1, fnum1);
2261 EXPECTED(ret, True);
2262 printf("the server %s have the NT byte range lock bug\n", !ret?"does":"doesn't");
2265 cli_close(cli1, fnum1);
2266 cli_close(cli2, fnum2);
2267 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2268 torture_close_connection(cli1);
2269 torture_close_connection(cli2);
2271 printf("finished locktest4\n");
2276 looks at lock upgrade/downgrade.
2278 static bool run_locktest5(int dummy)
2280 static struct cli_state *cli1, *cli2;
2281 const char *fname = "\\lockt5.lck";
2282 uint16_t fnum1, fnum2, fnum3;
2285 bool correct = True;
2288 if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
2292 smbXcli_conn_set_sockopt(cli1->conn, sockops);
2293 smbXcli_conn_set_sockopt(cli2->conn, sockops);
2295 printf("starting locktest5\n");
2297 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2299 cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
2300 cli_openx(cli2, fname, O_RDWR, DENY_NONE, &fnum2);
2301 cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum3);
2303 memset(buf, 0, sizeof(buf));
2305 status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 0, sizeof(buf),
2307 if (!NT_STATUS_IS_OK(status)) {
2308 printf("Failed to create file: %s\n", nt_errstr(status));
2313 /* Check for NT bug... */
2314 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 8, 0, READ_LOCK)) &&
2315 NT_STATUS_IS_OK(cli_lock32(cli1, fnum3, 0, 1, 0, READ_LOCK));
2316 cli_close(cli1, fnum1);
2317 cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
2318 status = cli_lock32(cli1, fnum1, 7, 1, 0, WRITE_LOCK);
2319 ret = NT_STATUS_IS_OK(status);
2320 EXPECTED(ret, True);
2321 printf("this server %s the NT locking bug\n", ret ? "doesn't have" : "has");
2322 cli_close(cli1, fnum1);
2323 cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
2324 cli_unlock(cli1, fnum3, 0, 1);
2326 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 4, 0, WRITE_LOCK)) &&
2327 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 1, 1, 0, READ_LOCK));
2328 EXPECTED(ret, True);
2329 printf("the same process %s overlay a write with a read lock\n", ret?"can":"cannot");
2331 status = cli_lock32(cli2, fnum2, 0, 4, 0, READ_LOCK);
2332 ret = NT_STATUS_IS_OK(status);
2333 EXPECTED(ret, False);
2335 printf("a different process %s get a read lock on the first process lock stack\n", ret?"can":"cannot");
2337 /* Unlock the process 2 lock. */
2338 cli_unlock(cli2, fnum2, 0, 4);
2340 status = cli_lock32(cli1, fnum3, 0, 4, 0, READ_LOCK);
2341 ret = NT_STATUS_IS_OK(status);
2342 EXPECTED(ret, False);
2344 printf("the same process on a different fnum %s get a read lock\n", ret?"can":"cannot");
2346 /* Unlock the process 1 fnum3 lock. */
2347 cli_unlock(cli1, fnum3, 0, 4);
2349 /* Stack 2 more locks here. */
2350 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 4, 0, READ_LOCK)) &&
2351 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 4, 0, READ_LOCK));
2353 EXPECTED(ret, True);
2354 printf("the same process %s stack read locks\n", ret?"can":"cannot");
2356 /* Unlock the first process lock, then check this was the WRITE lock that was
2359 ret = NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 0, 4)) &&
2360 NT_STATUS_IS_OK(cli_lock32(cli2, fnum2, 0, 4, 0, READ_LOCK));
2362 EXPECTED(ret, True);
2363 printf("the first unlock removes the %s lock\n", ret?"WRITE":"READ");
2365 /* Unlock the process 2 lock. */
2366 cli_unlock(cli2, fnum2, 0, 4);
2368 /* We should have 3 stacked locks here. Ensure we need to do 3 unlocks. */
2370 ret = NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 1, 1)) &&
2371 NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 0, 4)) &&
2372 NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 0, 4));
2374 EXPECTED(ret, True);
2375 printf("the same process %s unlock the stack of 4 locks\n", ret?"can":"cannot");
2377 /* Ensure the next unlock fails. */
2378 ret = NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 0, 4));
2379 EXPECTED(ret, False);
2380 printf("the same process %s count the lock stack\n", !ret?"can":"cannot");
2382 /* Ensure connection 2 can get a write lock. */
2383 status = cli_lock32(cli2, fnum2, 0, 4, 0, WRITE_LOCK);
2384 ret = NT_STATUS_IS_OK(status);
2385 EXPECTED(ret, True);
2387 printf("a different process %s get a write lock on the unlocked stack\n", ret?"can":"cannot");
2391 cli_close(cli1, fnum1);
2392 cli_close(cli2, fnum2);
2393 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2394 if (!torture_close_connection(cli1)) {
2397 if (!torture_close_connection(cli2)) {
2401 printf("finished locktest5\n");
2407 tries the unusual lockingX locktype bits
2409 static bool run_locktest6(int dummy)
2411 static struct cli_state *cli;
2412 const char *fname[1] = { "\\lock6.txt" };
2417 if (!torture_open_connection(&cli, 0)) {
2421 smbXcli_conn_set_sockopt(cli->conn, sockops);
2423 printf("starting locktest6\n");
2426 printf("Testing %s\n", fname[i]);
2428 cli_unlink(cli, fname[i], FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2430 cli_openx(cli, fname[i], O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
2431 status = cli_locktype(cli, fnum, 0, 8, 0, LOCKING_ANDX_CHANGE_LOCKTYPE);
2432 cli_close(cli, fnum);
2433 printf("CHANGE_LOCKTYPE gave %s\n", nt_errstr(status));
2435 cli_openx(cli, fname[i], O_RDWR, DENY_NONE, &fnum);
2436 status = cli_locktype(cli, fnum, 0, 8, 0, LOCKING_ANDX_CANCEL_LOCK);
2437 cli_close(cli, fnum);
2438 printf("CANCEL_LOCK gave %s\n", nt_errstr(status));
2440 cli_unlink(cli, fname[i], FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2443 torture_close_connection(cli);
2445 printf("finished locktest6\n");
2449 static bool run_locktest7(int dummy)
2451 struct cli_state *cli1;
2452 const char *fname = "\\lockt7.lck";
2455 bool correct = False;
2459 if (!torture_open_connection(&cli1, 0)) {
2463 smbXcli_conn_set_sockopt(cli1->conn, sockops);
2465 printf("starting locktest7\n");
2467 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2469 cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
2471 memset(buf, 0, sizeof(buf));
2473 status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 0, sizeof(buf),
2475 if (!NT_STATUS_IS_OK(status)) {
2476 printf("Failed to create file: %s\n", nt_errstr(status));
2480 cli_setpid(cli1, 1);
2482 status = cli_lock32(cli1, fnum1, 130, 4, 0, READ_LOCK);
2483 if (!NT_STATUS_IS_OK(status)) {
2484 printf("Unable to apply read lock on range 130:4, "
2485 "error was %s\n", nt_errstr(status));
2488 printf("pid1 successfully locked range 130:4 for READ\n");
2491 status = cli_read(cli1, fnum1, buf, 130, 4, &nread);
2492 if (!NT_STATUS_IS_OK(status)) {
2493 printf("pid1 unable to read the range 130:4, error was %s\n",
2496 } else if (nread != 4) {
2497 printf("pid1 unable to read the range 130:4, "
2498 "recv %ld req %d\n", (unsigned long)nread, 4);
2501 printf("pid1 successfully read the range 130:4\n");
2504 status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
2505 if (!NT_STATUS_IS_OK(status)) {
2506 printf("pid1 unable to write to the range 130:4, error was "
2507 "%s\n", nt_errstr(status));
2508 if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
2509 printf("Incorrect error (should be NT_STATUS_FILE_LOCK_CONFLICT)\n");
2513 printf("pid1 successfully wrote to the range 130:4 (should be denied)\n");
2517 cli_setpid(cli1, 2);
2519 status = cli_read(cli1, fnum1, buf, 130, 4, &nread);
2520 if (!NT_STATUS_IS_OK(status)) {
2521 printf("pid2 unable to read the range 130:4, error was %s\n",
2524 } else if (nread != 4) {
2525 printf("pid2 unable to read the range 130:4, "
2526 "recv %ld req %d\n", (unsigned long)nread, 4);
2529 printf("pid2 successfully read the range 130:4\n");
2532 status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
2533 if (!NT_STATUS_IS_OK(status)) {
2534 printf("pid2 unable to write to the range 130:4, error was "
2535 "%s\n", nt_errstr(status));
2536 if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
2537 printf("Incorrect error (should be NT_STATUS_FILE_LOCK_CONFLICT)\n");
2541 printf("pid2 successfully wrote to the range 130:4 (should be denied)\n");
2545 cli_setpid(cli1, 1);
2546 cli_unlock(cli1, fnum1, 130, 4);
2548 status = cli_lock32(cli1, fnum1, 130, 4, 0, WRITE_LOCK);
2549 if (!NT_STATUS_IS_OK(status)) {
2550 printf("Unable to apply write lock on range 130:4, error was %s\n", nt_errstr(status));
2553 printf("pid1 successfully locked range 130:4 for WRITE\n");
2556 status = cli_read(cli1, fnum1, buf, 130, 4, &nread);
2557 if (!NT_STATUS_IS_OK(status)) {
2558 printf("pid1 unable to read the range 130:4, error was %s\n",
2561 } else if (nread != 4) {
2562 printf("pid1 unable to read the range 130:4, "
2563 "recv %ld req %d\n", (unsigned long)nread, 4);
2566 printf("pid1 successfully read the range 130:4\n");
2569 status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
2570 if (!NT_STATUS_IS_OK(status)) {
2571 printf("pid1 unable to write to the range 130:4, error was "
2572 "%s\n", nt_errstr(status));
2575 printf("pid1 successfully wrote to the range 130:4\n");
2578 cli_setpid(cli1, 2);
2580 status = cli_read(cli1, fnum1, buf, 130, 4, &nread);
2581 if (!NT_STATUS_IS_OK(status)) {
2582 printf("pid2 unable to read the range 130:4, error was "
2583 "%s\n", nt_errstr(status));
2584 if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
2585 printf("Incorrect error (should be NT_STATUS_FILE_LOCK_CONFLICT)\n");
2589 printf("pid2 successfully read the range 130:4 (should be denied) recv %ld\n",
2590 (unsigned long)nread);
2594 status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
2595 if (!NT_STATUS_IS_OK(status)) {
2596 printf("pid2 unable to write to the range 130:4, error was "
2597 "%s\n", nt_errstr(status));
2598 if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
2599 printf("Incorrect error (should be NT_STATUS_FILE_LOCK_CONFLICT)\n");
2603 printf("pid2 successfully wrote to the range 130:4 (should be denied)\n");
2607 cli_unlock(cli1, fnum1, 130, 0);
2611 cli_close(cli1, fnum1);
2612 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2613 torture_close_connection(cli1);
2615 printf("finished locktest7\n");
2620 * This demonstrates a problem with our use of GPFS share modes: A file
2621 * descriptor sitting in the pending close queue holding a GPFS share mode
2622 * blocks opening a file another time. Happens with Word 2007 temp files.
2623 * With "posix locking = yes" and "gpfs:sharemodes = yes" enabled, the third
2624 * open is denied with NT_STATUS_SHARING_VIOLATION.
2627 static bool run_locktest8(int dummy)
2629 struct cli_state *cli1;
2630 const char *fname = "\\lockt8.lck";
2631 uint16_t fnum1, fnum2;
2633 bool correct = False;
2636 if (!torture_open_connection(&cli1, 0)) {
2640 smbXcli_conn_set_sockopt(cli1->conn, sockops);
2642 printf("starting locktest8\n");
2644 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2646 status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_WRITE,
2648 if (!NT_STATUS_IS_OK(status)) {
2649 d_fprintf(stderr, "cli_openx returned %s\n", nt_errstr(status));
2653 memset(buf, 0, sizeof(buf));
2655 status = cli_openx(cli1, fname, O_RDONLY, DENY_NONE, &fnum2);
2656 if (!NT_STATUS_IS_OK(status)) {
2657 d_fprintf(stderr, "cli_openx second time returned %s\n",
2662 status = cli_lock32(cli1, fnum2, 1, 1, 0, READ_LOCK);
2663 if (!NT_STATUS_IS_OK(status)) {
2664 printf("Unable to apply read lock on range 1:1, error was "
2665 "%s\n", nt_errstr(status));
2669 status = cli_close(cli1, fnum1);
2670 if (!NT_STATUS_IS_OK(status)) {
2671 d_fprintf(stderr, "cli_close(fnum1) %s\n", nt_errstr(status));
2675 status = cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
2676 if (!NT_STATUS_IS_OK(status)) {
2677 d_fprintf(stderr, "cli_openx third time returned %s\n",
2685 cli_close(cli1, fnum1);
2686 cli_close(cli1, fnum2);
2687 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2688 torture_close_connection(cli1);
2690 printf("finished locktest8\n");
2695 * This test is designed to be run in conjunction with
2696 * external NFS or POSIX locks taken in the filesystem.
2697 * It checks that the smbd server will block until the
2698 * lock is released and then acquire it. JRA.
2701 static bool got_alarm;
2702 static struct cli_state *alarm_cli;
2704 static void alarm_handler(int dummy)
2709 static void alarm_handler_parent(int dummy)
2711 smbXcli_conn_disconnect(alarm_cli->conn, NT_STATUS_LOCAL_DISCONNECT);
2714 static void do_local_lock(const char *fname, int read_fd, int write_fd)
2719 const char *local_pathname = NULL;
2722 local_pathname = talloc_asprintf(talloc_tos(),
2723 "%s/%s", local_path, fname);
2724 if (!local_pathname) {
2725 printf("child: alloc fail\n");
2729 unlink(local_pathname);
2730 fd = open(local_pathname, O_RDWR|O_CREAT, 0666);
2732 printf("child: open of %s failed %s.\n",
2733 local_pathname, strerror(errno));
2737 /* Now take a fcntl lock. */
2738 lock.l_type = F_WRLCK;
2739 lock.l_whence = SEEK_SET;
2742 lock.l_pid = getpid();
2744 ret = fcntl(fd,F_SETLK,&lock);
2746 printf("child: failed to get lock 0:4 on file %s. Error %s\n",
2747 local_pathname, strerror(errno));
2750 printf("child: got lock 0:4 on file %s.\n",
2755 CatchSignal(SIGALRM, alarm_handler);
2757 /* Signal the parent. */
2758 if (write(write_fd, &c, 1) != 1) {
2759 printf("child: start signal fail %s.\n",
2766 /* Wait for the parent to be ready. */
2767 if (read(read_fd, &c, 1) != 1) {
2768 printf("child: reply signal fail %s.\n",
2776 printf("child: released lock 0:4 on file %s.\n",
2782 static bool _run_locktest9X(const char *fname, int timeout)
2784 struct cli_state *cli1;
2785 char *fpath = talloc_asprintf(talloc_tos(), "\\%s", fname);
2787 bool correct = False;
2788 int pipe_in[2], pipe_out[2];
2792 struct timeval start;
2796 printf("starting locktest9X: %s\n", fname);
2798 if (local_path == NULL) {
2799 d_fprintf(stderr, "locktest9X must be given a local path via -l <localpath>\n");
2803 if (pipe(pipe_in) == -1 || pipe(pipe_out) == -1) {
2808 if (child_pid == -1) {
2812 if (child_pid == 0) {
2814 do_local_lock(fname, pipe_out[0], pipe_in[1]);
2824 ret = read(pipe_in[0], &c, 1);
2826 d_fprintf(stderr, "failed to read start signal from child. %s\n",
2831 if (!torture_open_connection(&cli1, 0)) {
2835 smbXcli_conn_set_sockopt(cli1->conn, sockops);
2837 status = cli_openx(cli1, fpath, O_RDWR, DENY_NONE,
2839 if (!NT_STATUS_IS_OK(status)) {
2840 d_fprintf(stderr, "cli_openx returned %s\n", nt_errstr(status));
2844 /* Ensure the child has the lock. */
2845 status = cli_lock32(cli1, fnum, 0, 4, 0, WRITE_LOCK);
2846 if (NT_STATUS_IS_OK(status)) {
2847 d_fprintf(stderr, "Got the lock on range 0:4 - this should not happen !\n");
2850 d_printf("Child has the lock.\n");
2853 /* Tell the child to wait 5 seconds then exit. */
2854 ret = write(pipe_out[1], &c, 1);
2856 d_fprintf(stderr, "failed to send exit signal to child. %s\n",
2861 /* Wait 20 seconds for the lock. */
2863 CatchSignal(SIGALRM, alarm_handler_parent);
2866 start = timeval_current();
2868 status = cli_lock32(cli1, fnum, 0, 4, timeout, WRITE_LOCK);
2869 if (!NT_STATUS_IS_OK(status)) {
2870 d_fprintf(stderr, "Unable to apply write lock on range 0:4, error was "
2871 "%s\n", nt_errstr(status));
2876 seconds = timeval_elapsed(&start);
2878 printf("Parent got the lock after %.2f seconds.\n",
2881 status = cli_close(cli1, fnum);
2882 if (!NT_STATUS_IS_OK(status)) {
2883 d_fprintf(stderr, "cli_close(fnum1) %s\n", nt_errstr(status));
2890 cli_close(cli1, fnum);
2891 torture_close_connection(cli1);
2895 printf("finished locktest9X: %s\n", fname);
2899 static bool run_locktest9a(int dummy)
2901 return _run_locktest9X("lock9a.dat", -1);
2904 static bool run_locktest9b(int dummy)
2906 return _run_locktest9X("lock9b.dat", 10000);
2909 struct locktest10_state {
2914 static void locktest10_lockingx_done(struct tevent_req *subreq);
2915 static void locktest10_read_andx_done(struct tevent_req *subreq);
2917 static bool run_locktest10(int dummy)
2919 struct tevent_context *ev = NULL;
2920 struct cli_state *cli1 = NULL;
2921 struct cli_state *cli2 = NULL;
2922 struct smb1_lock_element lck = { 0 };
2923 struct tevent_req *reqs[2] = { NULL };
2924 struct tevent_req *smbreqs[2] = { NULL };
2925 const char fname[] = "\\lockt10.lck";
2926 uint16_t fnum1, fnum2;
2930 struct locktest10_state state = { .ok = true };
2933 printf("starting locktest10\n");
2935 ev = samba_tevent_context_init(NULL);
2937 d_fprintf(stderr, "samba_tevent_context_init failed\n");
2941 ok = torture_open_connection(&cli1, 0);
2945 smbXcli_conn_set_sockopt(cli1->conn, sockops);
2947 ok = torture_open_connection(&cli2, 1);
2951 smbXcli_conn_set_sockopt(cli2->conn, sockops);
2953 status = cli_openx(cli1, fname, O_CREAT|O_RDWR, DENY_NONE, &fnum1);
2954 if (!NT_STATUS_IS_OK(status)) {
2956 "cli_openx failed: %s\n",
2961 status = cli_writeall(cli1, fnum1, 0, &data, 0, sizeof(data), NULL);
2962 if (!NT_STATUS_IS_OK(status)) {
2964 "cli_writeall failed: %s\n",
2969 status = cli_openx(cli2, fname, O_CREAT|O_RDWR, DENY_NONE, &fnum2);
2970 if (!NT_STATUS_IS_OK(status)) {
2972 "cli_openx failed: %s\n",
2977 status = cli_locktype(
2978 cli2, fnum2, 0, 1, 0, LOCKING_ANDX_EXCLUSIVE_LOCK);
2979 if (!NT_STATUS_IS_OK(status)) {
2981 "cli_locktype failed: %s\n",
2986 lck = (struct smb1_lock_element) {
2987 .pid = cli_getpid(cli1), .offset = 0, .length = 1,
2990 reqs[0] = cli_lockingx_create(
2992 ev, /* tevent_context */
2995 LOCKING_ANDX_EXCLUSIVE_LOCK, /* typeoflock */
2996 0, /* newoplocklevel */
2998 0, /* num_unlocks */
3002 &smbreqs[0]); /* psmbreq */
3003 if (reqs[0] == NULL) {
3004 d_fprintf(stderr, "cli_lockingx_create failed\n");
3007 tevent_req_set_callback(reqs[0], locktest10_lockingx_done, &state);
3009 reqs[1] = cli_read_andx_create(
3016 &smbreqs[1]); /* psmbreq */
3017 if (reqs[1] == NULL) {
3018 d_fprintf(stderr, "cli_read_andx_create failed\n");
3021 tevent_req_set_callback(reqs[1], locktest10_read_andx_done, &state);
3023 status = smb1cli_req_chain_submit(smbreqs, ARRAY_SIZE(smbreqs));
3024 if (!NT_STATUS_IS_OK(status)) {
3026 "smb1cli_req_chain_submit failed: %s\n",
3031 while (!state.done) {
3032 tevent_loop_once(ev);
3035 torture_close_connection(cli1);
3044 static void locktest10_lockingx_done(struct tevent_req *subreq)
3046 struct locktest10_state *state = tevent_req_callback_data_void(subreq);
3049 status = cli_lockingx_recv(subreq);
3050 TALLOC_FREE(subreq);
3052 if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
3053 d_printf("cli_lockingx returned %s\n", nt_errstr(status));
3058 static void locktest10_read_andx_done(struct tevent_req *subreq)
3060 struct locktest10_state *state = tevent_req_callback_data_void(subreq);
3061 ssize_t received = -1;
3062 uint8_t *rcvbuf = NULL;
3065 status = cli_read_andx_recv(subreq, &received, &rcvbuf);
3067 if (!NT_STATUS_EQUAL(status, NT_STATUS_REQUEST_ABORTED)) {
3068 d_printf("cli_read_andx returned %s\n", nt_errstr(status));
3073 TALLOC_FREE(subreq);
3076 static bool run_locktest11(int dummy)
3078 struct cli_state *cli1;
3079 const char *fname = "\\lockt11.lck";
3084 if (!torture_open_connection(&cli1, 0)) {
3088 smbXcli_conn_set_sockopt(cli1->conn, sockops);
3090 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3092 status = cli_openx(cli1, fname, O_CREAT|O_RDWR, DENY_NONE, &fnum);
3093 if (!NT_STATUS_IS_OK(status)) {
3095 "cli_openx returned %s\n",
3101 * Test that LOCKING_ANDX_CANCEL_LOCK without any locks
3102 * returns NT_STATUS_OK
3105 status = cli_lockingx(
3108 LOCKING_ANDX_CANCEL_LOCK, /* typeoflock */
3109 0, /* newoplocklevel */
3111 0, /* num_unlocks */
3116 if (!NT_STATUS_IS_OK(status)) {
3117 d_printf("cli_lockingX returned %s\n", nt_errstr(status));
3123 cli_close(cli1, fnum);
3124 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3129 struct deferred_close_state {
3130 struct tevent_context *ev;
3131 struct cli_state *cli;
3135 static void deferred_close_waited(struct tevent_req *subreq);
3136 static void deferred_close_done(struct tevent_req *subreq);
3138 static struct tevent_req *deferred_close_send(
3139 TALLOC_CTX *mem_ctx,
3140 struct tevent_context *ev,
3142 struct cli_state *cli,
3145 struct tevent_req *req = NULL, *subreq = NULL;
3146 struct deferred_close_state *state = NULL;
3147 struct timeval wakeup_time = timeval_current_ofs(wait_secs, 0);
3149 req = tevent_req_create(
3150 mem_ctx, &state, struct deferred_close_state);
3158 subreq = tevent_wakeup_send(state, state->ev, wakeup_time);
3159 if (tevent_req_nomem(subreq, req)) {
3160 return tevent_req_post(req, ev);
3162 tevent_req_set_callback(subreq, deferred_close_waited, req);
3166 static void deferred_close_waited(struct tevent_req *subreq)
3168 struct tevent_req *req = tevent_req_callback_data(
3169 subreq, struct tevent_req);
3170 struct deferred_close_state *state = tevent_req_data(
3171 req, struct deferred_close_state);
3174 ok = tevent_wakeup_recv(subreq);
3175 TALLOC_FREE(subreq);
3177 tevent_req_oom(req);
3181 subreq = cli_close_send(state, state->ev, state->cli, state->fnum, 0);
3182 if (tevent_req_nomem(subreq, req)) {
3185 tevent_req_set_callback(subreq, deferred_close_done, req);
3188 static void deferred_close_done(struct tevent_req *subreq)
3190 NTSTATUS status = cli_close_recv(subreq);
3191 tevent_req_simple_finish_ntstatus(subreq, status);
3194 static NTSTATUS deferred_close_recv(struct tevent_req *req)
3196 return tevent_req_simple_recv_ntstatus(req);
3199 struct lockread_state {
3200 struct smb1_lock_element lck;
3201 struct tevent_req *reqs[2];
3202 struct tevent_req *smbreqs[2];
3203 NTSTATUS lock_status;
3204 NTSTATUS read_status;
3208 static void lockread_lockingx_done(struct tevent_req *subreq);
3209 static void lockread_read_andx_done(struct tevent_req *subreq);
3211 static struct tevent_req *lockread_send(
3212 TALLOC_CTX *mem_ctx,
3213 struct tevent_context *ev,
3214 struct cli_state *cli,
3217 struct tevent_req *req = NULL;
3218 struct lockread_state *state = NULL;
3221 req = tevent_req_create(mem_ctx, &state, struct lockread_state);
3226 state->lck = (struct smb1_lock_element) {
3227 .pid = cli_getpid(cli), .offset = 0, .length = 1,
3230 state->reqs[0] = cli_lockingx_create(
3232 ev, /* tevent_context */
3235 LOCKING_ANDX_EXCLUSIVE_LOCK, /* typeoflock */
3236 0, /* newoplocklevel */
3237 10000, /* timeout */
3238 0, /* num_unlocks */
3241 &state->lck, /* locks */
3242 &state->smbreqs[0]); /* psmbreq */
3243 if (tevent_req_nomem(state->reqs[0], req)) {
3244 return tevent_req_post(req, ev);
3246 tevent_req_set_callback(
3247 state->reqs[0], lockread_lockingx_done, req);
3249 state->reqs[1] = cli_read_andx_create(
3256 &state->smbreqs[1]); /* psmbreq */
3257 if (tevent_req_nomem(state->reqs[1], req)) {
3258 return tevent_req_post(req, ev);
3260 tevent_req_set_callback(
3261 state->reqs[1], lockread_read_andx_done, req);
3263 status = smb1cli_req_chain_submit(state->smbreqs, 2);
3264 if (tevent_req_nterror(req, status)) {
3265 return tevent_req_post(req, ev);
3270 static void lockread_lockingx_done(struct tevent_req *subreq)
3272 struct tevent_req *req = tevent_req_callback_data(
3273 subreq, struct tevent_req);
3274 struct lockread_state *state = tevent_req_data(
3275 req, struct lockread_state);
3276 state->lock_status = cli_lockingx_recv(subreq);
3277 TALLOC_FREE(subreq);
3279 "lockingx returned %s\n",
3280 nt_errstr(state->lock_status));
3283 static void lockread_read_andx_done(struct tevent_req *subreq)
3285 struct tevent_req *req = tevent_req_callback_data(
3286 subreq, struct tevent_req);
3287 struct lockread_state *state = tevent_req_data(
3288 req, struct lockread_state);
3289 ssize_t received = -1;
3290 uint8_t *rcvbuf = NULL;
3292 state->read_status = cli_read_andx_recv(subreq, &received, &rcvbuf);
3295 "read returned %s\n",
3296 nt_errstr(state->read_status));
3298 if (!NT_STATUS_IS_OK(state->read_status)) {
3299 TALLOC_FREE(subreq);
3300 tevent_req_done(req);
3305 state->readbuf = talloc_memdup(state, rcvbuf, received);
3306 TALLOC_FREE(subreq);
3307 if (tevent_req_nomem(state->readbuf, req)) {
3311 TALLOC_FREE(subreq);
3312 tevent_req_done(req);
3315 static NTSTATUS lockread_recv(
3316 struct tevent_req *req,
3317 NTSTATUS *lock_status,
3318 NTSTATUS *read_status,
3319 TALLOC_CTX *mem_ctx,
3322 struct lockread_state *state = tevent_req_data(
3323 req, struct lockread_state);
3326 if (tevent_req_is_nterror(req, &status)) {
3330 *lock_status = state->lock_status;
3331 *read_status = state->read_status;
3332 if (state->readbuf != NULL) {
3333 *read_buf = talloc_move(mem_ctx, &state->readbuf);
3338 return NT_STATUS_OK;
3341 struct lock12_state {
3345 static void lock12_closed(struct tevent_req *subreq);
3346 static void lock12_read(struct tevent_req *subreq);
3348 static struct tevent_req *lock12_send(
3349 TALLOC_CTX *mem_ctx,
3350 struct tevent_context *ev,
3351 struct cli_state *cli,
3355 struct tevent_req *req = NULL, *subreq = NULL;
3356 struct lock12_state *state = NULL;
3358 req = tevent_req_create(mem_ctx, &state, struct lock12_state);
3363 subreq = deferred_close_send(state, ev, 1, cli, fnum1);
3364 if (tevent_req_nomem(subreq, req)) {
3365 return tevent_req_post(req, ev);
3367 tevent_req_set_callback(subreq, lock12_closed, req);
3369 subreq = lockread_send(state, ev, cli, fnum2);
3370 if (tevent_req_nomem(subreq, req)) {
3371 return tevent_req_post(req, ev);
3373 tevent_req_set_callback(subreq, lock12_read, req);
3378 static void lock12_closed(struct tevent_req *subreq)
3380 struct tevent_req *req = tevent_req_callback_data(
3381 subreq, struct tevent_req);
3384 status = deferred_close_recv(subreq);
3385 TALLOC_FREE(subreq);
3386 DBG_DEBUG("close returned %s\n", nt_errstr(status));
3387 if (tevent_req_nterror(req, status)) {
3392 static void lock12_read(struct tevent_req *subreq)
3394 struct tevent_req *req = tevent_req_callback_data(
3395 subreq, struct tevent_req);
3396 struct lock12_state *state = tevent_req_data(
3397 req, struct lock12_state);
3398 NTSTATUS status, lock_status, read_status;
3399 uint8_t *buf = NULL;
3401 status = lockread_recv(
3402 subreq, &lock_status, &read_status, state, &buf);
3403 TALLOC_FREE(subreq);
3404 if (tevent_req_nterror(req, status) ||
3405 tevent_req_nterror(req, lock_status) ||
3406 tevent_req_nterror(req, read_status)) {
3409 tevent_req_done(req);
3412 static NTSTATUS lock12_recv(struct tevent_req *req)
3417 if (tevent_req_is_nterror(req, &status)) {
3420 return NT_STATUS_OK;
3423 static bool run_locktest12(int dummy)
3425 struct tevent_context *ev = NULL;
3426 struct tevent_req *req = NULL;
3427 struct cli_state *cli = NULL;
3428 const char fname[] = "\\lockt12.lck";
3429 uint16_t fnum1, fnum2;
3435 printf("starting locktest12\n");
3437 ev = samba_tevent_context_init(NULL);
3439 d_fprintf(stderr, "samba_tevent_context_init failed\n");
3443 ok = torture_open_connection(&cli, 0);
3447 smbXcli_conn_set_sockopt(cli->conn, sockops);
3449 status = cli_openx(cli, fname, O_CREAT|O_RDWR, DENY_NONE, &fnum1);
3450 if (!NT_STATUS_IS_OK(status)) {
3452 "cli_openx failed: %s\n",
3457 status = cli_openx(cli, fname, O_CREAT|O_RDWR, DENY_NONE, &fnum2);
3458 if (!NT_STATUS_IS_OK(status)) {
3460 "cli_openx failed: %s\n",
3465 status = cli_writeall(cli, fnum1, 0, &data, 0, sizeof(data), NULL);
3466 if (!NT_STATUS_IS_OK(status)) {
3468 "cli_writeall failed: %s\n",
3473 status = cli_locktype(
3474 cli, fnum1, 0, 1, 0, LOCKING_ANDX_EXCLUSIVE_LOCK);
3475 if (!NT_STATUS_IS_OK(status)) {
3477 "cli_locktype failed: %s\n",
3482 req = lock12_send(ev, ev, cli, fnum1, fnum2);
3484 d_fprintf(stderr, "lock12_send failed\n");
3488 ok = tevent_req_poll_ntstatus(req, ev, &status);
3490 d_fprintf(stderr, "tevent_req_poll_ntstatus failed\n");
3494 if (!NT_STATUS_IS_OK(status)) {
3496 "tevent_req_poll_ntstatus returned %s\n",
3501 status = lock12_recv(req);
3502 if (!NT_STATUS_IS_OK(status)) {
3503 d_fprintf(stderr, "lock12 returned %s\n", nt_errstr(status));
3510 torture_close_connection(cli);
3515 struct lock_ntcancel_state {
3516 struct timeval start;
3517 struct smb1_lock_element lck;
3518 struct tevent_req *subreq;
3521 static void lock_ntcancel_waited(struct tevent_req *subreq);
3522 static void lock_ntcancel_done(struct tevent_req *subreq);
3524 static struct tevent_req *lock_ntcancel_send(
3525 TALLOC_CTX *mem_ctx,
3526 struct tevent_context *ev,
3527 struct cli_state *cli,
3530 struct tevent_req *req = NULL, *subreq = NULL;
3531 struct lock_ntcancel_state *state = NULL;
3533 req = tevent_req_create(mem_ctx, &state, struct lock_ntcancel_state);
3537 state->lck = (struct smb1_lock_element) {
3538 .pid = cli_getpid(cli), .offset = 0, .length = 1,
3540 state->start = timeval_current();
3542 state->subreq = cli_lockingx_send(
3543 state, /* mem_ctx */
3544 ev, /* tevent_context */
3547 LOCKING_ANDX_EXCLUSIVE_LOCK, /* typeoflock */
3548 0, /* newoplocklevel */
3549 10000, /* timeout */
3550 0, /* num_unlocks */
3553 &state->lck); /* locks */
3554 if (tevent_req_nomem(state->subreq, req)) {
3555 return tevent_req_post(req, ev);
3557 tevent_req_set_callback(state->subreq, lock_ntcancel_done, req);
3559 subreq = tevent_wakeup_send(state, ev, timeval_current_ofs(1, 0));
3560 if (tevent_req_nomem(subreq, req)) {
3561 return tevent_req_post(req, ev);
3563 tevent_req_set_callback(subreq, lock_ntcancel_waited, req);
3567 static void lock_ntcancel_waited(struct tevent_req *subreq)
3569 struct tevent_req *req = tevent_req_callback_data(
3570 subreq, struct tevent_req);
3571 struct lock_ntcancel_state *state = tevent_req_data(
3572 req, struct lock_ntcancel_state);
3575 ok = tevent_wakeup_recv(subreq);
3576 TALLOC_FREE(subreq);
3578 tevent_req_oom(req);
3582 ok = tevent_req_cancel(state->subreq);
3584 d_fprintf(stderr, "Could not cancel subreq\n");
3585 tevent_req_oom(req);
3590 static void lock_ntcancel_done(struct tevent_req *subreq)
3592 struct tevent_req *req = tevent_req_callback_data(
3593 subreq, struct tevent_req);
3594 struct lock_ntcancel_state *state = tevent_req_data(
3595 req, struct lock_ntcancel_state);
3599 status = cli_lockingx_recv(subreq);
3600 TALLOC_FREE(subreq);
3602 if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
3603 d_printf("cli_lockingx returned %s\n", nt_errstr(status));
3604 tevent_req_nterror(req, NT_STATUS_UNSUCCESSFUL);
3608 elapsed = timeval_elapsed(&state->start);
3611 d_printf("cli_lockingx was too slow, cancel did not work\n");
3612 tevent_req_nterror(req, NT_STATUS_UNSUCCESSFUL);
3616 tevent_req_done(req);
3619 static NTSTATUS lock_ntcancel_recv(struct tevent_req *req)
3621 return tevent_req_simple_recv_ntstatus(req);
3624 static bool run_locktest13(int dummy)
3626 struct tevent_context *ev = NULL;
3627 struct tevent_req *req = NULL;
3628 struct cli_state *cli = NULL;
3629 const char fname[] = "\\lockt13.lck";
3630 uint16_t fnum1, fnum2;
3636 printf("starting locktest13\n");
3638 ev = samba_tevent_context_init(NULL);
3640 d_fprintf(stderr, "samba_tevent_context_init failed\n");
3644 ok = torture_open_connection(&cli, 0);
3648 smbXcli_conn_set_sockopt(cli->conn, sockops);
3650 status = cli_openx(cli, fname, O_CREAT|O_RDWR, DENY_NONE, &fnum1);
3651 if (!NT_STATUS_IS_OK(status)) {
3653 "cli_openx failed: %s\n",
3658 status = cli_openx(cli, fname, O_CREAT|O_RDWR, DENY_NONE, &fnum2);
3659 if (!NT_STATUS_IS_OK(status)) {
3661 "cli_openx failed: %s\n",
3666 status = cli_writeall(cli, fnum1, 0, &data, 0, sizeof(data), NULL);
3667 if (!NT_STATUS_IS_OK(status)) {
3669 "cli_writeall failed: %s\n",
3674 status = cli_locktype(
3675 cli, fnum1, 0, 1, 0, LOCKING_ANDX_EXCLUSIVE_LOCK);
3676 if (!NT_STATUS_IS_OK(status)) {
3678 "cli_locktype failed: %s\n",
3683 req = lock_ntcancel_send(ev, ev, cli, fnum2);
3685 d_fprintf(stderr, "lock_ntcancel_send failed\n");
3689 ok = tevent_req_poll_ntstatus(req, ev, &status);
3691 d_fprintf(stderr, "tevent_req_poll_ntstatus failed\n");
3695 if (!NT_STATUS_IS_OK(status)) {
3697 "tevent_req_poll_ntstatus returned %s\n",
3702 status = lock_ntcancel_recv(req);
3703 if (!NT_STATUS_IS_OK(status)) {
3705 "lock_ntcancel returned %s\n",
3713 torture_close_connection(cli);
3719 test whether fnums and tids open on one VC are available on another (a major
3722 static bool run_fdpasstest(int dummy)
3724 struct cli_state *cli1, *cli2;
3725 const char *fname = "\\fdpass.tst";
3730 if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
3733 smbXcli_conn_set_sockopt(cli1->conn, sockops);
3734 smbXcli_conn_set_sockopt(cli2->conn, sockops);
3736 printf("starting fdpasstest\n");
3738 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3740 status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
3742 if (!NT_STATUS_IS_OK(status)) {
3743 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
3747 status = cli_writeall(cli1, fnum1, 0, (const uint8_t *)"hello world\n", 0,
3749 if (!NT_STATUS_IS_OK(status)) {
3750 printf("write failed (%s)\n", nt_errstr(status));
3754 cli_state_set_uid(cli2, cli_state_get_uid(cli1));
3755 cli_state_set_tid(cli2, cli_state_get_tid(cli1));
3756 cli_setpid(cli2, cli_getpid(cli1));
3758 if (test_cli_read(cli2, fnum1, buf, 0, 13, NULL, 13)) {
3759 printf("read succeeded! nasty security hole [%s]\n", buf);
3763 cli_close(cli1, fnum1);
3764 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3766 torture_close_connection(cli1);
3767 torture_close_connection(cli2);
3769 printf("finished fdpasstest\n");
3773 static bool run_fdsesstest(int dummy)
3775 struct cli_state *cli;
3777 uint16_t saved_vuid;
3779 uint32_t saved_cnum;
3780 const char *fname = "\\fdsess.tst";
3781 const char *fname1 = "\\fdsess1.tst";
3788 if (!torture_open_connection(&cli, 0))
3790 smbXcli_conn_set_sockopt(cli->conn, sockops);
3792 if (!torture_cli_session_setup2(cli, &new_vuid))
3795 saved_cnum = cli_state_get_tid(cli);
3796 if (!NT_STATUS_IS_OK(cli_tree_connect(cli, share, "?????", NULL)))
3798 new_cnum = cli_state_get_tid(cli);
3799 cli_state_set_tid(cli, saved_cnum);
3801 printf("starting fdsesstest\n");
3803 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3804 cli_unlink(cli, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3806 status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
3807 if (!NT_STATUS_IS_OK(status)) {
3808 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
3812 status = cli_writeall(cli, fnum1, 0, (const uint8_t *)"hello world\n", 0, 13,
3814 if (!NT_STATUS_IS_OK(status)) {
3815 printf("write failed (%s)\n", nt_errstr(status));
3819 saved_vuid = cli_state_get_uid(cli);
3820 cli_state_set_uid(cli, new_vuid);
3822 if (test_cli_read(cli, fnum1, buf, 0, 13, NULL, 13)) {
3823 printf("read succeeded with different vuid! "
3824 "nasty security hole [%s]\n", buf);
3827 /* Try to open a file with different vuid, samba cnum. */
3828 if (NT_STATUS_IS_OK(cli_openx(cli, fname1, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum2))) {
3829 printf("create with different vuid, same cnum succeeded.\n");
3830 cli_close(cli, fnum2);
3831 cli_unlink(cli, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3833 printf("create with different vuid, same cnum failed.\n");
3834 printf("This will cause problems with service clients.\n");
3838 cli_state_set_uid(cli, saved_vuid);
3840 /* Try with same vuid, different cnum. */
3841 cli_state_set_tid(cli, new_cnum);
3843 if (test_cli_read(cli, fnum1, buf, 0, 13, NULL, 13)) {
3844 printf("read succeeded with different cnum![%s]\n", buf);
3848 cli_state_set_tid(cli, saved_cnum);
3849 cli_close(cli, fnum1);
3850 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3852 torture_close_connection(cli);
3854 printf("finished fdsesstest\n");
3859 This test checks that
3861 1) the server does not allow an unlink on a file that is open
3863 static bool run_unlinktest(int dummy)
3865 struct cli_state *cli;
3866 const char *fname = "\\unlink.tst";
3868 bool correct = True;
3871 if (!torture_open_connection(&cli, 0)) {
3875 smbXcli_conn_set_sockopt(cli->conn, sockops);
3877 printf("starting unlink test\n");
3879 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3883 status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
3884 if (!NT_STATUS_IS_OK(status)) {
3885 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
3889 status = cli_unlink(cli, fname,
3890 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3891 if (NT_STATUS_IS_OK(status)) {
3892 printf("error: server allowed unlink on an open file\n");
3895 correct = check_error(__LINE__, status, ERRDOS, ERRbadshare,
3896 NT_STATUS_SHARING_VIOLATION);
3899 cli_close(cli, fnum);
3900 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3902 if (!torture_close_connection(cli)) {
3906 printf("unlink test finished\n");
3913 test how many open files this server supports on the one socket
3915 static bool run_maxfidtest(int dummy)
3917 struct cli_state *cli;
3919 uint16_t fnums[0x11000];
3922 bool correct = True;
3928 printf("failed to connect\n");
3932 smbXcli_conn_set_sockopt(cli->conn, sockops);
3934 for (i=0; i<0x11000; i++) {
3935 slprintf(fname,sizeof(fname)-1,"\\maxfid.%d.%d", i,(int)getpid());
3936 status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_TRUNC, DENY_NONE,
3938 if (!NT_STATUS_IS_OK(status)) {
3939 printf("open of %s failed (%s)\n",
3940 fname, nt_errstr(status));
3941 printf("maximum fnum is %d\n", i);
3949 printf("cleaning up\n");
3951 slprintf(fname,sizeof(fname)-1,"\\maxfid.%d.%d", i,(int)getpid());
3952 cli_close(cli, fnums[i]);
3954 status = cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3955 if (!NT_STATUS_IS_OK(status)) {
3956 printf("unlink of %s failed (%s)\n",
3957 fname, nt_errstr(status));
3964 printf("maxfid test finished\n");
3965 if (!torture_close_connection(cli)) {
3971 /* generate a random buffer */
3972 static void rand_buf(char *buf, int len)
3975 *buf = (char)sys_random();
3980 /* send smb negprot commands, not reading the response */
3981 static bool run_negprot_nowait(int dummy)
3983 struct tevent_context *ev;
3985 struct cli_state *cli;
3986 bool correct = True;
3988 printf("starting negprot nowait test\n");
3990 ev = samba_tevent_context_init(talloc_tos());
3995 if (!(cli = open_nbt_connection())) {
4000 for (i=0;i<50000;i++) {
4001 struct tevent_req *req;
4003 req = smbXcli_negprot_send(
4016 if (!tevent_req_poll(req, ev)) {
4017 d_fprintf(stderr, "tevent_req_poll failed: %s\n",
4025 if (torture_close_connection(cli)) {
4029 printf("finished negprot nowait test\n");
4034 /* send smb negprot commands, not reading the response */
4035 static bool run_bad_nbt_session(int dummy)
4037 struct nmb_name called, calling;
4038 struct sockaddr_storage ss;
4043 printf("starting bad nbt session test\n");
4045 make_nmb_name(&calling, myname, 0x0);
4046 make_nmb_name(&called , host, 0x20);
4048 if (!resolve_name(host, &ss, 0x20, true)) {
4049 d_fprintf(stderr, "Could not resolve name %s\n", host);
4053 status = open_socket_out(&ss, NBT_SMB_PORT, 10000, &fd);
4054 if (!NT_STATUS_IS_OK(status)) {
4055 d_fprintf(stderr, "open_socket_out failed: %s\n",
4060 ret = cli_bad_session_request(fd, &calling, &called);
4063 d_fprintf(stderr, "open_socket_out failed: %s\n",
4068 printf("finished bad nbt session test\n");
4072 /* send random IPC commands */
4073 static bool run_randomipc(int dummy)
4075 char *rparam = NULL;
4077 unsigned int rdrcnt,rprcnt;
4079 int api, param_len, i;
4080 struct cli_state *cli;
4081 bool correct = True;
4084 printf("starting random ipc test\n");
4086 if (!torture_open_connection(&cli, 0)) {
4090 for (i=0;i<count;i++) {
4091 api = sys_random() % 500;
4092 param_len = (sys_random() % 64);
4094 rand_buf(param, param_len);
4099 param, param_len, 8,
4100 NULL, 0, CLI_BUFFER_SIZE,
4104 printf("%d/%d\r", i,count);
4107 printf("%d/%d\n", i, count);
4109 if (!torture_close_connection(cli)) {
4116 printf("finished random ipc test\n");
4123 static void browse_callback(const char *sname, uint32_t stype,
4124 const char *comment, void *state)
4126 printf("\t%20.20s %08x %s\n", sname, stype, comment);
4132 This test checks the browse list code
4135 static bool run_browsetest(int dummy)
4137 static struct cli_state *cli;
4138 bool correct = True;
4140 printf("starting browse test\n");
4142 if (!torture_open_connection(&cli, 0)) {
4146 printf("domain list:\n");
4147 cli_NetServerEnum(cli, cli->server_domain,
4148 SV_TYPE_DOMAIN_ENUM,
4149 browse_callback, NULL);
4151 printf("machine list:\n");
4152 cli_NetServerEnum(cli, cli->server_domain,
4154 browse_callback, NULL);
4156 if (!torture_close_connection(cli)) {
4160 printf("browse test finished\n");
4166 static bool check_attributes(struct cli_state *cli,
4168 uint32_t expected_attrs)
4171 NTSTATUS status = cli_getatr(cli,
4176 if (!NT_STATUS_IS_OK(status)) {
4177 printf("cli_getatr failed with %s\n",
4181 if (attrs != expected_attrs) {
4182 printf("Attributes incorrect 0x%x, should be 0x%x\n",
4183 (unsigned int)attrs,
4184 (unsigned int)expected_attrs);
4191 This checks how the getatr calls works
4193 static bool run_attrtest(int dummy)
4195 struct cli_state *cli;
4198 const char *fname = "\\attrib123456789.tst";
4199 bool correct = True;
4202 printf("starting attrib test\n");
4204 if (!torture_open_connection(&cli, 0)) {
4208 /* Ensure we can't unlink with out-of-range (unknown) attribute. */
4209 status = cli_unlink(cli, fname, 0x20000);
4210 if (!NT_STATUS_EQUAL(status, NT_STATUS_INVALID_PARAMETER)) {
4215 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4216 cli_openx(cli, fname,
4217 O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum);
4218 cli_close(cli, fnum);
4220 status = cli_getatr(cli, fname, NULL, NULL, &t);
4221 if (!NT_STATUS_IS_OK(status)) {
4222 printf("getatr failed (%s)\n", nt_errstr(status));
4226 if (labs(t - time(NULL)) > 60*60*24*10) {
4227 printf("ERROR: SMBgetatr bug. time is %s",
4233 t2 = t-60*60*24; /* 1 day ago */
4235 /* Ensure we can't set with out-of-range (unknown) attribute. */
4236 status = cli_setatr(cli, fname, 0x20000, t2);
4237 if (!NT_STATUS_EQUAL(status, NT_STATUS_INVALID_PARAMETER)) {
4242 status = cli_setatr(cli, fname, 0, t2);
4243 if (!NT_STATUS_IS_OK(status)) {
4244 printf("setatr failed (%s)\n", nt_errstr(status));
4248 status = cli_getatr(cli, fname, NULL, NULL, &t);
4249 if (!NT_STATUS_IS_OK(status)) {
4250 printf("getatr failed (%s)\n", nt_errstr(status));
4255 printf("ERROR: getatr/setatr bug. times are\n%s",
4257 printf("%s", ctime(&t2));
4261 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4263 /* Check cli_setpathinfo_ext() */
4264 /* Re-create the file. */
4265 status = cli_openx(cli, fname,
4266 O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum);
4267 if (!NT_STATUS_IS_OK(status)) {
4268 printf("Failed to recreate %s (%s)\n",
4269 fname, nt_errstr(status));
4272 cli_close(cli, fnum);
4274 status = cli_setpathinfo_ext(
4277 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* create */
4278 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* access */
4279 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* write */
4280 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* change */
4281 FILE_ATTRIBUTE_SYSTEM |
4282 FILE_ATTRIBUTE_HIDDEN |
4283 FILE_ATTRIBUTE_READONLY);
4284 if (!NT_STATUS_IS_OK(status)) {
4285 printf("cli_setpathinfo_ext failed with %s\n",
4290 /* Check attributes are correct. */
4291 correct = check_attributes(cli,
4293 FILE_ATTRIBUTE_SYSTEM |
4294 FILE_ATTRIBUTE_HIDDEN |
4295 FILE_ATTRIBUTE_READONLY);
4296 if (correct == false) {
4300 /* Setting to FILE_ATTRIBUTE_NORMAL should be ignored. */
4301 status = cli_setpathinfo_ext(
4304 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* create */
4305 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* access */
4306 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* write */
4307 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* change */
4308 FILE_ATTRIBUTE_NORMAL);
4309 if (!NT_STATUS_IS_OK(status)) {
4310 printf("cli_setpathinfo_ext failed with %s\n",
4315 /* Check attributes are correct. */
4316 correct = check_attributes(cli,
4318 FILE_ATTRIBUTE_SYSTEM |
4319 FILE_ATTRIBUTE_HIDDEN |
4320 FILE_ATTRIBUTE_READONLY);
4321 if (correct == false) {
4325 /* Setting to (uint16_t)-1 should also be ignored. */
4326 status = cli_setpathinfo_ext(
4329 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* create */
4330 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* access */
4331 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* write */
4332 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* change */
4334 if (!NT_STATUS_IS_OK(status)) {
4335 printf("cli_setpathinfo_ext failed with %s\n",
4340 /* Check attributes are correct. */
4341 correct = check_attributes(cli,
4343 FILE_ATTRIBUTE_SYSTEM |
4344 FILE_ATTRIBUTE_HIDDEN |
4345 FILE_ATTRIBUTE_READONLY);
4346 if (correct == false) {
4350 /* Setting to 0 should clear them all. */
4351 status = cli_setpathinfo_ext(
4354 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* create */
4355 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* access */
4356 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* write */
4357 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* change */
4359 if (!NT_STATUS_IS_OK(status)) {
4360 printf("cli_setpathinfo_ext failed with %s\n",
4365 /* Check attributes are correct. */
4366 correct = check_attributes(cli,
4368 FILE_ATTRIBUTE_NORMAL);
4369 if (correct == false) {
4377 FILE_ATTRIBUTE_SYSTEM |
4378 FILE_ATTRIBUTE_HIDDEN|
4379 FILE_ATTRIBUTE_READONLY);
4381 if (!torture_close_connection(cli)) {
4385 printf("attrib test finished\n");
4390 static NTSTATUS cli_qfilename(
4391 struct cli_state *cli,
4393 TALLOC_CTX *mem_ctx,
4396 uint16_t recv_flags2;
4403 status = cli_qfileinfo(talloc_tos(), cli, fnum,
4404 SMB_QUERY_FILE_NAME_INFO,
4405 4, CLI_BUFFER_SIZE, &recv_flags2,
4406 &rdata, &num_rdata);
4407 if (!NT_STATUS_IS_OK(status)) {
4411 namelen = IVAL(rdata, 0);
4412 if (namelen > (num_rdata - 4)) {
4414 return NT_STATUS_INVALID_NETWORK_RESPONSE;
4417 pull_string_talloc(mem_ctx,
4418 (const char *)rdata,
4425 status = map_nt_error_from_unix(errno);
4432 return NT_STATUS_OK;
4436 This checks a couple of trans2 calls
4438 static bool run_trans2test(int dummy)
4440 struct cli_state *cli;
4443 time_t c_time, a_time, m_time;
4444 struct timespec c_time_ts, a_time_ts, m_time_ts, w_time_ts, m_time2_ts;
4445 const char *fname = "\\trans2.tst";
4446 const char *dname = "\\trans2";
4447 const char *fname2 = "\\trans2\\trans2.tst";
4449 bool correct = True;
4454 printf("starting trans2 test\n");
4456 if (!torture_open_connection(&cli, 0)) {
4460 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
4461 /* Ensure ino is zero, SMB2 gets a real one. */
4464 /* Ensure ino is -1, SMB1 never gets a real one. */
4468 status = cli_get_fs_attr_info(cli, &fs_attr);
4469 if (!NT_STATUS_IS_OK(status)) {
4470 printf("ERROR: cli_get_fs_attr_info returned %s\n",
4475 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4476 cli_openx(cli, fname, O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum);
4477 status = cli_qfileinfo_basic(cli, fnum, NULL, &size, &c_time_ts,
4478 &a_time_ts, &w_time_ts, &m_time_ts, NULL);
4479 if (!NT_STATUS_IS_OK(status)) {
4480 printf("ERROR: qfileinfo failed (%s)\n", nt_errstr(status));
4484 status = cli_qfilename(cli, fnum, talloc_tos(), &pname);
4485 if (!NT_STATUS_IS_OK(status)) {
4486 printf("ERROR: qfilename failed (%s)\n", nt_errstr(status));
4489 else if (strcmp(pname, fname)) {
4490 printf("qfilename gave different name? [%s] [%s]\n",
4495 cli_close(cli, fnum);
4499 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4500 status = cli_openx(cli, fname, O_RDWR | O_CREAT | O_TRUNC, DENY_NONE,
4502 if (!NT_STATUS_IS_OK(status)) {
4503 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
4506 cli_close(cli, fnum);
4508 status = cli_qpathinfo1(cli, fname, &c_time, &a_time, &m_time, &size,
4510 if (!NT_STATUS_IS_OK(status)) {
4511 printf("ERROR: qpathinfo failed (%s)\n", nt_errstr(status));
4514 time_t t = time(NULL);
4516 if (c_time != m_time) {
4517 printf("create time=%s", ctime(&c_time));
4518 printf("modify time=%s", ctime(&m_time));
4519 printf("This system appears to have sticky create times\n");
4521 if ((labs(a_time - t) > 60) && (a_time % (60*60) == 0)) {
4522 printf("access time=%s", ctime(&a_time));
4523 printf("This system appears to set a midnight access time\n");
4527 if (labs(m_time - t) > 60*60*24*7) {
4528 printf("ERROR: totally incorrect times - maybe word reversed? mtime=%s", ctime(&m_time));
4534 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4535 cli_openx(cli, fname,
4536 O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum);
4537 cli_close(cli, fnum);
4538 status = cli_qpathinfo2(cli,
4548 if (!NT_STATUS_IS_OK(status)) {
4549 printf("ERROR: qpathinfo2 failed (%s)\n", nt_errstr(status));
4552 if (w_time_ts.tv_sec < 60*60*24*2) {
4553 printf("write time=%s", ctime(&w_time_ts.tv_sec));
4554 printf("This system appears to set a initial 0 write time\n");
4557 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
4558 /* SMB2 should always return an inode. */
4560 printf("SMB2 bad inode (0)\n");
4564 /* SMB1 must always return zero here. */
4566 printf("SMB1 bad inode (!0)\n");
4572 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4575 /* check if the server updates the directory modification time
4576 when creating a new file */
4577 status = cli_mkdir(cli, dname);
4578 if (!NT_STATUS_IS_OK(status)) {
4579 printf("ERROR: mkdir failed (%s)\n", nt_errstr(status));
4583 status = cli_qpathinfo2(cli,
4593 if (!NT_STATUS_IS_OK(status)) {
4594 printf("ERROR: qpathinfo2 failed (%s)\n", nt_errstr(status));
4598 cli_openx(cli, fname2,
4599 O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum);
4600 cli_writeall(cli, fnum, 0, (uint8_t *)&fnum, 0, sizeof(fnum), NULL);
4601 cli_close(cli, fnum);
4602 status = cli_qpathinfo2(cli,
4612 if (!NT_STATUS_IS_OK(status)) {
4613 printf("ERROR: qpathinfo2 failed (%s)\n", nt_errstr(status));
4616 if (memcmp(&m_time_ts, &m_time2_ts, sizeof(struct timespec))
4618 printf("This system does not update directory modification times\n");
4622 cli_unlink(cli, fname2, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4623 cli_rmdir(cli, dname);
4625 if (!torture_close_connection(cli)) {
4629 printf("trans2 test finished\n");
4635 This checks new W2K calls.
4638 static NTSTATUS new_trans(struct cli_state *pcli, int fnum, int level)
4640 uint8_t *buf = NULL;
4644 status = cli_qfileinfo(talloc_tos(), pcli, fnum, level, 0,
4645 CLI_BUFFER_SIZE, NULL, &buf, &len);
4646 if (!NT_STATUS_IS_OK(status)) {
4647 printf("ERROR: qfileinfo (%d) failed (%s)\n", level,
4650 printf("qfileinfo: level %d, len = %u\n", level, len);
4651 dump_data(0, (uint8_t *)buf, len);
4658 static bool run_w2ktest(int dummy)
4660 struct cli_state *cli;
4662 const char *fname = "\\w2ktest\\w2k.tst";
4664 bool correct = True;
4666 printf("starting w2k test\n");
4668 if (!torture_open_connection(&cli, 0)) {
4672 cli_openx(cli, fname,
4673 O_RDWR | O_CREAT , DENY_NONE, &fnum);
4675 for (level = 1004; level < 1040; level++) {
4676 new_trans(cli, fnum, level);
4679 cli_close(cli, fnum);
4681 if (!torture_close_connection(cli)) {
4685 printf("w2k test finished\n");
4692 this is a harness for some oplock tests
4694 static bool run_oplock1(int dummy)
4696 struct cli_state *cli1;
4697 const char *fname = "\\lockt1.lck";
4699 bool correct = True;
4702 printf("starting oplock test 1\n");
4704 if (!torture_open_connection(&cli1, 0)) {
4708 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4710 smbXcli_conn_set_sockopt(cli1->conn, sockops);
4712 cli1->use_oplocks = True;
4714 status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
4716 if (!NT_STATUS_IS_OK(status)) {
4717 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
4721 cli1->use_oplocks = False;
4723 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4724 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4726 status = cli_close(cli1, fnum1);
4727 if (!NT_STATUS_IS_OK(status)) {
4728 printf("close2 failed (%s)\n", nt_errstr(status));
4732 status = cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4733 if (!NT_STATUS_IS_OK(status)) {
4734 printf("unlink failed (%s)\n", nt_errstr(status));
4738 if (!torture_close_connection(cli1)) {
4742 printf("finished oplock test 1\n");
4747 static bool run_oplock2(int dummy)
4749 struct cli_state *cli1, *cli2;
4750 const char *fname = "\\lockt2.lck";
4751 uint16_t fnum1, fnum2;
4752 int saved_use_oplocks = use_oplocks;
4754 bool correct = True;
4755 volatile bool *shared_correct;
4759 shared_correct = (volatile bool *)anonymous_shared_allocate(sizeof(bool));
4760 *shared_correct = True;
4762 use_level_II_oplocks = True;
4765 printf("starting oplock test 2\n");
4767 if (!torture_open_connection(&cli1, 0)) {
4768 use_level_II_oplocks = False;
4769 use_oplocks = saved_use_oplocks;
4773 if (!torture_open_connection(&cli2, 1)) {
4774 use_level_II_oplocks = False;
4775 use_oplocks = saved_use_oplocks;
4779 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4781 smbXcli_conn_set_sockopt(cli1->conn, sockops);
4782 smbXcli_conn_set_sockopt(cli2->conn, sockops);
4784 status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
4786 if (!NT_STATUS_IS_OK(status)) {
4787 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
4791 /* Don't need the globals any more. */
4792 use_level_II_oplocks = False;
4793 use_oplocks = saved_use_oplocks;
4797 status = cli_openx(cli2, fname, O_RDWR, DENY_NONE, &fnum2);
4798 if (!NT_STATUS_IS_OK(status)) {
4799 printf("second open of %s failed (%s)\n", fname, nt_errstr(status));
4800 *shared_correct = False;
4806 status = cli_close(cli2, fnum2);
4807 if (!NT_STATUS_IS_OK(status)) {
4808 printf("close2 failed (%s)\n", nt_errstr(status));
4809 *shared_correct = False;
4817 /* Ensure cli1 processes the break. Empty file should always return 0
4819 status = cli_read(cli1, fnum1, buf, 0, 4, &nread);
4820 if (!NT_STATUS_IS_OK(status)) {
4821 printf("read on fnum1 failed (%s)\n", nt_errstr(status));
4823 } else if (nread != 0) {
4824 printf("read on empty fnum1 failed. recv %ld expected %d\n",
4825 (unsigned long)nread, 0);
4829 /* Should now be at level II. */
4830 /* Test if sending a write locks causes a break to none. */
4831 status = cli_lock32(cli1, fnum1, 0, 4, 0, READ_LOCK);
4832 if (!NT_STATUS_IS_OK(status)) {
4833 printf("lock failed (%s)\n", nt_errstr(status));
4837 cli_unlock(cli1, fnum1, 0, 4);
4841 status = cli_lock32(cli1, fnum1, 0, 4, 0, WRITE_LOCK);
4842 if (!NT_STATUS_IS_OK(status)) {
4843 printf("lock failed (%s)\n", nt_errstr(status));
4847 cli_unlock(cli1, fnum1, 0, 4);
4851 cli_read(cli1, fnum1, buf, 0, 4, NULL);
4853 status = cli_close(cli1, fnum1);
4854 if (!NT_STATUS_IS_OK(status)) {
4855 printf("close1 failed (%s)\n", nt_errstr(status));
4861 status = cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4862 if (!NT_STATUS_IS_OK(status)) {
4863 printf("unlink failed (%s)\n", nt_errstr(status));
4867 if (!torture_close_connection(cli1)) {
4871 if (!*shared_correct) {
4875 printf("finished oplock test 2\n");
4880 struct oplock4_state {
4881 struct tevent_context *ev;
4882 struct cli_state *cli;
4887 static void oplock4_got_break(struct tevent_req *req);
4888 static void oplock4_got_open(struct tevent_req *req);
4890 static bool run_oplock4(int dummy)
4892 struct tevent_context *ev;
4893 struct cli_state *cli1, *cli2;
4894 struct tevent_req *oplock_req, *open_req;
4895 const char *fname = "\\lockt4.lck";
4896 const char *fname_ln = "\\lockt4_ln.lck";
4897 uint16_t fnum1, fnum2;
4898 int saved_use_oplocks = use_oplocks;
4900 bool correct = true;
4904 struct oplock4_state *state;
4906 printf("starting oplock test 4\n");
4908 if (!torture_open_connection(&cli1, 0)) {
4909 use_level_II_oplocks = false;
4910 use_oplocks = saved_use_oplocks;
4914 if (!torture_open_connection(&cli2, 1)) {
4915 use_level_II_oplocks = false;
4916 use_oplocks = saved_use_oplocks;
4920 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4921 cli_unlink(cli1, fname_ln, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4923 smbXcli_conn_set_sockopt(cli1->conn, sockops);
4924 smbXcli_conn_set_sockopt(cli2->conn, sockops);
4926 /* Create the file. */
4927 status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
4929 if (!NT_STATUS_IS_OK(status)) {
4930 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
4934 status = cli_close(cli1, fnum1);
4935 if (!NT_STATUS_IS_OK(status)) {
4936 printf("close1 failed (%s)\n", nt_errstr(status));
4940 /* Now create a hardlink. */
4941 status = cli_hardlink(cli1, fname, fname_ln);
4942 if (!NT_STATUS_IS_OK(status)) {
4943 printf("nt hardlink failed (%s)\n", nt_errstr(status));
4947 /* Prove that opening hardlinks cause deny modes to conflict. */
4948 status = cli_openx(cli1, fname, O_RDWR, DENY_ALL, &fnum1);
4949 if (!NT_STATUS_IS_OK(status)) {
4950 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
4954 status = cli_openx(cli1, fname_ln, O_RDWR, DENY_NONE, &fnum2);
4955 if (NT_STATUS_IS_OK(status)) {
4956 printf("open of %s succeeded - should fail with sharing violation.\n",
4961 if (!NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
4962 printf("open of %s should fail with sharing violation. Got %s\n",
4963 fname_ln, nt_errstr(status));
4967 status = cli_close(cli1, fnum1);
4968 if (!NT_STATUS_IS_OK(status)) {
4969 printf("close1 failed (%s)\n", nt_errstr(status));
4973 cli1->use_oplocks = true;
4974 cli2->use_oplocks = true;
4976 status = cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
4977 if (!NT_STATUS_IS_OK(status)) {
4978 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
4982 ev = samba_tevent_context_init(talloc_tos());
4984 printf("tevent_context_init failed\n");
4988 state = talloc(ev, struct oplock4_state);
4989 if (state == NULL) {
4990 printf("talloc failed\n");
4995 state->got_break = &got_break;
4996 state->fnum2 = &fnum2;
4998 oplock_req = cli_smb_oplock_break_waiter_send(
4999 talloc_tos(), ev, cli1);
5000 if (oplock_req == NULL) {
5001 printf("cli_smb_oplock_break_waiter_send failed\n");
5004 tevent_req_set_callback(oplock_req, oplock4_got_break, state);
5006 open_req = cli_openx_send(
5007 talloc_tos(), ev, cli2, fname_ln, O_RDWR, DENY_NONE);
5008 if (open_req == NULL) {
5009 printf("cli_openx_send failed\n");
5012 tevent_req_set_callback(open_req, oplock4_got_open, state);
5017 while (!got_break || fnum2 == 0xffff) {
5019 ret = tevent_loop_once(ev);
5021 printf("tevent_loop_once failed: %s\n",
5027 status = cli_close(cli2, fnum2);
5028 if (!NT_STATUS_IS_OK(status)) {
5029 printf("close2 failed (%s)\n", nt_errstr(status));
5033 status = cli_close(cli1, fnum1);
5034 if (!NT_STATUS_IS_OK(status)) {
5035 printf("close1 failed (%s)\n", nt_errstr(status));
5039 status = cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5040 if (!NT_STATUS_IS_OK(status)) {
5041 printf("unlink failed (%s)\n", nt_errstr(status));
5045 status = cli_unlink(cli1, fname_ln, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5046 if (!NT_STATUS_IS_OK(status)) {
5047 printf("unlink failed (%s)\n", nt_errstr(status));
5051 if (!torture_close_connection(cli1)) {
5059 printf("finished oplock test 4\n");
5064 static void oplock4_got_break(struct tevent_req *req)
5066 struct oplock4_state *state = tevent_req_callback_data(
5067 req, struct oplock4_state);
5072 status = cli_smb_oplock_break_waiter_recv(req, &fnum, &level);
5074 if (!NT_STATUS_IS_OK(status)) {
5075 printf("cli_smb_oplock_break_waiter_recv returned %s\n",
5079 *state->got_break = true;
5081 req = cli_oplock_ack_send(state, state->ev, state->cli, fnum,
5084 printf("cli_oplock_ack_send failed\n");
5089 static void oplock4_got_open(struct tevent_req *req)
5091 struct oplock4_state *state = tevent_req_callback_data(
5092 req, struct oplock4_state);
5095 status = cli_openx_recv(req, state->fnum2);
5096 if (!NT_STATUS_IS_OK(status)) {
5097 printf("cli_openx_recv returned %s\n", nt_errstr(status));
5098 *state->fnum2 = 0xffff;
5102 #ifdef HAVE_KERNEL_OPLOCKS_LINUX
5104 struct oplock5_state {
5109 * Async open the file that has a kernel oplock, do an echo to get
5110 * that 100% across, close the file to signal to the child fd that the
5111 * oplock can be dropped, wait for the open reply.
5114 static void oplock5_opened(struct tevent_req *subreq);
5115 static void oplock5_pong(struct tevent_req *subreq);
5116 static void oplock5_timedout(struct tevent_req *subreq);
5118 static struct tevent_req *oplock5_send(
5119 TALLOC_CTX *mem_ctx,
5120 struct tevent_context *ev,
5121 struct cli_state *cli,
5125 struct tevent_req *req = NULL, *subreq = NULL;
5126 struct oplock5_state *state = NULL;
5127 static uint8_t data = 0;
5129 req = tevent_req_create(mem_ctx, &state, struct oplock5_state);
5133 state->pipe_down_fd = pipe_down_fd;
5135 subreq = cli_ntcreate_send(
5141 SEC_FILE_READ_DATA, /* DesiredAccess */
5142 FILE_ATTRIBUTE_NORMAL, /* FileAttributes */
5143 FILE_SHARE_WRITE|FILE_SHARE_READ, /* ShareAccess */
5144 FILE_OPEN, /* CreateDisposition */
5145 FILE_NON_DIRECTORY_FILE, /* CreateOptions */
5146 0, /* Impersonation */
5147 0); /* SecurityFlags */
5148 if (tevent_req_nomem(subreq, req)) {
5149 return tevent_req_post(req, ev);
5151 tevent_req_set_callback(subreq, oplock5_opened, req);
5153 subreq = cli_echo_send(
5158 (DATA_BLOB) { .data = &data, .length = sizeof(data) });
5159 if (tevent_req_nomem(subreq, req)) {
5160 return tevent_req_post(req, ev);
5162 tevent_req_set_callback(subreq, oplock5_pong, req);
5164 subreq = tevent_wakeup_send(state, ev, timeval_current_ofs(20, 0));
5165 if (tevent_req_nomem(subreq, req)) {
5166 return tevent_req_post(req, ev);
5168 tevent_req_set_callback(subreq, oplock5_timedout, req);
5173 static void oplock5_opened(struct tevent_req *subreq)
5175 struct tevent_req *req = tevent_req_callback_data(
5176 subreq, struct tevent_req);
5180 status = cli_ntcreate_recv(subreq, &fnum, NULL);
5181 TALLOC_FREE(subreq);
5182 if (tevent_req_nterror(req, status)) {
5185 tevent_req_done(req);
5188 static void oplock5_pong(struct tevent_req *subreq)
5190 struct tevent_req *req = tevent_req_callback_data(
5191 subreq, struct tevent_req);
5192 struct oplock5_state *state = tevent_req_data(
5193 req, struct oplock5_state);
5196 status = cli_echo_recv(subreq);
5197 TALLOC_FREE(subreq);
5198 if (tevent_req_nterror(req, status)) {
5202 close(state->pipe_down_fd);
5205 static void oplock5_timedout(struct tevent_req *subreq)
5207 struct tevent_req *req = tevent_req_callback_data(
5208 subreq, struct tevent_req);
5211 ok = tevent_wakeup_recv(subreq);
5212 TALLOC_FREE(subreq);
5214 tevent_req_oom(req);
5217 tevent_req_nterror(req, NT_STATUS_TIMEOUT);
5220 static NTSTATUS oplock5_recv(struct tevent_req *req)
5222 return tevent_req_simple_recv_ntstatus(req);
5225 static bool run_oplock5(int dummy)
5227 struct tevent_context *ev = NULL;
5228 struct tevent_req *req = NULL;
5229 struct cli_state *cli = NULL;
5230 const char *fname = "oplock5.txt";
5231 int pipe_down[2], pipe_up[2];
5238 printf("starting oplock5\n");
5240 if (local_path == NULL) {
5241 d_fprintf(stderr, "oplock5 must be given a local path via "
5242 "-l <localpath>\n");
5246 ret = pipe(pipe_down);
5248 d_fprintf(stderr, "pipe() failed: %s\n", strerror(errno));
5251 ret = pipe(pipe_up);
5253 d_fprintf(stderr, "pipe() failed: %s\n", strerror(errno));
5258 if (child_pid == -1) {
5259 d_fprintf(stderr, "fork() failed: %s\n", strerror(errno));
5263 if (child_pid == 0) {
5264 char *local_file = NULL;
5267 close(pipe_down[1]);
5270 local_file = talloc_asprintf(
5271 talloc_tos(), "%s/%s", local_path, fname);
5272 if (local_file == 0) {
5276 fd = open(local_file, O_RDWR|O_CREAT, 0644);
5279 "open(%s) in child failed: %s\n",
5286 signal(SIGIO, SIG_IGN);
5288 ret = fcntl(fd, F_SETLEASE, F_WRLCK);
5291 "SETLEASE in child failed: %s\n",
5298 ret = sys_write(pipe_up[1], &c, sizeof(c));
5301 "sys_write failed: %s\n",
5305 ret = sys_read(pipe_down[0], &c, sizeof(c));
5308 "sys_read failed: %s\n",
5316 close(pipe_down[0]);
5318 ret = sys_read(pipe_up[0], &c, sizeof(c));
5321 "sys_read failed: %s\n",
5326 d_fprintf(stderr, "got error code %"PRIu8"\n", c);
5330 ok = torture_open_connection(&cli, 0);
5332 d_fprintf(stderr, "torture_open_connection failed\n");
5336 ev = samba_tevent_context_init(talloc_tos());
5338 d_fprintf(stderr, "samba_tevent_context_init failed\n");
5342 req = oplock5_send(ev, ev, cli, fname, pipe_down[1]);
5344 d_fprintf(stderr, "oplock5_send failed\n");
5348 ok = tevent_req_poll_ntstatus(req, ev, &status);
5351 "tevent_req_poll_ntstatus failed: %s\n",
5356 status = oplock5_recv(req);
5358 if (!NT_STATUS_IS_OK(status)) {
5360 "oplock5 failed: %s\n",
5368 #endif /* HAVE_KERNEL_OPLOCKS_LINUX */
5371 Test delete on close semantics.
5373 static bool run_deletetest(int dummy)
5375 struct cli_state *cli1 = NULL;
5376 struct cli_state *cli2 = NULL;
5377 const char *fname = "\\delete.file";
5378 uint16_t fnum1 = (uint16_t)-1;
5379 uint16_t fnum2 = (uint16_t)-1;
5380 bool correct = false;
5383 printf("starting delete test\n");
5385 if (!torture_open_connection(&cli1, 0)) {
5389 smbXcli_conn_set_sockopt(cli1->conn, sockops);
5391 /* Test 1 - this should delete the file on close. */
5393 cli_setatr(cli1, fname, 0, 0);
5394 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5396 status = cli_ntcreate(cli1, fname, 0, GENERIC_ALL_ACCESS|DELETE_ACCESS,
5397 FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
5398 FILE_DELETE_ON_CLOSE, 0, &fnum1, NULL);
5399 if (!NT_STATUS_IS_OK(status)) {
5400 printf("[1] open of %s failed (%s)\n", fname, nt_errstr(status));
5404 status = cli_close(cli1, fnum1);
5405 if (!NT_STATUS_IS_OK(status)) {
5406 printf("[1] close failed (%s)\n", nt_errstr(status));
5410 status = cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
5411 if (NT_STATUS_IS_OK(status)) {
5412 printf("[1] open of %s succeeded (should fail)\n", fname);
5416 printf("first delete on close test succeeded.\n");
5418 /* Test 2 - this should delete the file on close. */
5420 cli_setatr(cli1, fname, 0, 0);
5421 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5423 status = cli_ntcreate(cli1, fname, 0, GENERIC_ALL_ACCESS,
5424 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
5425 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
5426 if (!NT_STATUS_IS_OK(status)) {
5427 printf("[2] open of %s failed (%s)\n", fname, nt_errstr(status));
5431 status = cli_nt_delete_on_close(cli1, fnum1, true);
5432 if (!NT_STATUS_IS_OK(status)) {
5433 printf("[2] setting delete_on_close failed (%s)\n", nt_errstr(status));
5437 status = cli_close(cli1, fnum1);
5438 if (!NT_STATUS_IS_OK(status)) {
5439 printf("[2] close failed (%s)\n", nt_errstr(status));
5443 status = cli_openx(cli1, fname, O_RDONLY, DENY_NONE, &fnum1);
5444 if (NT_STATUS_IS_OK(status)) {
5445 printf("[2] open of %s succeeded should have been deleted on close !\n", fname);
5446 status = cli_close(cli1, fnum1);
5447 if (!NT_STATUS_IS_OK(status)) {
5448 printf("[2] close failed (%s)\n", nt_errstr(status));
5450 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5454 printf("second delete on close test succeeded.\n");
5457 cli_setatr(cli1, fname, 0, 0);
5458 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5460 status = cli_ntcreate(cli1, fname, 0, GENERIC_ALL_ACCESS,
5461 FILE_ATTRIBUTE_NORMAL,
5462 FILE_SHARE_READ|FILE_SHARE_WRITE,
5463 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
5464 if (!NT_STATUS_IS_OK(status)) {
5465 printf("[3] open - 1 of %s failed (%s)\n", fname, nt_errstr(status));
5469 /* This should fail with a sharing violation - open for delete is only compatible
5470 with SHARE_DELETE. */
5472 status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
5473 FILE_ATTRIBUTE_NORMAL,
5474 FILE_SHARE_READ|FILE_SHARE_WRITE,
5475 FILE_OPEN, 0, 0, &fnum2, NULL);
5476 if (NT_STATUS_IS_OK(status)) {
5477 printf("[3] open - 2 of %s succeeded - should have failed.\n", fname);
5481 /* This should succeed. */
5482 status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
5483 FILE_ATTRIBUTE_NORMAL,
5484 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5485 FILE_OPEN, 0, 0, &fnum2, NULL);
5486 if (!NT_STATUS_IS_OK(status)) {
5487 printf("[3] open - 3 of %s failed (%s)\n", fname, nt_errstr(status));
5491 status = cli_nt_delete_on_close(cli1, fnum1, true);
5492 if (!NT_STATUS_IS_OK(status)) {
5493 printf("[3] setting delete_on_close failed (%s)\n", nt_errstr(status));
5497 status = cli_close(cli1, fnum1);
5498 if (!NT_STATUS_IS_OK(status)) {
5499 printf("[3] close 1 failed (%s)\n", nt_errstr(status));
5503 status = cli_close(cli1, fnum2);
5504 if (!NT_STATUS_IS_OK(status)) {
5505 printf("[3] close 2 failed (%s)\n", nt_errstr(status));
5509 /* This should fail - file should no longer be there. */
5511 status = cli_openx(cli1, fname, O_RDONLY, DENY_NONE, &fnum1);
5512 if (NT_STATUS_IS_OK(status)) {
5513 printf("[3] open of %s succeeded should have been deleted on close !\n", fname);
5514 status = cli_close(cli1, fnum1);
5515 if (!NT_STATUS_IS_OK(status)) {
5516 printf("[3] close failed (%s)\n", nt_errstr(status));
5518 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5522 printf("third delete on close test succeeded.\n");
5525 cli_setatr(cli1, fname, 0, 0);
5526 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5528 status = cli_ntcreate(cli1, fname, 0,
5529 FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
5530 FILE_ATTRIBUTE_NORMAL,
5531 FILE_SHARE_READ|FILE_SHARE_WRITE,
5532 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
5533 if (!NT_STATUS_IS_OK(status)) {
5534 printf("[4] open of %s failed (%s)\n", fname, nt_errstr(status));
5538 /* This should succeed. */
5539 status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
5540 FILE_ATTRIBUTE_NORMAL,
5541 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5542 FILE_OPEN, 0, 0, &fnum2, NULL);
5543 if (!NT_STATUS_IS_OK(status)) {
5544 printf("[4] open - 2 of %s failed (%s)\n", fname, nt_errstr(status));
5548 status = cli_close(cli1, fnum2);
5549 if (!NT_STATUS_IS_OK(status)) {
5550 printf("[4] close - 1 failed (%s)\n", nt_errstr(status));
5554 status = cli_nt_delete_on_close(cli1, fnum1, true);
5555 if (!NT_STATUS_IS_OK(status)) {
5556 printf("[4] setting delete_on_close failed (%s)\n", nt_errstr(status));
5560 /* This should fail - no more opens once delete on close set. */
5561 status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
5562 FILE_ATTRIBUTE_NORMAL,
5563 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5564 FILE_OPEN, 0, 0, &fnum2, NULL);
5565 if (NT_STATUS_IS_OK(status)) {
5566 printf("[4] open - 3 of %s succeeded ! Should have failed.\n", fname );
5570 status = cli_close(cli1, fnum1);
5571 if (!NT_STATUS_IS_OK(status)) {
5572 printf("[4] close - 2 failed (%s)\n", nt_errstr(status));
5576 printf("fourth delete on close test succeeded.\n");
5579 cli_setatr(cli1, fname, 0, 0);
5580 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5582 status = cli_openx(cli1, fname, O_RDWR|O_CREAT, DENY_NONE, &fnum1);
5583 if (!NT_STATUS_IS_OK(status)) {
5584 printf("[5] open of %s failed (%s)\n", fname, nt_errstr(status));
5588 /* This should fail - only allowed on NT opens with DELETE access. */
5590 status = cli_nt_delete_on_close(cli1, fnum1, true);
5591 if (NT_STATUS_IS_OK(status)) {
5592 printf("[5] setting delete_on_close on OpenX file succeeded - should fail !\n");
5596 status = cli_close(cli1, fnum1);
5597 if (!NT_STATUS_IS_OK(status)) {
5598 printf("[5] close failed (%s)\n", nt_errstr(status));
5602 printf("fifth delete on close test succeeded.\n");
5605 cli_setatr(cli1, fname, 0, 0);
5606 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5608 status = cli_ntcreate(cli1, fname, 0, FILE_READ_DATA|FILE_WRITE_DATA,
5609 FILE_ATTRIBUTE_NORMAL,
5610 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5611 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
5612 if (!NT_STATUS_IS_OK(status)) {
5613 printf("[6] open of %s failed (%s)\n", fname,
5618 /* This should fail - only allowed on NT opens with DELETE access. */
5620 status = cli_nt_delete_on_close(cli1, fnum1, true);
5621 if (NT_STATUS_IS_OK(status)) {
5622 printf("[6] setting delete_on_close on file with no delete access succeeded - should fail !\n");
5626 status = cli_close(cli1, fnum1);
5627 if (!NT_STATUS_IS_OK(status)) {
5628 printf("[6] close failed (%s)\n", nt_errstr(status));
5632 printf("sixth delete on close test succeeded.\n");
5635 cli_setatr(cli1, fname, 0, 0);
5636 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5638 status = cli_ntcreate(cli1, fname, 0,
5639 FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
5640 FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
5641 0, 0, &fnum1, NULL);
5642 if (!NT_STATUS_IS_OK(status)) {
5643 printf("[7] open of %s failed (%s)\n", fname, nt_errstr(status));
5647 status = cli_nt_delete_on_close(cli1, fnum1, true);
5648 if (!NT_STATUS_IS_OK(status)) {
5649 printf("[7] setting delete_on_close on file failed !\n");
5653 status = cli_nt_delete_on_close(cli1, fnum1, false);
5654 if (!NT_STATUS_IS_OK(status)) {
5655 printf("[7] unsetting delete_on_close on file failed !\n");
5659 status = cli_close(cli1, fnum1);
5660 if (!NT_STATUS_IS_OK(status)) {
5661 printf("[7] close - 1 failed (%s)\n", nt_errstr(status));
5665 /* This next open should succeed - we reset the flag. */
5666 status = cli_openx(cli1, fname, O_RDONLY, DENY_NONE, &fnum1);
5667 if (!NT_STATUS_IS_OK(status)) {
5668 printf("[7] open of %s failed (%s)\n", fname, nt_errstr(status));
5672 status = cli_close(cli1, fnum1);
5673 if (!NT_STATUS_IS_OK(status)) {
5674 printf("[7] close - 2 failed (%s)\n", nt_errstr(status));
5678 printf("seventh delete on close test succeeded.\n");
5681 cli_setatr(cli1, fname, 0, 0);
5682 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5684 if (!torture_open_connection(&cli2, 1)) {
5685 printf("[8] failed to open second connection.\n");
5689 smbXcli_conn_set_sockopt(cli1->conn, sockops);
5691 status = cli_ntcreate(cli1, fname, 0,
5692 FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
5693 FILE_ATTRIBUTE_NORMAL,
5694 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5695 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
5696 if (!NT_STATUS_IS_OK(status)) {
5697 printf("[8] open 1 of %s failed (%s)\n", fname, nt_errstr(status));
5701 status = cli_ntcreate(cli2, fname, 0,
5702 FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
5703 FILE_ATTRIBUTE_NORMAL,
5704 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5705 FILE_OPEN, 0, 0, &fnum2, NULL);
5706 if (!NT_STATUS_IS_OK(status)) {
5707 printf("[8] open 2 of %s failed (%s)\n", fname, nt_errstr(status));
5711 status = cli_nt_delete_on_close(cli1, fnum1, true);
5712 if (!NT_STATUS_IS_OK(status)) {
5713 printf("[8] setting delete_on_close on file failed !\n");
5717 status = cli_close(cli1, fnum1);
5718 if (!NT_STATUS_IS_OK(status)) {
5719 printf("[8] close - 1 failed (%s)\n", nt_errstr(status));
5723 status = cli_close(cli2, fnum2);
5724 if (!NT_STATUS_IS_OK(status)) {
5725 printf("[8] close - 2 failed (%s)\n", nt_errstr(status));
5729 /* This should fail.. */
5730 status = cli_openx(cli1, fname, O_RDONLY, DENY_NONE, &fnum1);
5731 if (NT_STATUS_IS_OK(status)) {
5732 printf("[8] open of %s succeeded should have been deleted on close !\n", fname);
5736 printf("eighth delete on close test succeeded.\n");
5740 /* This should fail - we need to set DELETE_ACCESS. */
5741 status = cli_ntcreate(cli1, fname, 0, FILE_READ_DATA|FILE_WRITE_DATA,
5742 FILE_ATTRIBUTE_NORMAL,
5745 FILE_DELETE_ON_CLOSE, 0, &fnum1, NULL);
5746 if (NT_STATUS_IS_OK(status)) {
5747 printf("[9] open of %s succeeded should have failed!\n", fname);
5751 printf("ninth delete on close test succeeded.\n");
5755 status = cli_ntcreate(cli1, fname, 0,
5756 FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
5757 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
5758 FILE_OVERWRITE_IF, FILE_DELETE_ON_CLOSE,
5760 if (!NT_STATUS_IS_OK(status)) {
5761 printf("[10] open of %s failed (%s)\n", fname, nt_errstr(status));
5765 /* This should delete the file. */
5766 status = cli_close(cli1, fnum1);
5767 if (!NT_STATUS_IS_OK(status)) {
5768 printf("[10] close failed (%s)\n", nt_errstr(status));
5772 /* This should fail.. */
5773 status = cli_openx(cli1, fname, O_RDONLY, DENY_NONE, &fnum1);
5774 if (NT_STATUS_IS_OK(status)) {
5775 printf("[10] open of %s succeeded should have been deleted on close !\n", fname);
5779 printf("tenth delete on close test succeeded.\n");
5783 cli_setatr(cli1, fname, 0, 0);
5784 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5786 /* Can we open a read-only file with delete access? */
5788 /* Create a readonly file. */
5789 status = cli_ntcreate(cli1, fname, 0, FILE_READ_DATA|FILE_WRITE_DATA,
5790 FILE_ATTRIBUTE_READONLY, FILE_SHARE_NONE,
5791 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
5792 if (!NT_STATUS_IS_OK(status)) {
5793 printf("[11] open of %s failed (%s)\n", fname, nt_errstr(status));
5797 status = cli_close(cli1, fnum1);
5798 if (!NT_STATUS_IS_OK(status)) {
5799 printf("[11] close failed (%s)\n", nt_errstr(status));
5803 /* Now try open for delete access. */
5804 status = cli_ntcreate(cli1, fname, 0,
5805 FILE_READ_ATTRIBUTES|DELETE_ACCESS,
5807 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5808 FILE_OPEN, 0, 0, &fnum1, NULL);
5809 if (!NT_STATUS_IS_OK(status)) {
5810 printf("[11] open of %s failed: %s\n", fname, nt_errstr(status));
5814 cli_close(cli1, fnum1);
5816 printf("eleventh delete on close test succeeded.\n");
5820 * like test 4 but with initial delete on close
5823 cli_setatr(cli1, fname, 0, 0);
5824 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5826 status = cli_ntcreate(cli1, fname, 0,
5827 FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
5828 FILE_ATTRIBUTE_NORMAL,
5829 FILE_SHARE_READ|FILE_SHARE_WRITE,
5831 FILE_DELETE_ON_CLOSE, 0, &fnum1, NULL);
5832 if (!NT_STATUS_IS_OK(status)) {
5833 printf("[12] open 1 of %s failed (%s)\n", fname, nt_errstr(status));
5837 status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
5838 FILE_ATTRIBUTE_NORMAL,
5839 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5840 FILE_OPEN, 0, 0, &fnum2, NULL);
5841 if (!NT_STATUS_IS_OK(status)) {
5842 printf("[12] open 2 of %s failed(%s).\n", fname, nt_errstr(status));
5846 status = cli_close(cli1, fnum2);
5847 if (!NT_STATUS_IS_OK(status)) {
5848 printf("[12] close 1 failed (%s)\n", nt_errstr(status));
5852 status = cli_nt_delete_on_close(cli1, fnum1, true);
5853 if (!NT_STATUS_IS_OK(status)) {
5854 printf("[12] setting delete_on_close failed (%s)\n", nt_errstr(status));
5858 /* This should fail - no more opens once delete on close set. */
5859 status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
5860 FILE_ATTRIBUTE_NORMAL,
5861 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5862 FILE_OPEN, 0, 0, &fnum2, NULL);
5863 if (NT_STATUS_IS_OK(status)) {
5864 printf("[12] open 3 of %s succeeded - should fail).\n", fname);
5868 status = cli_nt_delete_on_close(cli1, fnum1, false);
5869 if (!NT_STATUS_IS_OK(status)) {
5870 printf("[12] unsetting delete_on_close failed (%s)\n", nt_errstr(status));
5874 status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
5875 FILE_ATTRIBUTE_NORMAL,
5876 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5877 FILE_OPEN, 0, 0, &fnum2, NULL);
5878 if (!NT_STATUS_IS_OK(status)) {
5879 printf("[12] open 4 of %s failed (%s)\n", fname, nt_errstr(status));
5883 status = cli_close(cli1, fnum2);
5884 if (!NT_STATUS_IS_OK(status)) {
5885 printf("[12] close 2 failed (%s)\n", nt_errstr(status));
5889 status = cli_close(cli1, fnum1);
5890 if (!NT_STATUS_IS_OK(status)) {
5891 printf("[12] close 3 failed (%s)\n", nt_errstr(status));
5896 * setting delete on close on the handle does
5897 * not unset the initial delete on close...
5899 status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
5900 FILE_ATTRIBUTE_NORMAL,
5901 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5902 FILE_OPEN, 0, 0, &fnum2, NULL);
5903 if (NT_STATUS_IS_OK(status)) {
5904 printf("[12] open 5 of %s succeeded - should fail).\n", fname);
5906 } else if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
5907 printf("ntcreate returned %s, expected "
5908 "NT_STATUS_OBJECT_NAME_NOT_FOUND\n",
5913 printf("twelfth delete on close test succeeded.\n");
5916 printf("finished delete test\n");
5921 /* FIXME: This will crash if we aborted before cli2 got
5922 * initialized, because these functions don't handle
5923 * uninitialized connections. */
5925 if (fnum1 != (uint16_t)-1) cli_close(cli1, fnum1);
5926 if (fnum2 != (uint16_t)-1) cli_close(cli1, fnum2);
5927 cli_setatr(cli1, fname, 0, 0);
5928 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5930 if (cli1 && !torture_close_connection(cli1)) {
5933 if (cli2 && !torture_close_connection(cli2)) {
5939 struct delete_stream_state {
5943 static void delete_stream_unlinked(struct tevent_req *subreq);
5944 static void delete_stream_closed(struct tevent_req *subreq);
5946 static struct tevent_req *delete_stream_send(
5947 TALLOC_CTX *mem_ctx,
5948 struct tevent_context *ev,
5949 struct cli_state *cli,
5950 const char *base_fname,
5951 uint16_t stream_fnum)
5953 struct tevent_req *req = NULL, *subreq = NULL;
5954 struct delete_stream_state *state = NULL;
5956 req = tevent_req_create(
5957 mem_ctx, &state, struct delete_stream_state);
5962 subreq = cli_unlink_send(
5967 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5968 if (tevent_req_nomem(subreq, req)) {
5969 return tevent_req_post(req, ev);
5971 tevent_req_set_callback(subreq, delete_stream_unlinked, req);
5973 subreq = cli_close_send(state, ev, cli, stream_fnum, 0);
5974 if (tevent_req_nomem(subreq, req)) {
5975 return tevent_req_post(req, ev);
5977 tevent_req_set_callback(subreq, delete_stream_closed, req);
5982 static void delete_stream_unlinked(struct tevent_req *subreq)
5984 struct tevent_req *req = tevent_req_callback_data(
5985 subreq, struct tevent_req);
5986 struct delete_stream_state *state = tevent_req_data(
5987 req, struct delete_stream_state);
5990 status = cli_unlink_recv(subreq);
5991 TALLOC_FREE(subreq);
5992 if (!NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
5993 printf("cli_unlink returned %s\n",
5995 tevent_req_nterror(req, NT_STATUS_UNSUCCESSFUL);
5998 if (!state->closed) {
5999 /* close reply should have come in first */
6000 printf("Not closed\n");
6001 tevent_req_nterror(req, NT_STATUS_UNSUCCESSFUL);
6004 tevent_req_done(req);
6007 static void delete_stream_closed(struct tevent_req *subreq)
6009 struct tevent_req *req = tevent_req_callback_data(
6010 subreq, struct tevent_req);
6011 struct delete_stream_state *state = tevent_req_data(
6012 req, struct delete_stream_state);
6015 status = cli_close_recv(subreq);
6016 TALLOC_FREE(subreq);
6017 if (tevent_req_nterror(req, status)) {
6020 /* also waiting for the unlink to come back */
6021 state->closed = true;
6024 static NTSTATUS delete_stream_recv(struct tevent_req *req)
6026 return tevent_req_simple_recv_ntstatus(req);
6029 static bool run_delete_stream(int dummy)
6031 struct tevent_context *ev = NULL;
6032 struct tevent_req *req = NULL;
6033 struct cli_state *cli = NULL;
6034 const char fname[] = "delete_stream";
6035 const char fname_stream[] = "delete_stream:Zone.Identifier:$DATA";
6036 uint16_t fnum1, fnum2;
6040 printf("Starting stream delete test\n");
6042 ok = torture_open_connection(&cli, 0);
6047 cli_setatr(cli, fname, 0, 0);
6048 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6050 /* Create the file. */
6051 status = cli_ntcreate(
6055 READ_CONTROL_ACCESS,
6057 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6063 if (!NT_STATUS_IS_OK(status)) {
6065 "cli_ntcreate of %s failed (%s)\n",
6070 status = cli_close(cli, fnum1);
6071 if (!NT_STATUS_IS_OK(status)) {
6073 "cli_close of %s failed (%s)\n",
6079 /* Now create the stream. */
6080 status = cli_ntcreate(
6086 FILE_SHARE_READ|FILE_SHARE_WRITE,
6093 if (!NT_STATUS_IS_OK(status)) {
6095 "cli_ntcreate of %s failed (%s)\n",
6101 /* open it a second time */
6103 status = cli_ntcreate(
6109 FILE_SHARE_READ|FILE_SHARE_WRITE,
6116 if (!NT_STATUS_IS_OK(status)) {
6118 "2nd cli_ntcreate of %s failed (%s)\n",
6124 ev = samba_tevent_context_init(talloc_tos());
6126 d_fprintf(stderr, "samba_tevent_context_init failed\n");
6130 req = delete_stream_send(ev, ev, cli, fname, fnum1);
6132 d_fprintf(stderr, "delete_stream_send failed\n");
6136 ok = tevent_req_poll_ntstatus(req, ev, &status);
6139 "tevent_req_poll_ntstatus failed: %s\n",
6144 status = delete_stream_recv(req);
6146 if (!NT_STATUS_IS_OK(status)) {
6148 "delete_stream failed: %s\n",
6153 status = cli_close(cli, fnum2);
6154 if (!NT_STATUS_IS_OK(status)) {
6156 "close failed: %s\n",
6161 status = cli_unlink(
6162 cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6163 if (!NT_STATUS_IS_OK(status)) {
6165 "unlink failed: %s\n",
6174 Exercise delete on close semantics - use on the PRINT1 share in torture
6177 static bool run_delete_print_test(int dummy)
6179 struct cli_state *cli1 = NULL;
6180 const char *fname = "print_delete.file";
6181 uint16_t fnum1 = (uint16_t)-1;
6182 bool correct = false;
6183 const char *buf = "print file data\n";
6186 printf("starting print delete test\n");
6188 if (!torture_open_connection(&cli1, 0)) {
6192 smbXcli_conn_set_sockopt(cli1->conn, sockops);
6194 status = cli_ntcreate(cli1, fname, 0, GENERIC_ALL_ACCESS|DELETE_ACCESS,
6195 FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
6196 0, 0, &fnum1, NULL);
6197 if (!NT_STATUS_IS_OK(status)) {
6198 printf("open of %s failed (%s)\n",
6204 status = cli_writeall(cli1,
6207 (const uint8_t *)buf,
6209 strlen(buf), /* size */
6211 if (!NT_STATUS_IS_OK(status)) {
6212 printf("writing print file data failed (%s)\n",
6217 status = cli_nt_delete_on_close(cli1, fnum1, true);
6218 if (!NT_STATUS_IS_OK(status)) {
6219 printf("setting delete_on_close failed (%s)\n",
6224 status = cli_close(cli1, fnum1);
6225 if (!NT_STATUS_IS_OK(status)) {
6226 printf("close failed (%s)\n", nt_errstr(status));
6230 printf("finished print delete test\n");
6236 if (fnum1 != (uint16_t)-1) {
6237 cli_close(cli1, fnum1);
6240 if (cli1 && !torture_close_connection(cli1)) {
6246 static bool run_deletetest_ln(int dummy)
6248 struct cli_state *cli;
6249 const char *fname = "\\delete1";
6250 const char *fname_ln = "\\delete1_ln";
6254 bool correct = true;
6257 printf("starting deletetest-ln\n");
6259 if (!torture_open_connection(&cli, 0)) {
6263 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6264 cli_unlink(cli, fname_ln, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6266 smbXcli_conn_set_sockopt(cli->conn, sockops);
6268 /* Create the file. */
6269 status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
6270 if (!NT_STATUS_IS_OK(status)) {
6271 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
6275 status = cli_close(cli, fnum);
6276 if (!NT_STATUS_IS_OK(status)) {
6277 printf("close1 failed (%s)\n", nt_errstr(status));
6281 /* Now create a hardlink. */
6282 status = cli_hardlink(cli, fname, fname_ln);
6283 if (!NT_STATUS_IS_OK(status)) {
6284 printf("nt hardlink failed (%s)\n", nt_errstr(status));
6288 /* Open the original file. */
6289 status = cli_ntcreate(cli, fname, 0, FILE_READ_DATA,
6290 FILE_ATTRIBUTE_NORMAL,
6291 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6292 FILE_OPEN_IF, 0, 0, &fnum, NULL);
6293 if (!NT_STATUS_IS_OK(status)) {
6294 printf("ntcreate of %s failed (%s)\n", fname, nt_errstr(status));
6298 /* Unlink the hard link path. */
6299 status = cli_ntcreate(cli, fname_ln, 0, DELETE_ACCESS,
6300 FILE_ATTRIBUTE_NORMAL,
6301 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6302 FILE_OPEN_IF, 0, 0, &fnum1, NULL);
6303 if (!NT_STATUS_IS_OK(status)) {
6304 printf("ntcreate of %s failed (%s)\n", fname_ln, nt_errstr(status));
6307 status = cli_nt_delete_on_close(cli, fnum1, true);
6308 if (!NT_STATUS_IS_OK(status)) {
6309 d_printf("(%s) failed to set delete_on_close %s: %s\n",
6310 __location__, fname_ln, nt_errstr(status));
6314 status = cli_close(cli, fnum1);
6315 if (!NT_STATUS_IS_OK(status)) {
6316 printf("close %s failed (%s)\n",
6317 fname_ln, nt_errstr(status));
6321 status = cli_close(cli, fnum);
6322 if (!NT_STATUS_IS_OK(status)) {
6323 printf("close %s failed (%s)\n",
6324 fname, nt_errstr(status));
6328 /* Ensure the original file is still there. */
6329 status = cli_getatr(cli, fname, NULL, NULL, &t);
6330 if (!NT_STATUS_IS_OK(status)) {
6331 printf("%s getatr on file %s failed (%s)\n",
6338 /* Ensure the link path is gone. */
6339 status = cli_getatr(cli, fname_ln, NULL, NULL, &t);
6340 if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
6341 printf("%s, getatr for file %s returned wrong error code %s "
6342 "- should have been deleted\n",
6344 fname_ln, nt_errstr(status));
6348 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6349 cli_unlink(cli, fname_ln, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6351 if (!torture_close_connection(cli)) {
6355 printf("finished deletetest-ln\n");
6361 print out server properties
6363 static bool run_properties(int dummy)
6365 struct cli_state *cli;
6366 bool correct = True;
6368 printf("starting properties test\n");
6372 if (!torture_open_connection(&cli, 0)) {
6376 smbXcli_conn_set_sockopt(cli->conn, sockops);
6378 d_printf("Capabilities 0x%08x\n", smb1cli_conn_capabilities(cli->conn));
6380 if (!torture_close_connection(cli)) {
6389 /* FIRST_DESIRED_ACCESS 0xf019f */
6390 #define FIRST_DESIRED_ACCESS FILE_READ_DATA|FILE_WRITE_DATA|FILE_APPEND_DATA|\
6391 FILE_READ_EA| /* 0xf */ \
6392 FILE_WRITE_EA|FILE_READ_ATTRIBUTES| /* 0x90 */ \
6393 FILE_WRITE_ATTRIBUTES| /* 0x100 */ \
6394 DELETE_ACCESS|READ_CONTROL_ACCESS|\
6395 WRITE_DAC_ACCESS|WRITE_OWNER_ACCESS /* 0xf0000 */
6396 /* SECOND_DESIRED_ACCESS 0xe0080 */
6397 #define SECOND_DESIRED_ACCESS FILE_READ_ATTRIBUTES| /* 0x80 */ \
6398 READ_CONTROL_ACCESS|WRITE_DAC_ACCESS|\
6399 WRITE_OWNER_ACCESS /* 0xe0000 */
6402 #define THIRD_DESIRED_ACCESS FILE_READ_ATTRIBUTES| /* 0x80 */ \
6403 READ_CONTROL_ACCESS|WRITE_DAC_ACCESS|\
6405 WRITE_OWNER_ACCESS /* */
6409 Test ntcreate calls made by xcopy
6411 static bool run_xcopy(int dummy)
6413 static struct cli_state *cli1;
6414 const char *fname = "\\test.txt";
6415 bool correct = True;
6416 uint16_t fnum1, fnum2;
6419 printf("starting xcopy test\n");
6421 if (!torture_open_connection(&cli1, 0)) {
6425 status = cli_ntcreate(cli1, fname, 0, FIRST_DESIRED_ACCESS,
6426 FILE_ATTRIBUTE_ARCHIVE, FILE_SHARE_NONE,
6427 FILE_OVERWRITE_IF, 0x4044, 0, &fnum1, NULL);
6428 if (!NT_STATUS_IS_OK(status)) {
6429 printf("First open failed - %s\n", nt_errstr(status));
6433 status = cli_ntcreate(cli1, fname, 0, SECOND_DESIRED_ACCESS, 0,
6434 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6435 FILE_OPEN, 0x200000, 0, &fnum2, NULL);
6436 if (!NT_STATUS_IS_OK(status)) {
6437 printf("second open failed - %s\n", nt_errstr(status));
6441 if (!torture_close_connection(cli1)) {
6449 Test rename on files open with share delete and no share delete.
6451 static bool run_rename(int dummy)
6453 static struct cli_state *cli1;
6454 const char *fname = "\\test.txt";
6455 const char *fname1 = "\\test1.txt";
6456 bool correct = True;
6461 printf("starting rename test\n");
6463 if (!torture_open_connection(&cli1, 0)) {
6467 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6468 cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6470 status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
6471 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ,
6472 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
6473 if (!NT_STATUS_IS_OK(status)) {
6474 printf("First open failed - %s\n", nt_errstr(status));
6478 status = cli_rename(cli1, fname, fname1, false);
6479 if (!NT_STATUS_IS_OK(status)) {
6480 printf("First rename failed (SHARE_READ) (this is correct) - %s\n", nt_errstr(status));
6482 printf("First rename succeeded (SHARE_READ) - this should have failed !\n");
6486 status = cli_close(cli1, fnum1);
6487 if (!NT_STATUS_IS_OK(status)) {
6488 printf("close - 1 failed (%s)\n", nt_errstr(status));
6492 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6493 cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6494 status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS, FILE_ATTRIBUTE_NORMAL,
6496 FILE_SHARE_DELETE|FILE_SHARE_NONE,
6498 FILE_SHARE_DELETE|FILE_SHARE_READ,
6500 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
6501 if (!NT_STATUS_IS_OK(status)) {
6502 printf("Second open failed - %s\n", nt_errstr(status));
6506 status = cli_rename(cli1, fname, fname1, false);
6507 if (!NT_STATUS_IS_OK(status)) {
6508 printf("Second rename failed (SHARE_DELETE | SHARE_READ) - this should have succeeded - %s\n", nt_errstr(status));
6511 printf("Second rename succeeded (SHARE_DELETE | SHARE_READ)\n");
6514 status = cli_close(cli1, fnum1);
6515 if (!NT_STATUS_IS_OK(status)) {
6516 printf("close - 2 failed (%s)\n", nt_errstr(status));
6520 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6521 cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6523 status = cli_ntcreate(cli1, fname, 0, READ_CONTROL_ACCESS,
6524 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
6525 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
6526 if (!NT_STATUS_IS_OK(status)) {
6527 printf("Third open failed - %s\n", nt_errstr(status));
6532 status = cli_rename(cli1, fname, fname1, false);
6533 if (!NT_STATUS_IS_OK(status)) {
6534 printf("Third rename failed (SHARE_NONE) - this should have succeeded - %s\n", nt_errstr(status));
6537 printf("Third rename succeeded (SHARE_NONE)\n");
6540 status = cli_close(cli1, fnum1);
6541 if (!NT_STATUS_IS_OK(status)) {
6542 printf("close - 3 failed (%s)\n", nt_errstr(status));
6546 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6547 cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6551 status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
6552 FILE_ATTRIBUTE_NORMAL,
6553 FILE_SHARE_READ | FILE_SHARE_WRITE,
6554 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
6555 if (!NT_STATUS_IS_OK(status)) {
6556 printf("Fourth open failed - %s\n", nt_errstr(status));
6560 status = cli_rename(cli1, fname, fname1, false);
6561 if (!NT_STATUS_IS_OK(status)) {
6562 printf("Fourth rename failed (SHARE_READ | SHARE_WRITE) (this is correct) - %s\n", nt_errstr(status));
6564 printf("Fourth rename succeeded (SHARE_READ | SHARE_WRITE) - this should have failed !\n");
6568 status = cli_close(cli1, fnum1);
6569 if (!NT_STATUS_IS_OK(status)) {
6570 printf("close - 4 failed (%s)\n", nt_errstr(status));
6574 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6575 cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6579 status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
6580 FILE_ATTRIBUTE_NORMAL,
6581 FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
6582 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
6583 if (!NT_STATUS_IS_OK(status)) {
6584 printf("Fifth open failed - %s\n", nt_errstr(status));
6588 status = cli_rename(cli1, fname, fname1, false);
6589 if (!NT_STATUS_IS_OK(status)) {
6590 printf("Fifth rename failed (SHARE_READ | SHARE_WRITE | SHARE_DELETE) - this should have succeeded - %s ! \n", nt_errstr(status));
6593 printf("Fifth rename succeeded (SHARE_READ | SHARE_WRITE | SHARE_DELETE) (this is correct) - %s\n", nt_errstr(status));
6597 status = cli_close(cli1, fnum1);
6598 if (!NT_STATUS_IS_OK(status)) {
6599 printf("close - 5 failed (%s)\n", nt_errstr(status));
6603 /* Check that the renamed file has FILE_ATTRIBUTE_ARCHIVE. */
6604 status = cli_getatr(cli1, fname1, &attr, NULL, NULL);
6605 if (!NT_STATUS_IS_OK(status)) {
6606 printf("getatr on file %s failed - %s ! \n",
6607 fname1, nt_errstr(status));
6610 if (attr != FILE_ATTRIBUTE_ARCHIVE) {
6611 printf("Renamed file %s has wrong attr 0x%x "
6612 "(should be 0x%x)\n",
6615 (unsigned int)FILE_ATTRIBUTE_ARCHIVE);
6618 printf("Renamed file %s has archive bit set\n", fname1);
6622 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6623 cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6625 if (!torture_close_connection(cli1)) {
6633 Test rename into a directory with an ACL denying it.
6635 static bool run_rename_access(int dummy)
6637 static struct cli_state *cli = NULL;
6638 static struct cli_state *posix_cli = NULL;
6639 const char *src = "test.txt";
6640 const char *dname = "dir";
6641 const char *dst = "dir\\test.txt";
6642 const char *dsrc = "test.dir";
6643 const char *ddst = "dir\\test.dir";
6644 uint16_t fnum = (uint16_t)-1;
6645 struct security_descriptor *sd = NULL;
6646 struct security_descriptor *newsd = NULL;
6648 TALLOC_CTX *frame = NULL;
6650 frame = talloc_stackframe();
6651 printf("starting rename access test\n");
6653 /* Windows connection. */
6654 if (!torture_open_connection(&cli, 0)) {
6658 smbXcli_conn_set_sockopt(cli->conn, sockops);
6660 /* Posix connection. */
6661 if (!torture_open_connection(&posix_cli, 0)) {
6665 smbXcli_conn_set_sockopt(posix_cli->conn, sockops);
6667 status = torture_setup_unix_extensions(posix_cli);
6668 if (!NT_STATUS_IS_OK(status)) {
6672 /* Start with a clean slate. */
6673 cli_unlink(cli, src, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6674 cli_unlink(cli, dst, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6675 cli_rmdir(cli, dsrc);
6676 cli_rmdir(cli, ddst);
6677 cli_rmdir(cli, dname);
6680 * Setup the destination directory with a DENY ACE to
6681 * prevent new files within it.
6683 status = cli_ntcreate(cli,
6686 FILE_READ_ATTRIBUTES|READ_CONTROL_ACCESS|
6687 WRITE_DAC_ACCESS|FILE_READ_DATA|
6689 FILE_ATTRIBUTE_DIRECTORY,
6690 FILE_SHARE_READ|FILE_SHARE_WRITE,
6692 FILE_DIRECTORY_FILE,
6696 if (!NT_STATUS_IS_OK(status)) {
6697 printf("Create of %s - %s\n", dname, nt_errstr(status));
6701 status = cli_query_secdesc(cli,
6705 if (!NT_STATUS_IS_OK(status)) {
6706 printf("cli_query_secdesc failed for %s (%s)\n",
6707 dname, nt_errstr(status));
6711 newsd = security_descriptor_dacl_create(frame,
6716 SEC_ACE_TYPE_ACCESS_DENIED,
6717 SEC_DIR_ADD_FILE|SEC_DIR_ADD_SUBDIR,
6720 if (newsd == NULL) {
6723 sd->dacl = security_acl_concatenate(frame,
6726 if (sd->dacl == NULL) {
6729 status = cli_set_secdesc(cli, fnum, sd);
6730 if (!NT_STATUS_IS_OK(status)) {
6731 printf("cli_set_secdesc failed for %s (%s)\n",
6732 dname, nt_errstr(status));
6735 status = cli_close(cli, fnum);
6736 if (!NT_STATUS_IS_OK(status)) {
6737 printf("close failed for %s (%s)\n",
6738 dname, nt_errstr(status));
6741 /* Now go around the back and chmod to 777 via POSIX. */
6742 status = cli_posix_chmod(posix_cli, dname, 0777);
6743 if (!NT_STATUS_IS_OK(status)) {
6744 printf("cli_posix_chmod failed for %s (%s)\n",
6745 dname, nt_errstr(status));
6749 /* Check we can't create a file within dname via Windows. */
6750 status = cli_openx(cli, dst, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
6751 if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
6752 cli_close(posix_cli, fnum);
6753 printf("Create of %s should be ACCESS denied, was %s\n",
6754 dst, nt_errstr(status));
6758 /* Make the sample file/directory. */
6759 status = cli_openx(cli, src, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
6760 if (!NT_STATUS_IS_OK(status)) {
6761 printf("open of %s failed (%s)\n", src, nt_errstr(status));
6764 status = cli_close(cli, fnum);
6765 if (!NT_STATUS_IS_OK(status)) {
6766 printf("cli_close failed (%s)\n", nt_errstr(status));
6770 status = cli_mkdir(cli, dsrc);
6771 if (!NT_STATUS_IS_OK(status)) {
6772 printf("cli_mkdir of %s failed (%s)\n",
6773 dsrc, nt_errstr(status));
6778 * OK - renames of the new file and directory into the
6779 * dst directory should fail.
6782 status = cli_rename(cli, src, dst, false);
6783 if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
6784 printf("rename of %s -> %s should be ACCESS denied, was %s\n",
6785 src, dst, nt_errstr(status));
6788 status = cli_rename(cli, dsrc, ddst, false);
6789 if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
6790 printf("rename of %s -> %s should be ACCESS denied, was %s\n",
6791 src, dst, nt_errstr(status));
6801 torture_close_connection(posix_cli);
6805 if (fnum != (uint16_t)-1) {
6806 cli_close(cli, fnum);
6808 cli_unlink(cli, src,
6809 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6810 cli_unlink(cli, dst,
6811 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6812 cli_rmdir(cli, dsrc);
6813 cli_rmdir(cli, ddst);
6814 cli_rmdir(cli, dname);
6816 torture_close_connection(cli);
6824 Test owner rights ACE.
6826 static bool run_owner_rights(int dummy)
6828 static struct cli_state *cli = NULL;
6829 const char *fname = "owner_rights.txt";
6830 uint16_t fnum = (uint16_t)-1;
6831 struct security_descriptor *sd = NULL;
6832 struct security_descriptor *newsd = NULL;
6834 TALLOC_CTX *frame = NULL;
6836 frame = talloc_stackframe();
6837 printf("starting owner rights test\n");
6839 /* Windows connection. */
6840 if (!torture_open_connection(&cli, 0)) {
6844 smbXcli_conn_set_sockopt(cli->conn, sockops);
6846 /* Start with a clean slate. */
6847 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6849 /* Create the test file. */
6850 /* Now try and open for read and write-dac. */
6851 status = cli_ntcreate(cli,
6855 FILE_ATTRIBUTE_NORMAL,
6856 FILE_SHARE_READ|FILE_SHARE_WRITE|
6863 if (!NT_STATUS_IS_OK(status)) {
6864 printf("Create of %s - %s\n", fname, nt_errstr(status));
6868 /* Get the original SD. */
6869 status = cli_query_secdesc(cli,
6873 if (!NT_STATUS_IS_OK(status)) {
6874 printf("cli_query_secdesc failed for %s (%s)\n",
6875 fname, nt_errstr(status));
6880 * Add an "owner-rights" ACE denying WRITE_DATA,
6881 * and an "owner-rights" ACE allowing READ_DATA.
6884 newsd = security_descriptor_dacl_create(frame,
6889 SEC_ACE_TYPE_ACCESS_DENIED,
6893 SEC_ACE_TYPE_ACCESS_ALLOWED,
6897 if (newsd == NULL) {
6900 sd->dacl = security_acl_concatenate(frame,
6903 if (sd->dacl == NULL) {
6906 status = cli_set_secdesc(cli, fnum, sd);
6907 if (!NT_STATUS_IS_OK(status)) {
6908 printf("cli_set_secdesc failed for %s (%s)\n",
6909 fname, nt_errstr(status));
6912 status = cli_close(cli, fnum);
6913 if (!NT_STATUS_IS_OK(status)) {
6914 printf("close failed for %s (%s)\n",
6915 fname, nt_errstr(status));
6918 fnum = (uint16_t)-1;
6920 /* Try and open for FILE_WRITE_DATA */
6921 status = cli_ntcreate(cli,
6925 FILE_ATTRIBUTE_NORMAL,
6926 FILE_SHARE_READ|FILE_SHARE_WRITE|
6933 if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
6934 printf("Open of %s - %s\n", fname, nt_errstr(status));
6938 /* Now try and open for FILE_READ_DATA */
6939 status = cli_ntcreate(cli,
6943 FILE_ATTRIBUTE_NORMAL,
6944 FILE_SHARE_READ|FILE_SHARE_WRITE|
6951 if (!NT_STATUS_IS_OK(status)) {
6952 printf("Open of %s - %s\n", fname, nt_errstr(status));
6956 status = cli_close(cli, fnum);
6957 if (!NT_STATUS_IS_OK(status)) {
6958 printf("close failed for %s (%s)\n",
6959 fname, nt_errstr(status));
6963 /* Restore clean slate. */
6965 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6967 /* Create the test file. */
6968 status = cli_ntcreate(cli,
6972 FILE_ATTRIBUTE_NORMAL,
6973 FILE_SHARE_READ|FILE_SHARE_WRITE|
6980 if (!NT_STATUS_IS_OK(status)) {
6981 printf("Create of %s - %s\n", fname, nt_errstr(status));
6985 /* Get the original SD. */
6986 status = cli_query_secdesc(cli,
6990 if (!NT_STATUS_IS_OK(status)) {
6991 printf("cli_query_secdesc failed for %s (%s)\n",
6992 fname, nt_errstr(status));
6997 * Add an "owner-rights ACE denying WRITE_DATA,
6998 * and an "owner-rights ACE allowing READ_DATA|WRITE_DATA.
7001 newsd = security_descriptor_dacl_create(frame,
7006 SEC_ACE_TYPE_ACCESS_DENIED,
7010 SEC_ACE_TYPE_ACCESS_ALLOWED,
7011 FILE_READ_DATA|FILE_WRITE_DATA,
7014 if (newsd == NULL) {
7017 sd->dacl = security_acl_concatenate(frame,
7020 if (sd->dacl == NULL) {
7023 status = cli_set_secdesc(cli, fnum, sd);
7024 if (!NT_STATUS_IS_OK(status)) {
7025 printf("cli_set_secdesc failed for %s (%s)\n",
7026 fname, nt_errstr(status));
7029 status = cli_close(cli, fnum);
7030 if (!NT_STATUS_IS_OK(status)) {
7031 printf("close failed for %s (%s)\n",
7032 fname, nt_errstr(status));
7035 fnum = (uint16_t)-1;
7037 /* Try and open for FILE_WRITE_DATA */
7038 status = cli_ntcreate(cli,
7042 FILE_ATTRIBUTE_NORMAL,
7043 FILE_SHARE_READ|FILE_SHARE_WRITE|
7050 if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
7051 printf("Open of %s - %s\n", fname, nt_errstr(status));
7055 /* Now try and open for FILE_READ_DATA */
7056 status = cli_ntcreate(cli,
7060 FILE_ATTRIBUTE_NORMAL,
7061 FILE_SHARE_READ|FILE_SHARE_WRITE|
7068 if (!NT_STATUS_IS_OK(status)) {
7069 printf("Open of %s - %s\n", fname, nt_errstr(status));
7073 status = cli_close(cli, fnum);
7074 if (!NT_STATUS_IS_OK(status)) {
7075 printf("close failed for %s (%s)\n",
7076 fname, nt_errstr(status));
7080 /* Restore clean slate. */
7082 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7085 /* Create the test file. */
7086 status = cli_ntcreate(cli,
7090 FILE_ATTRIBUTE_NORMAL,
7091 FILE_SHARE_READ|FILE_SHARE_WRITE|
7098 if (!NT_STATUS_IS_OK(status)) {
7099 printf("Create of %s - %s\n", fname, nt_errstr(status));
7103 /* Get the original SD. */
7104 status = cli_query_secdesc(cli,
7108 if (!NT_STATUS_IS_OK(status)) {
7109 printf("cli_query_secdesc failed for %s (%s)\n",
7110 fname, nt_errstr(status));
7115 * Add an "authenticated users" ACE allowing READ_DATA,
7116 * add an "owner-rights" denying READ_DATA,
7117 * and an "authenticated users" ACE allowing WRITE_DATA.
7120 newsd = security_descriptor_dacl_create(frame,
7124 SID_NT_AUTHENTICATED_USERS,
7125 SEC_ACE_TYPE_ACCESS_ALLOWED,
7129 SEC_ACE_TYPE_ACCESS_DENIED,
7132 SID_NT_AUTHENTICATED_USERS,
7133 SEC_ACE_TYPE_ACCESS_ALLOWED,
7137 if (newsd == NULL) {
7138 printf("newsd == NULL\n");
7141 sd->dacl = security_acl_concatenate(frame,
7144 if (sd->dacl == NULL) {
7145 printf("sd->dacl == NULL\n");
7148 status = cli_set_secdesc(cli, fnum, sd);
7149 if (!NT_STATUS_IS_OK(status)) {
7150 printf("cli_set_secdesc failed for %s (%s)\n",
7151 fname, nt_errstr(status));
7154 status = cli_close(cli, fnum);
7155 if (!NT_STATUS_IS_OK(status)) {
7156 printf("close failed for %s (%s)\n",
7157 fname, nt_errstr(status));
7160 fnum = (uint16_t)-1;
7162 /* Now try and open for FILE_READ_DATA|FILE_WRITE_DATA */
7163 status = cli_ntcreate(cli,
7166 FILE_READ_DATA|FILE_WRITE_DATA,
7167 FILE_ATTRIBUTE_NORMAL,
7168 FILE_SHARE_READ|FILE_SHARE_WRITE|
7175 if (!NT_STATUS_IS_OK(status)) {
7176 printf("Open of %s - %s\n", fname, nt_errstr(status));
7180 status = cli_close(cli, fnum);
7181 if (!NT_STATUS_IS_OK(status)) {
7182 printf("close failed for %s (%s)\n",
7183 fname, nt_errstr(status));
7187 cli_unlink(cli, fname,
7188 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7196 if (fnum != (uint16_t)-1) {
7197 cli_close(cli, fnum);
7199 cli_unlink(cli, fname,
7200 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7201 torture_close_connection(cli);
7209 * Test SMB1-specific open with SEC_FLAG_SYSTEM_SECURITY.
7210 * Note this test only works with a user with SeSecurityPrivilege set.
7212 * NB. This is also tested in samba3.base.createx_access
7213 * but this makes it very explicit what we're looking for.
7215 static bool run_smb1_system_security(int dummy)
7217 static struct cli_state *cli = NULL;
7218 const char *fname = "system_security.txt";
7219 uint16_t fnum = (uint16_t)-1;
7221 TALLOC_CTX *frame = NULL;
7223 frame = talloc_stackframe();
7224 printf("starting smb1 system security test\n");
7226 /* SMB1 connection - torture_open_connection() forces this. */
7227 if (!torture_open_connection(&cli, 0)) {
7231 smbXcli_conn_set_sockopt(cli->conn, sockops);
7233 /* Start with a clean slate. */
7234 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7236 /* Create the test file. */
7237 status = cli_ntcreate(cli,
7241 FILE_ATTRIBUTE_NORMAL,
7242 FILE_SHARE_READ|FILE_SHARE_WRITE|
7249 if (!NT_STATUS_IS_OK(status)) {
7250 printf("Create of %s - %s\n", fname, nt_errstr(status));
7254 status = cli_close(cli, fnum);
7256 /* Open with SEC_FLAG_SYSTEM_SECURITY only. */
7258 * On SMB1 this succeeds - SMB2 it fails,
7259 * see the SMB2-SACL test.
7261 status = cli_ntcreate(cli,
7264 SEC_FLAG_SYSTEM_SECURITY,
7265 FILE_ATTRIBUTE_NORMAL,
7266 FILE_SHARE_READ|FILE_SHARE_WRITE|
7273 if (!NT_STATUS_IS_OK(status)) {
7274 printf("Open of %s - %s\n", fname, nt_errstr(status));
7278 status = cli_close(cli, fnum);
7280 cli_unlink(cli, fname,
7281 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7283 torture_close_connection(cli);
7290 if (fnum != (uint16_t)-1) {
7291 cli_close(cli, fnum);
7293 cli_unlink(cli, fname,
7294 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7295 torture_close_connection(cli);
7302 static bool run_pipe_number(int dummy)
7304 struct cli_state *cli1;
7305 const char *pipe_name = "\\SPOOLSS";
7310 printf("starting pipenumber test\n");
7311 if (!torture_open_connection(&cli1, 0)) {
7315 smbXcli_conn_set_sockopt(cli1->conn, sockops);
7317 status = cli_ntcreate(cli1, pipe_name, 0, FILE_READ_DATA,
7318 FILE_ATTRIBUTE_NORMAL,
7319 FILE_SHARE_READ|FILE_SHARE_WRITE,
7320 FILE_OPEN_IF, 0, 0, &fnum, NULL);
7321 if (!NT_STATUS_IS_OK(status)) {
7322 printf("Open of pipe %s failed with error (%s)\n", pipe_name, nt_errstr(status));
7326 printf("\r%6d", num_pipes);
7329 printf("pipe_number test - we can open %d %s pipes.\n", num_pipes, pipe_name );
7330 torture_close_connection(cli1);
7335 Test open mode returns on read-only files.
7337 static bool run_opentest(int dummy)
7339 static struct cli_state *cli1;
7340 static struct cli_state *cli2;
7341 const char *fname = "\\readonly.file";
7342 uint16_t fnum1, fnum2;
7345 bool correct = True;
7349 printf("starting open test\n");
7351 if (!torture_open_connection(&cli1, 0)) {
7355 cli_setatr(cli1, fname, 0, 0);
7356 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7358 smbXcli_conn_set_sockopt(cli1->conn, sockops);
7360 status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
7361 if (!NT_STATUS_IS_OK(status)) {
7362 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
7366 status = cli_close(cli1, fnum1);
7367 if (!NT_STATUS_IS_OK(status)) {
7368 printf("close2 failed (%s)\n", nt_errstr(status));
7372 status = cli_setatr(cli1, fname, FILE_ATTRIBUTE_READONLY, 0);
7373 if (!NT_STATUS_IS_OK(status)) {
7374 printf("cli_setatr failed (%s)\n", nt_errstr(status));
7378 status = cli_openx(cli1, fname, O_RDONLY, DENY_WRITE, &fnum1);
7379 if (!NT_STATUS_IS_OK(status)) {
7380 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
7384 /* This will fail - but the error should be ERRnoaccess, not ERRbadshare. */
7385 status = cli_openx(cli1, fname, O_RDWR, DENY_ALL, &fnum2);
7387 if (check_error(__LINE__, status, ERRDOS, ERRnoaccess,
7388 NT_STATUS_ACCESS_DENIED)) {
7389 printf("correct error code ERRDOS/ERRnoaccess returned\n");
7392 printf("finished open test 1\n");
7394 cli_close(cli1, fnum1);
7396 /* Now try not readonly and ensure ERRbadshare is returned. */
7398 cli_setatr(cli1, fname, 0, 0);
7400 status = cli_openx(cli1, fname, O_RDONLY, DENY_WRITE, &fnum1);
7401 if (!NT_STATUS_IS_OK(status)) {
7402 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
7406 /* This will fail - but the error should be ERRshare. */
7407 status = cli_openx(cli1, fname, O_RDWR, DENY_ALL, &fnum2);
7409 if (check_error(__LINE__, status, ERRDOS, ERRbadshare,
7410 NT_STATUS_SHARING_VIOLATION)) {
7411 printf("correct error code ERRDOS/ERRbadshare returned\n");
7414 status = cli_close(cli1, fnum1);
7415 if (!NT_STATUS_IS_OK(status)) {
7416 printf("close2 failed (%s)\n", nt_errstr(status));
7420 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7422 printf("finished open test 2\n");
7424 /* Test truncate open disposition on file opened for read. */
7425 status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
7426 if (!NT_STATUS_IS_OK(status)) {
7427 printf("(3) open (1) of %s failed (%s)\n", fname, nt_errstr(status));
7431 /* write 20 bytes. */
7433 memset(buf, '\0', 20);
7435 status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 0, 20, NULL);
7436 if (!NT_STATUS_IS_OK(status)) {
7437 printf("write failed (%s)\n", nt_errstr(status));
7441 status = cli_close(cli1, fnum1);
7442 if (!NT_STATUS_IS_OK(status)) {
7443 printf("(3) close1 failed (%s)\n", nt_errstr(status));
7447 /* Ensure size == 20. */
7448 status = cli_getatr(cli1, fname, NULL, &fsize, NULL);
7449 if (!NT_STATUS_IS_OK(status)) {
7450 printf("(3) getatr failed (%s)\n", nt_errstr(status));
7455 printf("(3) file size != 20\n");
7459 /* Now test if we can truncate a file opened for readonly. */
7460 status = cli_openx(cli1, fname, O_RDONLY|O_TRUNC, DENY_NONE, &fnum1);
7461 if (!NT_STATUS_IS_OK(status)) {
7462 printf("(3) open (2) of %s failed (%s)\n", fname, nt_errstr(status));
7466 status = cli_close(cli1, fnum1);
7467 if (!NT_STATUS_IS_OK(status)) {
7468 printf("close2 failed (%s)\n", nt_errstr(status));
7472 /* Ensure size == 0. */
7473 status = cli_getatr(cli1, fname, NULL, &fsize, NULL);
7474 if (!NT_STATUS_IS_OK(status)) {
7475 printf("(3) getatr failed (%s)\n", nt_errstr(status));
7480 printf("(3) file size != 0\n");
7483 printf("finished open test 3\n");
7485 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7487 printf("Do ctemp tests\n");
7488 status = cli_ctemp(cli1, talloc_tos(), "\\", &fnum1, &tmp_path);
7489 if (!NT_STATUS_IS_OK(status)) {
7490 printf("ctemp failed (%s)\n", nt_errstr(status));
7494 printf("ctemp gave path %s\n", tmp_path);
7495 status = cli_close(cli1, fnum1);
7496 if (!NT_STATUS_IS_OK(status)) {
7497 printf("close of temp failed (%s)\n", nt_errstr(status));
7500 status = cli_unlink(cli1, tmp_path, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7501 if (!NT_STATUS_IS_OK(status)) {
7502 printf("unlink of temp failed (%s)\n", nt_errstr(status));
7505 /* Test the non-io opens... */
7507 if (!torture_open_connection(&cli2, 1)) {
7511 cli_setatr(cli2, fname, 0, 0);
7512 cli_unlink(cli2, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7514 smbXcli_conn_set_sockopt(cli2->conn, sockops);
7516 printf("TEST #1 testing 2 non-io opens (no delete)\n");
7517 status = cli_ntcreate(cli1, fname, 0, FILE_READ_ATTRIBUTES,
7518 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7519 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
7520 if (!NT_STATUS_IS_OK(status)) {
7521 printf("TEST #1 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
7525 status = cli_ntcreate(cli2, fname, 0, FILE_READ_ATTRIBUTES,
7526 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7527 FILE_OPEN_IF, 0, 0, &fnum2, NULL);
7528 if (!NT_STATUS_IS_OK(status)) {
7529 printf("TEST #1 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
7533 status = cli_close(cli1, fnum1);
7534 if (!NT_STATUS_IS_OK(status)) {
7535 printf("TEST #1 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
7539 status = cli_close(cli2, fnum2);
7540 if (!NT_STATUS_IS_OK(status)) {
7541 printf("TEST #1 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
7545 printf("non-io open test #1 passed.\n");
7547 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7549 printf("TEST #2 testing 2 non-io opens (first with delete)\n");
7551 status = cli_ntcreate(cli1, fname, 0,
7552 DELETE_ACCESS|FILE_READ_ATTRIBUTES,
7553 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7554 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
7555 if (!NT_STATUS_IS_OK(status)) {
7556 printf("TEST #2 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
7560 status = cli_ntcreate(cli2, fname, 0, FILE_READ_ATTRIBUTES,
7561 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7562 FILE_OPEN_IF, 0, 0, &fnum2, NULL);
7563 if (!NT_STATUS_IS_OK(status)) {
7564 printf("TEST #2 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
7568 status = cli_close(cli1, fnum1);
7569 if (!NT_STATUS_IS_OK(status)) {
7570 printf("TEST #2 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
7574 status = cli_close(cli2, fnum2);
7575 if (!NT_STATUS_IS_OK(status)) {
7576 printf("TEST #2 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
7580 printf("non-io open test #2 passed.\n");
7582 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7584 printf("TEST #3 testing 2 non-io opens (second with delete)\n");
7586 status = cli_ntcreate(cli1, fname, 0, FILE_READ_ATTRIBUTES,
7587 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7588 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
7589 if (!NT_STATUS_IS_OK(status)) {
7590 printf("TEST #3 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
7594 status = cli_ntcreate(cli2, fname, 0,
7595 DELETE_ACCESS|FILE_READ_ATTRIBUTES,
7596 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7597 FILE_OPEN_IF, 0, 0, &fnum2, NULL);
7598 if (!NT_STATUS_IS_OK(status)) {
7599 printf("TEST #3 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
7603 status = cli_close(cli1, fnum1);
7604 if (!NT_STATUS_IS_OK(status)) {
7605 printf("TEST #3 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
7609 status = cli_close(cli2, fnum2);
7610 if (!NT_STATUS_IS_OK(status)) {
7611 printf("TEST #3 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
7615 printf("non-io open test #3 passed.\n");
7617 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7619 printf("TEST #4 testing 2 non-io opens (both with delete)\n");
7621 status = cli_ntcreate(cli1, fname, 0,
7622 DELETE_ACCESS|FILE_READ_ATTRIBUTES,
7623 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7624 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
7625 if (!NT_STATUS_IS_OK(status)) {
7626 printf("TEST #4 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
7630 status = cli_ntcreate(cli2, fname, 0,
7631 DELETE_ACCESS|FILE_READ_ATTRIBUTES,
7632 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7633 FILE_OPEN_IF, 0, 0, &fnum2, NULL);
7634 if (NT_STATUS_IS_OK(status)) {
7635 printf("TEST #4 open 2 of %s SUCCEEDED - should have failed (%s)\n", fname, nt_errstr(status));
7639 printf("TEST #4 open 2 of %s gave %s (correct error should be %s)\n", fname, nt_errstr(status), "sharing violation");
7641 status = cli_close(cli1, fnum1);
7642 if (!NT_STATUS_IS_OK(status)) {
7643 printf("TEST #4 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
7647 printf("non-io open test #4 passed.\n");
7649 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7651 printf("TEST #5 testing 2 non-io opens (both with delete - both with file share delete)\n");
7653 status = cli_ntcreate(cli1, fname, 0,
7654 DELETE_ACCESS|FILE_READ_ATTRIBUTES,
7655 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_DELETE,
7656 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
7657 if (!NT_STATUS_IS_OK(status)) {
7658 printf("TEST #5 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
7662 status = cli_ntcreate(cli2, fname, 0,
7663 DELETE_ACCESS|FILE_READ_ATTRIBUTES,
7664 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_DELETE,
7665 FILE_OPEN_IF, 0, 0, &fnum2, NULL);
7666 if (!NT_STATUS_IS_OK(status)) {
7667 printf("TEST #5 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
7671 status = cli_close(cli1, fnum1);
7672 if (!NT_STATUS_IS_OK(status)) {
7673 printf("TEST #5 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
7677 status = cli_close(cli2, fnum2);
7678 if (!NT_STATUS_IS_OK(status)) {
7679 printf("TEST #5 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
7683 printf("non-io open test #5 passed.\n");
7685 printf("TEST #6 testing 1 non-io open, one io open\n");
7687 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7689 status = cli_ntcreate(cli1, fname, 0, FILE_READ_DATA,
7690 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7691 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
7692 if (!NT_STATUS_IS_OK(status)) {
7693 printf("TEST #6 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
7697 status = cli_ntcreate(cli2, fname, 0, FILE_READ_ATTRIBUTES,
7698 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ,
7699 FILE_OPEN_IF, 0, 0, &fnum2, NULL);
7700 if (!NT_STATUS_IS_OK(status)) {
7701 printf("TEST #6 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
7705 status = cli_close(cli1, fnum1);
7706 if (!NT_STATUS_IS_OK(status)) {
7707 printf("TEST #6 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
7711 status = cli_close(cli2, fnum2);
7712 if (!NT_STATUS_IS_OK(status)) {
7713 printf("TEST #6 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
7717 printf("non-io open test #6 passed.\n");
7719 printf("TEST #7 testing 1 non-io open, one io open with delete\n");
7721 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7723 status = cli_ntcreate(cli1, fname, 0, FILE_READ_DATA,
7724 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7725 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
7726 if (!NT_STATUS_IS_OK(status)) {
7727 printf("TEST #7 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
7731 status = cli_ntcreate(cli2, fname, 0,
7732 DELETE_ACCESS|FILE_READ_ATTRIBUTES,
7733 FILE_ATTRIBUTE_NORMAL,
7734 FILE_SHARE_READ|FILE_SHARE_DELETE,
7735 FILE_OPEN_IF, 0, 0, &fnum2, NULL);
7736 if (NT_STATUS_IS_OK(status)) {
7737 printf("TEST #7 open 2 of %s SUCCEEDED - should have failed (%s)\n", fname, nt_errstr(status));
7741 printf("TEST #7 open 2 of %s gave %s (correct error should be %s)\n", fname, nt_errstr(status), "sharing violation");
7743 status = cli_close(cli1, fnum1);
7744 if (!NT_STATUS_IS_OK(status)) {
7745 printf("TEST #7 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
7749 printf("non-io open test #7 passed.\n");
7751 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7753 printf("TEST #8 testing open without WRITE_ATTRIBUTES, updating close write time.\n");
7754 status = cli_ntcreate(cli1, fname, 0, FILE_WRITE_DATA, FILE_ATTRIBUTE_NORMAL,
7755 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
7756 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
7757 if (!NT_STATUS_IS_OK(status)) {
7758 printf("TEST #8 open of %s failed (%s)\n", fname, nt_errstr(status));
7763 /* Write to ensure we have to update the file time. */
7764 status = cli_writeall(cli1, fnum1, 0, (const uint8_t *)"TEST DATA\n", 0, 10,
7766 if (!NT_STATUS_IS_OK(status)) {
7767 printf("TEST #8 cli_write failed: %s\n", nt_errstr(status));
7772 status = cli_close(cli1, fnum1);
7773 if (!NT_STATUS_IS_OK(status)) {
7774 printf("TEST #8 close of %s failed (%s)\n", fname, nt_errstr(status));
7780 if (!torture_close_connection(cli1)) {
7783 if (!torture_close_connection(cli2)) {
7790 NTSTATUS torture_setup_unix_extensions(struct cli_state *cli)
7792 uint16_t major, minor;
7793 uint32_t caplow, caphigh;
7796 if (!SERVER_HAS_UNIX_CIFS(cli)) {
7797 printf("Server doesn't support UNIX CIFS extensions.\n");
7798 return NT_STATUS_NOT_SUPPORTED;
7801 status = cli_unix_extensions_version(cli, &major, &minor, &caplow,
7803 if (!NT_STATUS_IS_OK(status)) {
7804 printf("Server didn't return UNIX CIFS extensions: %s\n",
7809 status = cli_set_unix_extensions_capabilities(cli, major, minor,
7811 if (!NT_STATUS_IS_OK(status)) {
7812 printf("Server doesn't support setting UNIX CIFS extensions: "
7813 "%s.\n", nt_errstr(status));
7817 return NT_STATUS_OK;
7821 Test POSIX open /mkdir calls.
7823 static bool run_simple_posix_open_test(int dummy)
7825 static struct cli_state *cli1;
7826 const char *fname = "posix:file";
7827 const char *hname = "posix:hlink";
7828 const char *sname = "posix:symlink";
7829 const char *dname = "posix:dir";
7831 char *target = NULL;
7832 uint16_t fnum1 = (uint16_t)-1;
7833 SMB_STRUCT_STAT sbuf;
7834 bool correct = false;
7837 const char *fname_windows = "windows_file";
7838 uint16_t fnum2 = (uint16_t)-1;
7841 printf("Starting simple POSIX open test\n");
7843 if (!torture_open_connection(&cli1, 0)) {
7847 smbXcli_conn_set_sockopt(cli1->conn, sockops);
7849 status = torture_setup_unix_extensions(cli1);
7850 if (!NT_STATUS_IS_OK(status)) {
7854 cli_setatr(cli1, fname, 0, 0);
7855 cli_posix_unlink(cli1, fname);
7856 cli_setatr(cli1, dname, 0, 0);
7857 cli_posix_rmdir(cli1, dname);
7858 cli_setatr(cli1, hname, 0, 0);
7859 cli_posix_unlink(cli1, hname);
7860 cli_setatr(cli1, sname, 0, 0);
7861 cli_posix_unlink(cli1, sname);
7862 cli_setatr(cli1, fname_windows, 0, 0);
7863 cli_posix_unlink(cli1, fname_windows);
7865 /* Create a directory. */
7866 status = cli_posix_mkdir(cli1, dname, 0777);
7867 if (!NT_STATUS_IS_OK(status)) {
7868 printf("POSIX mkdir of %s failed (%s)\n", dname, nt_errstr(status));
7872 status = cli_posix_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL,
7874 if (!NT_STATUS_IS_OK(status)) {
7875 printf("POSIX create of %s failed (%s)\n", fname, nt_errstr(status));
7879 /* Test ftruncate - set file size. */
7880 status = cli_ftruncate(cli1, fnum1, 1000);
7881 if (!NT_STATUS_IS_OK(status)) {
7882 printf("ftruncate failed (%s)\n", nt_errstr(status));
7886 /* Ensure st_size == 1000 */
7887 status = cli_posix_stat(cli1, fname, &sbuf);
7888 if (!NT_STATUS_IS_OK(status)) {
7889 printf("stat failed (%s)\n", nt_errstr(status));
7893 if (sbuf.st_ex_size != 1000) {
7894 printf("ftruncate - stat size (%u) != 1000\n", (unsigned int)sbuf.st_ex_size);
7898 /* Ensure st_mode == 0600 */
7899 if ((sbuf.st_ex_mode & 07777) != 0600) {
7900 printf("posix_open - bad permissions 0%o != 0600\n",
7901 (unsigned int)(sbuf.st_ex_mode & 07777));
7905 /* Test ftruncate - set file size back to zero. */
7906 status = cli_ftruncate(cli1, fnum1, 0);
7907 if (!NT_STATUS_IS_OK(status)) {
7908 printf("ftruncate failed (%s)\n", nt_errstr(status));
7912 status = cli_close(cli1, fnum1);
7913 if (!NT_STATUS_IS_OK(status)) {
7914 printf("close failed (%s)\n", nt_errstr(status));
7918 /* Now open the file again for read only. */
7919 status = cli_posix_open(cli1, fname, O_RDONLY, 0, &fnum1);
7920 if (!NT_STATUS_IS_OK(status)) {
7921 printf("POSIX open of %s failed (%s)\n", fname, nt_errstr(status));
7925 /* Now unlink while open. */
7926 status = cli_posix_unlink(cli1, fname);
7927 if (!NT_STATUS_IS_OK(status)) {
7928 printf("POSIX unlink of %s failed (%s)\n", fname, nt_errstr(status));
7932 status = cli_close(cli1, fnum1);
7933 if (!NT_STATUS_IS_OK(status)) {
7934 printf("close(2) failed (%s)\n", nt_errstr(status));
7938 /* Ensure the file has gone. */
7939 status = cli_posix_open(cli1, fname, O_RDONLY, 0, &fnum1);
7940 if (NT_STATUS_IS_OK(status)) {
7941 printf("POSIX open of %s succeeded, should have been deleted.\n", fname);
7945 /* Create again to test open with O_TRUNC. */
7946 status = cli_posix_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL, 0600, &fnum1);
7947 if (!NT_STATUS_IS_OK(status)) {
7948 printf("POSIX create of %s failed (%s)\n", fname, nt_errstr(status));
7952 /* Test ftruncate - set file size. */
7953 status = cli_ftruncate(cli1, fnum1, 1000);
7954 if (!NT_STATUS_IS_OK(status)) {
7955 printf("ftruncate failed (%s)\n", nt_errstr(status));
7959 /* Ensure st_size == 1000 */
7960 status = cli_posix_stat(cli1, fname, &sbuf);
7961 if (!NT_STATUS_IS_OK(status)) {
7962 printf("stat failed (%s)\n", nt_errstr(status));
7966 if (sbuf.st_ex_size != 1000) {
7967 printf("ftruncate - stat size (%u) != 1000\n", (unsigned int)sbuf.st_ex_size);
7971 status = cli_close(cli1, fnum1);
7972 if (!NT_STATUS_IS_OK(status)) {
7973 printf("close(2) failed (%s)\n", nt_errstr(status));
7977 /* Re-open with O_TRUNC. */
7978 status = cli_posix_open(cli1, fname, O_WRONLY|O_TRUNC, 0600, &fnum1);
7979 if (!NT_STATUS_IS_OK(status)) {
7980 printf("POSIX create of %s failed (%s)\n", fname, nt_errstr(status));
7984 /* Ensure st_size == 0 */
7985 status = cli_posix_stat(cli1, fname, &sbuf);
7986 if (!NT_STATUS_IS_OK(status)) {
7987 printf("stat failed (%s)\n", nt_errstr(status));
7991 if (sbuf.st_ex_size != 0) {
7992 printf("O_TRUNC - stat size (%u) != 0\n", (unsigned int)sbuf.st_ex_size);
7996 status = cli_close(cli1, fnum1);
7997 if (!NT_STATUS_IS_OK(status)) {
7998 printf("close failed (%s)\n", nt_errstr(status));
8002 status = cli_posix_unlink(cli1, fname);
8003 if (!NT_STATUS_IS_OK(status)) {
8004 printf("POSIX unlink of %s failed (%s)\n", fname, nt_errstr(status));
8008 status = cli_posix_open(cli1, dname, O_RDONLY, 0, &fnum1);
8009 if (!NT_STATUS_IS_OK(status)) {
8010 printf("POSIX open directory O_RDONLY of %s failed (%s)\n",
8011 dname, nt_errstr(status));
8015 cli_close(cli1, fnum1);
8017 /* What happens when we try and POSIX open a directory for write ? */
8018 status = cli_posix_open(cli1, dname, O_RDWR, 0, &fnum1);
8019 if (NT_STATUS_IS_OK(status)) {
8020 printf("POSIX open of directory %s succeeded, "
8021 "should have failed.\n",
8025 if (!check_both_error(__LINE__, status, ERRDOS, EISDIR,
8026 NT_STATUS_FILE_IS_A_DIRECTORY)) {
8031 /* Create the file. */
8032 status = cli_posix_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL,
8034 if (!NT_STATUS_IS_OK(status)) {
8035 printf("POSIX create of %s failed (%s)\n", fname, nt_errstr(status));
8039 /* Write some data into it. */
8040 status = cli_writeall(cli1, fnum1, 0, (const uint8_t *)"TEST DATA\n", 0, 10,
8042 if (!NT_STATUS_IS_OK(status)) {
8043 printf("cli_write failed: %s\n", nt_errstr(status));
8047 cli_close(cli1, fnum1);
8049 /* Now create a hardlink. */
8050 status = cli_posix_hardlink(cli1, fname, hname);
8051 if (!NT_STATUS_IS_OK(status)) {
8052 printf("POSIX hardlink of %s failed (%s)\n", hname, nt_errstr(status));
8056 /* Now create a symlink. */
8057 status = cli_posix_symlink(cli1, fname, sname);
8058 if (!NT_STATUS_IS_OK(status)) {
8059 printf("POSIX symlink of %s failed (%s)\n", sname, nt_errstr(status));
8063 /* Open the hardlink for read. */
8064 status = cli_posix_open(cli1, hname, O_RDONLY, 0, &fnum1);
8065 if (!NT_STATUS_IS_OK(status)) {
8066 printf("POSIX open of %s failed (%s)\n", hname, nt_errstr(status));
8070 status = cli_read(cli1, fnum1, buf, 0, 10, &nread);
8071 if (!NT_STATUS_IS_OK(status)) {
8072 printf("POSIX read of %s failed (%s)\n", hname,
8075 } else if (nread != 10) {
8076 printf("POSIX read of %s failed. Received %ld, expected %d\n",
8077 hname, (unsigned long)nread, 10);
8081 if (memcmp(buf, "TEST DATA\n", 10)) {
8082 printf("invalid data read from hardlink\n");
8086 /* Do a POSIX lock/unlock. */
8087 status = cli_posix_lock(cli1, fnum1, 0, 100, true, READ_LOCK);
8088 if (!NT_STATUS_IS_OK(status)) {
8089 printf("POSIX lock failed %s\n", nt_errstr(status));
8093 /* Punch a hole in the locked area. */
8094 status = cli_posix_unlock(cli1, fnum1, 10, 80);
8095 if (!NT_STATUS_IS_OK(status)) {
8096 printf("POSIX unlock failed %s\n", nt_errstr(status));
8100 cli_close(cli1, fnum1);
8102 /* Open the symlink for read - this should fail. A POSIX
8103 client should not be doing opens on a symlink. */
8104 status = cli_posix_open(cli1, sname, O_RDONLY, 0, &fnum1);
8105 if (NT_STATUS_IS_OK(status)) {
8106 printf("POSIX open of %s succeeded (should have failed)\n", sname);
8109 ok = check_both_error(
8110 __LINE__, status, ERRDOS, ERRbadpath,
8111 NT_STATUS_OBJECT_NAME_NOT_FOUND);
8113 printf("POSIX open of %s should have failed "
8114 "with NT_STATUS_OBJECT_NAME_NOT_FOUND, "
8115 "failed with %s instead.\n",
8116 sname, nt_errstr(status));
8120 status = cli_readlink(cli1, sname, talloc_tos(), &target, NULL, NULL);
8121 if (!NT_STATUS_IS_OK(status)) {
8122 printf("POSIX readlink on %s failed (%s)\n", sname, nt_errstr(status));
8126 if (strcmp(target, fname) != 0) {
8127 printf("POSIX readlink on %s failed to match name %s (read %s)\n",
8128 sname, fname, target);
8132 status = cli_posix_rmdir(cli1, dname);
8133 if (!NT_STATUS_IS_OK(status)) {
8134 printf("POSIX rmdir failed (%s)\n", nt_errstr(status));
8138 /* Check directory opens with a specific permission. */
8139 status = cli_posix_mkdir(cli1, dname, 0700);
8140 if (!NT_STATUS_IS_OK(status)) {
8141 printf("POSIX mkdir of %s failed (%s)\n", dname, nt_errstr(status));
8145 /* Ensure st_mode == 0700 */
8146 status = cli_posix_stat(cli1, dname, &sbuf);
8147 if (!NT_STATUS_IS_OK(status)) {
8148 printf("stat failed (%s)\n", nt_errstr(status));
8152 if ((sbuf.st_ex_mode & 07777) != 0700) {
8153 printf("posix_mkdir - bad permissions 0%o != 0700\n",
8154 (unsigned int)(sbuf.st_ex_mode & 07777));
8159 * Now create a Windows file, and attempt a POSIX unlink.
8160 * This should fail with a sharing violation but due to:
8162 * [Bug 9571] Unlink after open causes smbd to panic
8164 * ensure we've fixed the lock ordering violation.
8167 status = cli_ntcreate(cli1, fname_windows, 0,
8168 FILE_READ_DATA|FILE_WRITE_DATA, 0,
8169 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
8171 0x0, 0x0, &fnum2, NULL);
8172 if (!NT_STATUS_IS_OK(status)) {
8173 printf("Windows create of %s failed (%s)\n", fname_windows,
8178 /* Now try posix_unlink. */
8179 status = cli_posix_unlink(cli1, fname_windows);
8180 if (!NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
8181 printf("POSIX unlink of %s should fail "
8182 "with NT_STATUS_SHARING_VIOLATION "
8183 "got %s instead !\n",
8189 cli_close(cli1, fnum2);
8191 printf("Simple POSIX open test passed\n");
8196 if (fnum1 != (uint16_t)-1) {
8197 cli_close(cli1, fnum1);
8198 fnum1 = (uint16_t)-1;
8201 if (fnum2 != (uint16_t)-1) {
8202 cli_close(cli1, fnum2);
8203 fnum2 = (uint16_t)-1;
8206 cli_setatr(cli1, sname, 0, 0);
8207 cli_posix_unlink(cli1, sname);
8208 cli_setatr(cli1, hname, 0, 0);
8209 cli_posix_unlink(cli1, hname);
8210 cli_setatr(cli1, fname, 0, 0);
8211 cli_posix_unlink(cli1, fname);
8212 cli_setatr(cli1, dname, 0, 0);
8213 cli_posix_rmdir(cli1, dname);
8214 cli_setatr(cli1, fname_windows, 0, 0);
8215 cli_posix_unlink(cli1, fname_windows);
8217 if (!torture_close_connection(cli1)) {
8225 Test POSIX and Windows ACLs are rejected on symlinks.
8227 static bool run_acl_symlink_test(int dummy)
8229 static struct cli_state *cli;
8230 const char *fname = "posix_file";
8231 const char *sname = "posix_symlink";
8232 uint16_t fnum = (uint16_t)-1;
8233 bool correct = false;
8235 char *posix_acl = NULL;
8236 size_t posix_acl_len = 0;
8237 char *posix_acl_sym = NULL;
8238 size_t posix_acl_len_sym = 0;
8239 struct security_descriptor *sd = NULL;
8240 TALLOC_CTX *frame = NULL;
8242 frame = talloc_stackframe();
8244 printf("Starting acl symlink test\n");
8246 if (!torture_open_connection(&cli, 0)) {
8251 smbXcli_conn_set_sockopt(cli->conn, sockops);
8253 status = torture_setup_unix_extensions(cli);
8254 if (!NT_STATUS_IS_OK(status)) {
8259 cli_setatr(cli, fname, 0, 0);
8260 cli_posix_unlink(cli, fname);
8261 cli_setatr(cli, sname, 0, 0);
8262 cli_posix_unlink(cli, sname);
8264 status = cli_ntcreate(cli,
8267 READ_CONTROL_ACCESS,
8269 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
8276 if (!NT_STATUS_IS_OK(status)) {
8277 printf("cli_ntcreate of %s failed (%s)\n",
8283 /* Get the Windows ACL on the file. */
8284 status = cli_query_secdesc(cli,
8288 if (!NT_STATUS_IS_OK(status)) {
8289 printf("cli_query_secdesc failed (%s)\n",
8294 /* Get the POSIX ACL on the file. */
8295 status = cli_posix_getacl(cli,
8301 if (!NT_STATUS_IS_OK(status)) {
8302 printf("cli_posix_getacl failed (%s)\n",
8307 status = cli_close(cli, fnum);
8308 if (!NT_STATUS_IS_OK(status)) {
8309 printf("close failed (%s)\n", nt_errstr(status));
8312 fnum = (uint16_t)-1;
8314 /* Now create a symlink. */
8315 status = cli_posix_symlink(cli, fname, sname);
8316 if (!NT_STATUS_IS_OK(status)) {
8317 printf("cli_posix_symlink of %s -> %s failed (%s)\n",
8324 /* Open a handle on the symlink for SD set/get should fail. */
8325 status = cli_ntcreate(cli,
8328 READ_CONTROL_ACCESS|SEC_STD_WRITE_DAC,
8330 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
8337 if (NT_STATUS_IS_OK(status)) {
8338 printf("Symlink open for getsd/setsd of %s "
8339 "succeeded (should fail)\n",
8344 /* Try a stat-open on the symlink, should also fail. */
8345 status = cli_ntcreate(cli,
8348 FILE_READ_ATTRIBUTES|FILE_WRITE_ATTRIBUTES,
8350 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
8357 if (NT_STATUS_IS_OK(status)) {
8358 printf("Stat-open of symlink succeeded (should fail)\n");
8362 /* Get the POSIX ACL on the symlink pathname. Should fail. */
8363 status = cli_posix_getacl(cli,
8369 if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
8370 printf("cli_posix_getacl on a symlink gave %s. "
8371 "Should be NT_STATUS_ACCESS_DENIED.\n",
8376 /* Set the POSIX ACL on the symlink pathname. Should fail. */
8377 status = cli_posix_setacl(cli,
8382 if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
8383 printf("cli_posix_setacl on a symlink gave %s. "
8384 "Should be NT_STATUS_ACCESS_DENIED.\n",
8389 printf("ACL symlink test passed\n");
8394 if (fnum != (uint16_t)-1) {
8395 cli_close(cli, fnum);
8396 fnum = (uint16_t)-1;
8399 cli_setatr(cli, sname, 0, 0);
8400 cli_posix_unlink(cli, sname);
8401 cli_setatr(cli, fname, 0, 0);
8402 cli_posix_unlink(cli, fname);
8404 if (!torture_close_connection(cli)) {
8413 Test POSIX can delete a file containing streams.
8415 static bool run_posix_stream_delete(int dummy)
8417 struct cli_state *cli1 = NULL;
8418 struct cli_state *cli2 = NULL;
8419 const char *fname = "streamfile";
8420 const char *stream_fname = "streamfile:Zone.Identifier:$DATA";
8421 uint16_t fnum1 = (uint16_t)-1;
8422 bool correct = false;
8424 TALLOC_CTX *frame = NULL;
8426 frame = talloc_stackframe();
8428 printf("Starting POSIX stream delete test\n");
8430 if (!torture_open_connection(&cli1, 0) ||
8431 !torture_open_connection(&cli2, 1)) {
8436 smbXcli_conn_set_sockopt(cli1->conn, sockops);
8437 smbXcli_conn_set_sockopt(cli2->conn, sockops);
8439 status = torture_setup_unix_extensions(cli2);
8440 if (!NT_STATUS_IS_OK(status)) {
8444 cli_setatr(cli1, fname, 0, 0);
8445 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
8447 /* Create the file. */
8448 status = cli_ntcreate(cli1,
8451 READ_CONTROL_ACCESS,
8453 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
8460 if (!NT_STATUS_IS_OK(status)) {
8461 printf("cli_ntcreate of %s failed (%s)\n",
8467 status = cli_close(cli1, fnum1);
8468 if (!NT_STATUS_IS_OK(status)) {
8469 printf("cli_close of %s failed (%s)\n",
8474 fnum1 = (uint16_t)-1;
8476 /* Now create the stream. */
8477 status = cli_ntcreate(cli1,
8482 FILE_SHARE_READ|FILE_SHARE_WRITE,
8489 if (!NT_STATUS_IS_OK(status)) {
8490 printf("cli_ntcreate of %s failed (%s)\n",
8496 /* Leave the stream handle open... */
8498 /* POSIX unlink should fail. */
8499 status = cli_posix_unlink(cli2, fname);
8500 if (NT_STATUS_IS_OK(status)) {
8501 printf("cli_posix_unlink of %s succeeded, should have failed\n",
8506 if (!NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
8507 printf("cli_posix_unlink of %s failed with (%s) "
8508 "should have been NT_STATUS_SHARING_VIOLATION\n",
8514 /* Close the stream handle. */
8515 status = cli_close(cli1, fnum1);
8516 if (!NT_STATUS_IS_OK(status)) {
8517 printf("cli_close of %s failed (%s)\n",
8522 fnum1 = (uint16_t)-1;
8524 /* POSIX unlink after stream handle closed should succeed. */
8525 status = cli_posix_unlink(cli2, fname);
8526 if (!NT_STATUS_IS_OK(status)) {
8527 printf("cli_posix_unlink of %s failed (%s)\n",
8533 printf("POSIX stream delete test passed\n");
8538 if (fnum1 != (uint16_t)-1) {
8539 cli_close(cli1, fnum1);
8540 fnum1 = (uint16_t)-1;
8543 cli_setatr(cli1, fname, 0, 0);
8544 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
8546 if (!torture_close_connection(cli1)) {
8549 if (!torture_close_connection(cli2)) {
8558 Test setting EA's are rejected on symlinks.
8560 static bool run_ea_symlink_test(int dummy)
8562 static struct cli_state *cli;
8563 const char *fname = "posix_file_ea";
8564 const char *sname = "posix_symlink_ea";
8565 const char *ea_name = "testea_name";
8566 const char *ea_value = "testea_value";
8567 uint16_t fnum = (uint16_t)-1;
8568 bool correct = false;
8571 struct ea_struct *eas = NULL;
8572 TALLOC_CTX *frame = NULL;
8574 frame = talloc_stackframe();
8576 printf("Starting EA symlink test\n");
8578 if (!torture_open_connection(&cli, 0)) {
8583 smbXcli_conn_set_sockopt(cli->conn, sockops);
8585 status = torture_setup_unix_extensions(cli);
8586 if (!NT_STATUS_IS_OK(status)) {
8591 cli_setatr(cli, fname, 0, 0);
8592 cli_posix_unlink(cli, fname);
8593 cli_setatr(cli, sname, 0, 0);
8594 cli_posix_unlink(cli, sname);
8596 status = cli_ntcreate(cli,
8599 READ_CONTROL_ACCESS,
8601 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
8608 if (!NT_STATUS_IS_OK(status)) {
8609 printf("cli_ntcreate of %s failed (%s)\n",
8615 status = cli_close(cli, fnum);
8616 if (!NT_STATUS_IS_OK(status)) {
8617 printf("close failed (%s)\n",
8621 fnum = (uint16_t)-1;
8623 /* Set an EA on the path. */
8624 status = cli_set_ea_path(cli,
8628 strlen(ea_value)+1);
8630 if (!NT_STATUS_IS_OK(status)) {
8631 printf("cli_set_ea_path failed (%s)\n",
8636 /* Now create a symlink. */
8637 status = cli_posix_symlink(cli, fname, sname);
8638 if (!NT_STATUS_IS_OK(status)) {
8639 printf("cli_posix_symlink of %s -> %s failed (%s)\n",
8646 /* Get the EA list on the path. Should return value set. */
8647 status = cli_get_ea_list_path(cli,
8653 if (!NT_STATUS_IS_OK(status)) {
8654 printf("cli_get_ea_list_path failed (%s)\n",
8659 /* Ensure the EA we set is there. */
8660 for (i=0; i<num_eas; i++) {
8661 if (strcmp(eas[i].name, ea_name) == 0 &&
8662 eas[i].value.length == strlen(ea_value)+1 &&
8663 memcmp(eas[i].value.data,
8665 eas[i].value.length) == 0) {
8671 printf("Didn't find EA on pathname %s\n",
8679 /* Get the EA list on the symlink. Should return empty list. */
8680 status = cli_get_ea_list_path(cli,
8686 if (!NT_STATUS_IS_OK(status)) {
8687 printf("cli_get_ea_list_path failed (%s)\n",
8693 printf("cli_get_ea_list_path failed (%s)\n",
8698 /* Set an EA on the symlink. Should fail. */
8699 status = cli_set_ea_path(cli,
8703 strlen(ea_value)+1);
8705 if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
8706 printf("cli_set_ea_path on a symlink gave %s. "
8707 "Should be NT_STATUS_ACCESS_DENIED.\n",
8712 printf("EA symlink test passed\n");
8717 if (fnum != (uint16_t)-1) {
8718 cli_close(cli, fnum);
8719 fnum = (uint16_t)-1;
8722 cli_setatr(cli, sname, 0, 0);
8723 cli_posix_unlink(cli, sname);
8724 cli_setatr(cli, fname, 0, 0);
8725 cli_posix_unlink(cli, fname);
8727 if (!torture_close_connection(cli)) {
8736 Test POSIX locks are OFD-locks.
8738 static bool run_posix_ofd_lock_test(int dummy)
8740 static struct cli_state *cli;
8741 const char *fname = "posix_file";
8742 uint16_t fnum1 = (uint16_t)-1;
8743 uint16_t fnum2 = (uint16_t)-1;
8744 bool correct = false;
8746 TALLOC_CTX *frame = NULL;
8748 frame = talloc_stackframe();
8750 printf("Starting POSIX ofd-lock test\n");
8752 if (!torture_open_connection(&cli, 0)) {
8757 smbXcli_conn_set_sockopt(cli->conn, sockops);
8759 status = torture_setup_unix_extensions(cli);
8760 if (!NT_STATUS_IS_OK(status)) {
8765 cli_setatr(cli, fname, 0, 0);
8766 cli_posix_unlink(cli, fname);
8768 /* Open the file twice. */
8769 status = cli_posix_open(cli, fname, O_RDWR|O_CREAT|O_EXCL,
8771 if (!NT_STATUS_IS_OK(status)) {
8772 printf("First POSIX open of %s failed\n", fname);
8776 status = cli_posix_open(cli, fname, O_RDWR, 0, &fnum2);
8777 if (!NT_STATUS_IS_OK(status)) {
8778 printf("First POSIX open of %s failed\n", fname);
8782 /* Set a 0-50 lock on fnum1. */
8783 status = cli_posix_lock(cli, fnum1, 0, 50, false, WRITE_LOCK);
8784 if (!NT_STATUS_IS_OK(status)) {
8785 printf("POSIX lock (1) failed %s\n", nt_errstr(status));
8789 /* Set a 60-100 lock on fnum2. */
8790 status = cli_posix_lock(cli, fnum2, 60, 100, false, WRITE_LOCK);
8791 if (!NT_STATUS_IS_OK(status)) {
8792 printf("POSIX lock (2) failed %s\n", nt_errstr(status));
8796 /* close fnum1 - 0-50 lock should go away. */
8797 status = cli_close(cli, fnum1);
8798 if (!NT_STATUS_IS_OK(status)) {
8799 printf("close failed (%s)\n",
8803 fnum1 = (uint16_t)-1;
8805 /* Change the lock context. */
8806 cli_setpid(cli, cli_getpid(cli) + 1);
8808 /* Re-open fnum1. */
8809 status = cli_posix_open(cli, fname, O_RDWR, 0, &fnum1);
8810 if (!NT_STATUS_IS_OK(status)) {
8811 printf("Third POSIX open of %s failed\n", fname);
8815 /* 60-100 lock should still be there. */
8816 status = cli_posix_lock(cli, fnum1, 60, 100, false, WRITE_LOCK);
8817 if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
8818 printf("POSIX lock 60-100 not there %s\n", nt_errstr(status));
8822 /* 0-50 lock should be gone. */
8823 status = cli_posix_lock(cli, fnum1, 0, 50, false, WRITE_LOCK);
8824 if (!NT_STATUS_IS_OK(status)) {
8825 printf("POSIX lock 0-50 failed %s\n", nt_errstr(status));
8829 printf("POSIX OFD lock test passed\n");
8834 if (fnum1 != (uint16_t)-1) {
8835 cli_close(cli, fnum1);
8836 fnum1 = (uint16_t)-1;
8838 if (fnum2 != (uint16_t)-1) {
8839 cli_close(cli, fnum2);
8840 fnum2 = (uint16_t)-1;
8843 cli_setatr(cli, fname, 0, 0);
8844 cli_posix_unlink(cli, fname);
8846 if (!torture_close_connection(cli)) {
8854 struct posix_blocking_state {
8855 struct tevent_context *ev;
8856 struct cli_state *cli1;
8858 struct cli_state *cli2;
8864 static void posix_blocking_locked(struct tevent_req *subreq);
8865 static void posix_blocking_gotblocked(struct tevent_req *subreq);
8866 static void posix_blocking_gotecho(struct tevent_req *subreq);
8867 static void posix_blocking_unlocked(struct tevent_req *subreq);
8869 static struct tevent_req *posix_blocking_send(
8870 TALLOC_CTX *mem_ctx,
8871 struct tevent_context *ev,
8872 struct cli_state *cli1,
8874 struct cli_state *cli2,
8877 struct tevent_req *req = NULL, *subreq = NULL;
8878 struct posix_blocking_state *state = NULL;
8880 req = tevent_req_create(mem_ctx, &state, struct posix_blocking_state);
8886 state->fnum1 = fnum1;
8888 state->fnum2 = fnum2;
8890 subreq = cli_posix_lock_send(
8899 if (tevent_req_nomem(subreq, req)) {
8900 return tevent_req_post(req, ev);
8902 tevent_req_set_callback(subreq, posix_blocking_locked, req);
8906 static void posix_blocking_locked(struct tevent_req *subreq)
8908 struct tevent_req *req = tevent_req_callback_data(
8909 subreq, struct tevent_req);
8910 struct posix_blocking_state *state = tevent_req_data(
8911 req, struct posix_blocking_state);
8914 status = cli_posix_lock_recv(subreq);
8915 TALLOC_FREE(subreq);
8916 if (tevent_req_nterror(req, status)) {
8920 subreq = cli_posix_lock_send(
8929 if (tevent_req_nomem(subreq, req)) {
8932 tevent_req_set_callback(subreq, posix_blocking_gotblocked, req);
8934 /* Make sure the blocking request is delivered */
8935 subreq = cli_echo_send(
8940 (DATA_BLOB) { .data = (uint8_t *)state, .length = 1 });
8941 if (tevent_req_nomem(subreq, req)) {
8944 tevent_req_set_callback(subreq, posix_blocking_gotecho, req);
8947 static void posix_blocking_gotblocked(struct tevent_req *subreq)
8949 struct tevent_req *req = tevent_req_callback_data(
8950 subreq, struct tevent_req);
8951 struct posix_blocking_state *state = tevent_req_data(
8952 req, struct posix_blocking_state);
8955 status = cli_posix_lock_recv(subreq);
8956 TALLOC_FREE(subreq);
8957 if (tevent_req_nterror(req, status)) {
8960 if (!state->gotecho) {
8961 printf("blocked req got through before echo\n");
8962 tevent_req_nterror(req, NT_STATUS_INVALID_LOCK_SEQUENCE);
8965 tevent_req_done(req);
8968 static void posix_blocking_gotecho(struct tevent_req *subreq)
8970 struct tevent_req *req = tevent_req_callback_data(
8971 subreq, struct tevent_req);
8972 struct posix_blocking_state *state = tevent_req_data(
8973 req, struct posix_blocking_state);
8976 status = cli_echo_recv(subreq);
8977 TALLOC_FREE(subreq);
8978 if (tevent_req_nterror(req, status)) {
8981 if (state->gotblocked) {
8982 printf("blocked req got through before echo\n");
8983 tevent_req_nterror(req, NT_STATUS_INVALID_LOCK_SEQUENCE);
8986 state->gotecho = true;
8988 subreq = cli_posix_lock_send(
8997 if (tevent_req_nomem(subreq, req)) {
9000 tevent_req_set_callback(subreq, posix_blocking_unlocked, req);
9003 static void posix_blocking_unlocked(struct tevent_req *subreq)
9005 struct tevent_req *req = tevent_req_callback_data(
9006 subreq, struct tevent_req);
9009 status = cli_posix_lock_recv(subreq);
9010 TALLOC_FREE(subreq);
9011 if (tevent_req_nterror(req, status)) {
9014 /* tevent_req_done in posix_blocking_gotlocked */
9017 static NTSTATUS posix_blocking_recv(struct tevent_req *req)
9019 return tevent_req_simple_recv_ntstatus(req);
9022 static bool run_posix_blocking_lock(int dummy)
9024 struct tevent_context *ev = NULL;
9025 struct cli_state *cli1 = NULL, *cli2 = NULL;
9026 const char *fname = "posix_blocking";
9027 uint16_t fnum1 = UINT16_MAX, fnum2 = UINT16_MAX;
9028 struct tevent_req *req = NULL;
9033 printf("Starting posix blocking lock test\n");
9035 ev = samba_tevent_context_init(NULL);
9040 ok = torture_open_connection(&cli1, 0);
9044 ok = torture_open_connection(&cli2, 0);
9049 smbXcli_conn_set_sockopt(cli1->conn, sockops);
9051 status = torture_setup_unix_extensions(cli1);
9052 if (!NT_STATUS_IS_OK(status)) {
9056 status = torture_setup_unix_extensions(cli2);
9057 if (!NT_STATUS_IS_OK(status)) {
9061 cli_setatr(cli1, fname, 0, 0);
9062 cli_posix_unlink(cli1, fname);
9064 status = cli_posix_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL,
9066 if (!NT_STATUS_IS_OK(status)) {
9067 printf("First POSIX open of %s failed: %s\n",
9073 status = cli_posix_open(cli2, fname, O_RDWR, 0600, &fnum2);
9074 if (!NT_STATUS_IS_OK(status)) {
9075 printf("Second POSIX open of %s failed: %s\n",
9081 req = posix_blocking_send(ev, ev, cli1, fnum1, cli2, fnum2);
9083 printf("cli_posix_blocking failed\n");
9087 ok = tevent_req_poll_ntstatus(req, ev, &status);
9089 printf("tevent_req_poll_ntstatus failed: %s\n",
9093 status = posix_blocking_recv(req);
9095 if (!NT_STATUS_IS_OK(status)) {
9096 printf("posix_blocking_recv returned %s\n",
9104 if (fnum1 != UINT16_MAX) {
9105 cli_close(cli1, fnum1);
9108 if (fnum2 != UINT16_MAX) {
9109 cli_close(cli2, fnum2);
9114 cli_setatr(cli1, fname, 0, 0);
9115 cli_posix_unlink(cli1, fname);
9121 ok &= torture_close_connection(cli1);
9125 ok &= torture_close_connection(cli2);
9137 Test POSIX mkdir is case-sensitive.
9139 static bool run_posix_mkdir_test(int dummy)
9141 static struct cli_state *cli;
9142 const char *fname_foo = "POSIX_foo";
9143 const char *fname_foo_Foo = "POSIX_foo/Foo";
9144 const char *fname_foo_foo = "POSIX_foo/foo";
9145 const char *fname_Foo = "POSIX_Foo";
9146 const char *fname_Foo_Foo = "POSIX_Foo/Foo";
9147 const char *fname_Foo_foo = "POSIX_Foo/foo";
9148 bool correct = false;
9150 TALLOC_CTX *frame = NULL;
9151 uint16_t fnum = (uint16_t)-1;
9153 frame = talloc_stackframe();
9155 printf("Starting POSIX mkdir test\n");
9157 if (!torture_open_connection(&cli, 0)) {
9162 smbXcli_conn_set_sockopt(cli->conn, sockops);
9164 status = torture_setup_unix_extensions(cli);
9165 if (!NT_STATUS_IS_OK(status)) {
9170 cli_posix_rmdir(cli, fname_foo_foo);
9171 cli_posix_rmdir(cli, fname_foo_Foo);
9172 cli_posix_rmdir(cli, fname_foo);
9174 cli_posix_rmdir(cli, fname_Foo_foo);
9175 cli_posix_rmdir(cli, fname_Foo_Foo);
9176 cli_posix_rmdir(cli, fname_Foo);
9179 * Create a file POSIX_foo then try
9180 * and use it in a directory path by
9181 * doing mkdir POSIX_foo/bar.
9182 * The mkdir should fail with
9183 * NT_STATUS_OBJECT_PATH_NOT_FOUND
9186 status = cli_posix_open(cli,
9191 if (!NT_STATUS_IS_OK(status)) {
9192 printf("cli_posix_open of %s failed error %s\n",
9198 status = cli_posix_mkdir(cli, fname_foo_foo, 0777);
9199 if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_PATH_NOT_FOUND)) {
9200 printf("cli_posix_mkdir of %s should fail with "
9201 "NT_STATUS_OBJECT_PATH_NOT_FOUND got "
9208 status = cli_close(cli, fnum);
9209 if (!NT_STATUS_IS_OK(status)) {
9210 printf("cli_close failed %s\n", nt_errstr(status));
9213 fnum = (uint16_t)-1;
9215 status = cli_posix_unlink(cli, fname_foo);
9216 if (!NT_STATUS_IS_OK(status)) {
9217 printf("cli_posix_unlink of %s failed error %s\n",
9224 * Now we've deleted everything, posix_mkdir, posix_rmdir,
9225 * posix_open, posix_unlink, on
9226 * POSIX_foo/foo should return NT_STATUS_OBJECT_PATH_NOT_FOUND
9227 * not silently create POSIX_foo/foo.
9230 status = cli_posix_mkdir(cli, fname_foo_foo, 0777);
9231 if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_PATH_NOT_FOUND)) {
9232 printf("cli_posix_mkdir of %s should fail with "
9233 "NT_STATUS_OBJECT_PATH_NOT_FOUND got "
9240 status = cli_posix_rmdir(cli, fname_foo_foo);
9241 if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_PATH_NOT_FOUND)) {
9242 printf("cli_posix_rmdir of %s should fail with "
9243 "NT_STATUS_OBJECT_PATH_NOT_FOUND got "
9250 status = cli_posix_open(cli,
9255 if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_PATH_NOT_FOUND)) {
9256 printf("cli_posix_open of %s should fail with "
9257 "NT_STATUS_OBJECT_PATH_NOT_FOUND got "
9264 status = cli_posix_unlink(cli, fname_foo_foo);
9265 if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_PATH_NOT_FOUND)) {
9266 printf("cli_posix_unlink of %s should fail with "
9267 "NT_STATUS_OBJECT_PATH_NOT_FOUND got "
9274 status = cli_posix_mkdir(cli, fname_foo, 0777);
9275 if (!NT_STATUS_IS_OK(status)) {
9276 printf("cli_posix_mkdir of %s failed\n", fname_foo);
9280 status = cli_posix_mkdir(cli, fname_Foo, 0777);
9281 if (!NT_STATUS_IS_OK(status)) {
9282 printf("cli_posix_mkdir of %s failed\n", fname_Foo);
9286 status = cli_posix_mkdir(cli, fname_foo_foo, 0777);
9287 if (!NT_STATUS_IS_OK(status)) {
9288 printf("cli_posix_mkdir of %s failed\n", fname_foo_foo);
9292 status = cli_posix_mkdir(cli, fname_foo_Foo, 0777);
9293 if (!NT_STATUS_IS_OK(status)) {
9294 printf("cli_posix_mkdir of %s failed\n", fname_foo_Foo);
9298 status = cli_posix_mkdir(cli, fname_Foo_foo, 0777);
9299 if (!NT_STATUS_IS_OK(status)) {
9300 printf("cli_posix_mkdir of %s failed\n", fname_Foo_foo);
9304 status = cli_posix_mkdir(cli, fname_Foo_Foo, 0777);
9305 if (!NT_STATUS_IS_OK(status)) {
9306 printf("cli_posix_mkdir of %s failed\n", fname_Foo_Foo);
9310 printf("POSIX mkdir test passed\n");
9315 if (fnum != (uint16_t)-1) {
9316 cli_close(cli, fnum);
9317 fnum = (uint16_t)-1;
9320 cli_posix_rmdir(cli, fname_foo_foo);
9321 cli_posix_rmdir(cli, fname_foo_Foo);
9322 cli_posix_rmdir(cli, fname_foo);
9324 cli_posix_rmdir(cli, fname_Foo_foo);
9325 cli_posix_rmdir(cli, fname_Foo_Foo);
9326 cli_posix_rmdir(cli, fname_Foo);
9328 if (!torture_close_connection(cli)) {
9336 struct posix_acl_oplock_state {
9337 struct tevent_context *ev;
9338 struct cli_state *cli;
9344 static void posix_acl_oplock_got_break(struct tevent_req *req)
9346 struct posix_acl_oplock_state *state = tevent_req_callback_data(
9347 req, struct posix_acl_oplock_state);
9352 status = cli_smb_oplock_break_waiter_recv(req, &fnum, &level);
9354 if (!NT_STATUS_IS_OK(status)) {
9355 printf("cli_smb_oplock_break_waiter_recv returned %s\n",
9359 *state->got_break = true;
9361 req = cli_oplock_ack_send(state, state->ev, state->cli, fnum,
9364 printf("cli_oplock_ack_send failed\n");
9369 static void posix_acl_oplock_got_acl(struct tevent_req *req)
9371 struct posix_acl_oplock_state *state = tevent_req_callback_data(
9372 req, struct posix_acl_oplock_state);
9373 size_t ret_size = 0;
9374 char *ret_data = NULL;
9376 state->status = cli_posix_getacl_recv(req,
9381 if (!NT_STATUS_IS_OK(state->status)) {
9382 printf("cli_posix_getacl_recv returned %s\n",
9383 nt_errstr(state->status));
9385 *state->acl_ret = true;
9388 static bool run_posix_acl_oplock_test(int dummy)
9390 struct tevent_context *ev;
9391 struct cli_state *cli1, *cli2;
9392 struct tevent_req *oplock_req, *getacl_req;
9393 const char *fname = "posix_acl_oplock";
9395 int saved_use_oplocks = use_oplocks;
9397 bool correct = true;
9398 bool got_break = false;
9399 bool acl_ret = false;
9401 struct posix_acl_oplock_state *state;
9403 printf("starting posix_acl_oplock test\n");
9405 if (!torture_open_connection(&cli1, 0)) {
9406 use_level_II_oplocks = false;
9407 use_oplocks = saved_use_oplocks;
9411 if (!torture_open_connection(&cli2, 1)) {
9412 use_level_II_oplocks = false;
9413 use_oplocks = saved_use_oplocks;
9417 /* Setup posix on cli2 only. */
9418 status = torture_setup_unix_extensions(cli2);
9419 if (!NT_STATUS_IS_OK(status)) {
9423 smbXcli_conn_set_sockopt(cli1->conn, sockops);
9424 smbXcli_conn_set_sockopt(cli2->conn, sockops);
9426 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
9428 /* Create the file on the Windows connection. */
9429 status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
9431 if (!NT_STATUS_IS_OK(status)) {
9432 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
9436 status = cli_close(cli1, fnum);
9437 if (!NT_STATUS_IS_OK(status)) {
9438 printf("close1 failed (%s)\n", nt_errstr(status));
9442 cli1->use_oplocks = true;
9444 /* Open with oplock. */
9445 status = cli_ntcreate(cli1,
9449 FILE_ATTRIBUTE_NORMAL,
9450 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
9457 if (!NT_STATUS_IS_OK(status)) {
9458 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
9462 ev = samba_tevent_context_init(talloc_tos());
9464 printf("tevent_context_init failed\n");
9468 state = talloc_zero(ev, struct posix_acl_oplock_state);
9469 if (state == NULL) {
9470 printf("talloc failed\n");
9475 state->got_break = &got_break;
9476 state->acl_ret = &acl_ret;
9478 oplock_req = cli_smb_oplock_break_waiter_send(
9479 talloc_tos(), ev, cli1);
9480 if (oplock_req == NULL) {
9481 printf("cli_smb_oplock_break_waiter_send failed\n");
9484 tevent_req_set_callback(oplock_req, posix_acl_oplock_got_break, state);
9486 /* Get ACL on POSIX connection - should break oplock. */
9487 getacl_req = cli_posix_getacl_send(talloc_tos(),
9491 if (getacl_req == NULL) {
9492 printf("cli_posix_getacl_send failed\n");
9495 tevent_req_set_callback(getacl_req, posix_acl_oplock_got_acl, state);
9497 while (!got_break || !acl_ret) {
9499 ret = tevent_loop_once(ev);
9501 printf("tevent_loop_once failed: %s\n",
9507 if (!NT_STATUS_IS_OK(state->status)) {
9508 printf("getacl failed (%s)\n", nt_errstr(state->status));
9512 status = cli_close(cli1, fnum);
9513 if (!NT_STATUS_IS_OK(status)) {
9514 printf("close2 failed (%s)\n", nt_errstr(status));
9518 status = cli_unlink(cli1,
9520 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
9521 if (!NT_STATUS_IS_OK(status)) {
9522 printf("unlink failed (%s)\n", nt_errstr(status));
9526 if (!torture_close_connection(cli1)) {
9529 if (!torture_close_connection(cli2)) {
9537 printf("finished posix acl oplock test\n");
9542 static bool run_posix_acl_shareroot_test(int dummy)
9544 struct cli_state *cli;
9546 bool correct = false;
9547 char *posix_acl = NULL;
9548 size_t posix_acl_len = 0;
9549 uint16_t num_file_acls = 0;
9550 uint16_t num_dir_acls = 0;
9552 uint32_t expected_size = 0;
9553 bool got_user = false;
9554 bool got_group = false;
9555 bool got_other = false;
9556 TALLOC_CTX *frame = NULL;
9558 frame = talloc_stackframe();
9560 printf("starting posix_acl_shareroot test\n");
9562 if (!torture_open_connection(&cli, 0)) {
9567 smbXcli_conn_set_sockopt(cli->conn, sockops);
9569 status = torture_setup_unix_extensions(cli);
9570 if (!NT_STATUS_IS_OK(status)) {
9571 printf("Failed to setup unix extensions\n");
9575 /* Get the POSIX ACL on the root of the share. */
9576 status = cli_posix_getacl(cli,
9582 if (!NT_STATUS_IS_OK(status)) {
9583 printf("cli_posix_getacl of '.' failed (%s)\n",
9588 if (posix_acl_len < 6 ||
9589 SVAL(posix_acl,0) != SMB_POSIX_ACL_VERSION) {
9590 printf("getfacl ., unknown POSIX acl version %u.\n",
9591 (unsigned int)CVAL(posix_acl,0) );
9595 num_file_acls = SVAL(posix_acl,2);
9596 num_dir_acls = SVAL(posix_acl,4);
9597 expected_size = SMB_POSIX_ACL_HEADER_SIZE +
9598 SMB_POSIX_ACL_ENTRY_SIZE*
9599 (num_file_acls+num_dir_acls);
9601 if (posix_acl_len != expected_size) {
9602 printf("incorrect POSIX acl buffer size "
9603 "(should be %u, was %u).\n",
9604 (unsigned int)expected_size,
9605 (unsigned int)posix_acl_len);
9610 * We don't need to know what the ACL's are
9611 * we just need to know we have at least 3
9612 * file entries (u,g,o).
9615 for (i = 0; i < num_file_acls; i++) {
9616 unsigned char tagtype =
9618 SMB_POSIX_ACL_HEADER_SIZE+
9619 (i*SMB_POSIX_ACL_ENTRY_SIZE));
9622 case SMB_POSIX_ACL_USER_OBJ:
9625 case SMB_POSIX_ACL_GROUP_OBJ:
9628 case SMB_POSIX_ACL_OTHER:
9637 printf("Missing user entry\n");
9642 printf("Missing group entry\n");
9647 printf("Missing other entry\n");
9655 if (!torture_close_connection(cli)) {
9659 printf("finished posix acl shareroot test\n");
9665 static uint32_t open_attrs_table[] = {
9666 FILE_ATTRIBUTE_NORMAL,
9667 FILE_ATTRIBUTE_ARCHIVE,
9668 FILE_ATTRIBUTE_READONLY,
9669 FILE_ATTRIBUTE_HIDDEN,
9670 FILE_ATTRIBUTE_SYSTEM,
9672 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY,
9673 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN,
9674 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM,
9675 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN,
9676 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM,
9677 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM,
9679 FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN,
9680 FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM,
9681 FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM,
9682 FILE_ATTRIBUTE_HIDDEN,FILE_ATTRIBUTE_SYSTEM,
9685 struct trunc_open_results {
9688 uint32_t trunc_attr;
9689 uint32_t result_attr;
9692 static struct trunc_open_results attr_results[] = {
9693 { 0, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_ARCHIVE },
9694 { 1, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_ARCHIVE },
9695 { 2, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_READONLY, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY },
9696 { 16, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_ARCHIVE },
9697 { 17, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_ARCHIVE },
9698 { 18, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_READONLY, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY },
9699 { 51, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
9700 { 54, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
9701 { 56, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN },
9702 { 68, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
9703 { 71, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
9704 { 73, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM },
9705 { 99, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_HIDDEN,FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
9706 { 102, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
9707 { 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 },
9708 { 116, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
9709 { 119, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
9710 { 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 },
9711 { 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 },
9712 { 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 },
9713 { 227, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
9714 { 230, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
9715 { 232, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN },
9716 { 244, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
9717 { 247, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
9718 { 249, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM }
9721 static bool run_openattrtest(int dummy)
9723 static struct cli_state *cli1;
9724 const char *fname = "\\openattr.file";
9726 bool correct = True;
9728 unsigned int i, j, k, l;
9731 printf("starting open attr test\n");
9733 if (!torture_open_connection(&cli1, 0)) {
9737 smbXcli_conn_set_sockopt(cli1->conn, sockops);
9739 for (k = 0, i = 0; i < sizeof(open_attrs_table)/sizeof(uint32_t); i++) {
9740 cli_setatr(cli1, fname, 0, 0);
9741 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
9743 status = cli_ntcreate(cli1, fname, 0, FILE_WRITE_DATA,
9744 open_attrs_table[i], FILE_SHARE_NONE,
9745 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
9746 if (!NT_STATUS_IS_OK(status)) {
9747 printf("open %d (1) of %s failed (%s)\n", i, fname, nt_errstr(status));
9751 status = cli_close(cli1, fnum1);
9752 if (!NT_STATUS_IS_OK(status)) {
9753 printf("close %d (1) of %s failed (%s)\n", i, fname, nt_errstr(status));
9757 for (j = 0; j < sizeof(open_attrs_table)/sizeof(uint32_t); j++) {
9758 status = cli_ntcreate(cli1, fname, 0,
9759 FILE_READ_DATA|FILE_WRITE_DATA,
9760 open_attrs_table[j],
9761 FILE_SHARE_NONE, FILE_OVERWRITE,
9762 0, 0, &fnum1, NULL);
9763 if (!NT_STATUS_IS_OK(status)) {
9764 for (l = 0; l < sizeof(attr_results)/sizeof(struct trunc_open_results); l++) {
9765 if (attr_results[l].num == k) {
9766 printf("[%d] trunc open 0x%x -> 0x%x of %s failed - should have succeeded !(0x%x:%s)\n",
9767 k, open_attrs_table[i],
9768 open_attrs_table[j],
9769 fname, NT_STATUS_V(status), nt_errstr(status));
9774 if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
9775 printf("[%d] trunc open 0x%x -> 0x%x failed with wrong error code %s\n",
9776 k, open_attrs_table[i], open_attrs_table[j],
9781 printf("[%d] trunc open 0x%x -> 0x%x failed\n", k, open_attrs_table[i], open_attrs_table[j]);
9787 status = cli_close(cli1, fnum1);
9788 if (!NT_STATUS_IS_OK(status)) {
9789 printf("close %d (2) of %s failed (%s)\n", j, fname, nt_errstr(status));
9793 status = cli_getatr(cli1, fname, &attr, NULL, NULL);
9794 if (!NT_STATUS_IS_OK(status)) {
9795 printf("getatr(2) failed (%s)\n", nt_errstr(status));
9800 printf("[%d] getatr check [0x%x] trunc [0x%x] got attr 0x%x\n",
9801 k, open_attrs_table[i], open_attrs_table[j], attr );
9804 for (l = 0; l < sizeof(attr_results)/sizeof(struct trunc_open_results); l++) {
9805 if (attr_results[l].num == k) {
9806 if (attr != attr_results[l].result_attr ||
9807 open_attrs_table[i] != attr_results[l].init_attr ||
9808 open_attrs_table[j] != attr_results[l].trunc_attr) {
9809 printf("getatr check failed. [0x%x] trunc [0x%x] got attr 0x%x, should be 0x%x\n",
9810 open_attrs_table[i],
9811 open_attrs_table[j],
9813 attr_results[l].result_attr);
9823 cli_setatr(cli1, fname, 0, 0);
9824 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
9826 printf("open attr test %s.\n", correct ? "passed" : "failed");
9828 if (!torture_close_connection(cli1)) {
9834 static NTSTATUS list_fn(struct file_info *finfo,
9835 const char *name, void *state)
9837 int *matched = (int *)state;
9838 if (matched != NULL) {
9841 return NT_STATUS_OK;
9845 test directory listing speed
9847 static bool run_dirtest(int dummy)
9850 static struct cli_state *cli;
9852 struct timeval core_start;
9853 bool correct = True;
9856 printf("starting directory test\n");
9858 if (!torture_open_connection(&cli, 0)) {
9862 smbXcli_conn_set_sockopt(cli->conn, sockops);
9865 for (i=0;i<torture_numops;i++) {
9867 slprintf(fname, sizeof(fname), "\\%x", (int)random());
9868 if (!NT_STATUS_IS_OK(cli_openx(cli, fname, O_RDWR|O_CREAT, DENY_NONE, &fnum))) {
9869 fprintf(stderr,"Failed to open %s\n", fname);
9872 cli_close(cli, fnum);
9875 core_start = timeval_current();
9878 cli_list(cli, "a*.*", 0, list_fn, &matched);
9879 printf("Matched %d\n", matched);
9882 cli_list(cli, "b*.*", 0, list_fn, &matched);
9883 printf("Matched %d\n", matched);
9886 cli_list(cli, "xyzabc", 0, list_fn, &matched);
9887 printf("Matched %d\n", matched);
9889 printf("dirtest core %g seconds\n", timeval_elapsed(&core_start));
9892 for (i=0;i<torture_numops;i++) {
9894 slprintf(fname, sizeof(fname), "\\%x", (int)random());
9895 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
9898 if (!torture_close_connection(cli)) {
9902 printf("finished dirtest\n");
9907 static NTSTATUS del_fn(struct file_info *finfo, const char *mask,
9910 struct cli_state *pcli = (struct cli_state *)state;
9912 slprintf(fname, sizeof(fname), "\\LISTDIR\\%s", finfo->name);
9914 if (strcmp(finfo->name, ".") == 0 || strcmp(finfo->name, "..") == 0)
9915 return NT_STATUS_OK;
9917 if (finfo->attr & FILE_ATTRIBUTE_DIRECTORY) {
9918 if (!NT_STATUS_IS_OK(cli_rmdir(pcli, fname)))
9919 printf("del_fn: failed to rmdir %s\n,", fname );
9921 if (!NT_STATUS_IS_OK(cli_unlink(pcli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN)))
9922 printf("del_fn: failed to unlink %s\n,", fname );
9924 return NT_STATUS_OK;
9929 send a raw ioctl - used by the torture code
9931 static NTSTATUS cli_raw_ioctl(struct cli_state *cli,
9939 PUSH_LE_U16(vwv + 0, 0, fnum);
9940 PUSH_LE_U16(vwv + 1, 0, code >> 16);
9941 PUSH_LE_U16(vwv + 2, 0, (code & 0xFFFF));
9943 status = cli_smb(talloc_tos(),
9957 if (!NT_STATUS_IS_OK(status)) {
9960 *blob = data_blob_null;
9961 return NT_STATUS_OK;
9965 sees what IOCTLs are supported
9967 bool torture_ioctl_test(int dummy)
9969 static struct cli_state *cli;
9970 uint16_t device, function;
9972 const char *fname = "\\ioctl.dat";
9976 if (!torture_open_connection(&cli, 0)) {
9980 printf("starting ioctl test\n");
9982 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
9984 status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
9985 if (!NT_STATUS_IS_OK(status)) {
9986 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
9990 status = cli_raw_ioctl(cli, fnum, 0x2d0000 | (0x0420<<2), &blob);
9991 printf("ioctl device info: %s\n", nt_errstr(status));
9993 status = cli_raw_ioctl(cli, fnum, IOCTL_QUERY_JOB_INFO, &blob);
9994 printf("ioctl job info: %s\n", nt_errstr(status));
9996 for (device=0;device<0x100;device++) {
9997 printf("ioctl test with device = 0x%x\n", device);
9998 for (function=0;function<0x100;function++) {
9999 uint32_t code = (device<<16) | function;
10001 status = cli_raw_ioctl(cli, fnum, code, &blob);
10003 if (NT_STATUS_IS_OK(status)) {
10004 printf("ioctl 0x%x OK : %d bytes\n", (int)code,
10006 data_blob_free(&blob);
10011 if (!torture_close_connection(cli)) {
10020 tries variants of chkpath
10022 bool torture_chkpath_test(int dummy)
10024 static struct cli_state *cli;
10029 if (!torture_open_connection(&cli, 0)) {
10033 printf("starting chkpath test\n");
10035 /* cleanup from an old run */
10036 torture_deltree(cli, "\\chkpath.dir");
10038 status = cli_mkdir(cli, "\\chkpath.dir");
10039 if (!NT_STATUS_IS_OK(status)) {
10040 printf("mkdir1 failed : %s\n", nt_errstr(status));
10044 status = cli_mkdir(cli, "\\chkpath.dir\\dir2");
10045 if (!NT_STATUS_IS_OK(status)) {
10046 printf("mkdir2 failed : %s\n", nt_errstr(status));
10050 status = cli_openx(cli, "\\chkpath.dir\\foo.txt", O_RDWR|O_CREAT|O_EXCL,
10052 if (!NT_STATUS_IS_OK(status)) {
10053 printf("open1 failed (%s)\n", nt_errstr(status));
10056 cli_close(cli, fnum);
10058 status = cli_chkpath(cli, "\\chkpath.dir");
10059 if (!NT_STATUS_IS_OK(status)) {
10060 printf("chkpath1 failed: %s\n", nt_errstr(status));
10064 status = cli_chkpath(cli, "\\chkpath.dir\\dir2");
10065 if (!NT_STATUS_IS_OK(status)) {
10066 printf("chkpath2 failed: %s\n", nt_errstr(status));
10070 status = cli_chkpath(cli, "\\chkpath.dir\\foo.txt");
10071 if (!NT_STATUS_IS_OK(status)) {
10072 ret = check_error(__LINE__, status, ERRDOS, ERRbadpath,
10073 NT_STATUS_NOT_A_DIRECTORY);
10075 printf("* chkpath on a file should fail\n");
10079 status = cli_chkpath(cli, "\\chkpath.dir\\bar.txt");
10080 if (!NT_STATUS_IS_OK(status)) {
10081 ret = check_error(__LINE__, status, ERRDOS, ERRbadfile,
10082 NT_STATUS_OBJECT_NAME_NOT_FOUND);
10084 printf("* chkpath on a non existent file should fail\n");
10088 status = cli_chkpath(cli, "\\chkpath.dir\\dirxx\\bar.txt");
10089 if (!NT_STATUS_IS_OK(status)) {
10090 ret = check_error(__LINE__, status, ERRDOS, ERRbadpath,
10091 NT_STATUS_OBJECT_PATH_NOT_FOUND);
10093 printf("* chkpath on a non existent component should fail\n");
10097 torture_deltree(cli, "\\chkpath.dir");
10099 if (!torture_close_connection(cli)) {
10106 static bool run_eatest(int dummy)
10108 static struct cli_state *cli;
10109 const char *fname = "\\eatest.txt";
10110 bool correct = True;
10113 struct ea_struct *ea_list = NULL;
10114 TALLOC_CTX *mem_ctx = talloc_init("eatest");
10117 printf("starting eatest\n");
10119 if (!torture_open_connection(&cli, 0)) {
10120 talloc_destroy(mem_ctx);
10124 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
10126 status = cli_ntcreate(cli, fname, 0,
10127 FIRST_DESIRED_ACCESS, FILE_ATTRIBUTE_ARCHIVE,
10128 FILE_SHARE_NONE, FILE_OVERWRITE_IF,
10129 0x4044, 0, &fnum, NULL);
10130 if (!NT_STATUS_IS_OK(status)) {
10131 printf("open failed - %s\n", nt_errstr(status));
10132 talloc_destroy(mem_ctx);
10136 for (i = 0; i < 10; i++) {
10137 fstring ea_name, ea_val;
10139 slprintf(ea_name, sizeof(ea_name), "EA_%zu", i);
10140 memset(ea_val, (char)i+1, i+1);
10141 status = cli_set_ea_fnum(cli, fnum, ea_name, ea_val, i+1);
10142 if (!NT_STATUS_IS_OK(status)) {
10143 printf("ea_set of name %s failed - %s\n", ea_name,
10144 nt_errstr(status));
10145 talloc_destroy(mem_ctx);
10150 cli_close(cli, fnum);
10151 for (i = 0; i < 10; i++) {
10152 fstring ea_name, ea_val;
10154 slprintf(ea_name, sizeof(ea_name), "EA_%zu", i+10);
10155 memset(ea_val, (char)i+1, i+1);
10156 status = cli_set_ea_path(cli, fname, ea_name, ea_val, i+1);
10157 if (!NT_STATUS_IS_OK(status)) {
10158 printf("ea_set of name %s failed - %s\n", ea_name,
10159 nt_errstr(status));
10160 talloc_destroy(mem_ctx);
10165 status = cli_get_ea_list_path(cli, fname, mem_ctx, &num_eas, &ea_list);
10166 if (!NT_STATUS_IS_OK(status)) {
10167 printf("ea_get list failed - %s\n", nt_errstr(status));
10171 printf("num_eas = %d\n", (int)num_eas);
10173 if (num_eas != 20) {
10174 printf("Should be 20 EA's stored... failing.\n");
10178 for (i = 0; i < num_eas; i++) {
10179 printf("%zu: ea_name = %s. Val = ", i, ea_list[i].name);
10180 dump_data(0, ea_list[i].value.data,
10181 ea_list[i].value.length);
10184 /* Setting EA's to zero length deletes them. Test this */
10185 printf("Now deleting all EA's - case independent....\n");
10188 cli_set_ea_path(cli, fname, "", "", 0);
10190 for (i = 0; i < 20; i++) {
10192 slprintf(ea_name, sizeof(ea_name), "ea_%d", i);
10193 status = cli_set_ea_path(cli, fname, ea_name, "", 0);
10194 if (!NT_STATUS_IS_OK(status)) {
10195 printf("ea_set of name %s failed - %s\n", ea_name,
10196 nt_errstr(status));
10197 talloc_destroy(mem_ctx);
10203 status = cli_get_ea_list_path(cli, fname, mem_ctx, &num_eas, &ea_list);
10204 if (!NT_STATUS_IS_OK(status)) {
10205 printf("ea_get list failed - %s\n", nt_errstr(status));
10209 printf("num_eas = %d\n", (int)num_eas);
10210 for (i = 0; i < num_eas; i++) {
10211 printf("%zu: ea_name = %s. Val = ", i, ea_list[i].name);
10212 dump_data(0, ea_list[i].value.data,
10213 ea_list[i].value.length);
10216 if (num_eas != 0) {
10217 printf("deleting EA's failed.\n");
10221 /* Try and delete a non existent EA. */
10222 status = cli_set_ea_path(cli, fname, "foo", "", 0);
10223 if (!NT_STATUS_IS_OK(status)) {
10224 printf("deleting non-existent EA 'foo' should succeed. %s\n",
10225 nt_errstr(status));
10229 talloc_destroy(mem_ctx);
10230 if (!torture_close_connection(cli)) {
10237 static bool run_dirtest1(int dummy)
10240 static struct cli_state *cli;
10243 bool correct = True;
10245 printf("starting directory test\n");
10247 if (!torture_open_connection(&cli, 0)) {
10251 smbXcli_conn_set_sockopt(cli->conn, sockops);
10253 cli_list(cli, "\\LISTDIR\\*", 0, del_fn, cli);
10254 cli_list(cli, "\\LISTDIR\\*", FILE_ATTRIBUTE_DIRECTORY, del_fn, cli);
10255 cli_rmdir(cli, "\\LISTDIR");
10256 cli_mkdir(cli, "\\LISTDIR");
10258 /* Create 1000 files and 1000 directories. */
10259 for (i=0;i<1000;i++) {
10261 slprintf(fname, sizeof(fname), "\\LISTDIR\\f%d", i);
10262 if (!NT_STATUS_IS_OK(cli_ntcreate(cli, fname, 0, GENERIC_ALL_ACCESS, FILE_ATTRIBUTE_ARCHIVE,
10263 FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OVERWRITE_IF,
10264 0, 0, &fnum, NULL))) {
10265 fprintf(stderr,"Failed to open %s\n", fname);
10268 cli_close(cli, fnum);
10270 for (i=0;i<1000;i++) {
10272 slprintf(fname, sizeof(fname), "\\LISTDIR\\d%d", i);
10273 if (!NT_STATUS_IS_OK(cli_mkdir(cli, fname))) {
10274 fprintf(stderr,"Failed to open %s\n", fname);
10279 /* Now ensure that doing an old list sees both files and directories. */
10281 cli_list_old(cli, "\\LISTDIR\\*", FILE_ATTRIBUTE_DIRECTORY, list_fn, &num_seen);
10282 printf("num_seen = %d\n", num_seen );
10283 /* We should see 100 files + 1000 directories + . and .. */
10284 if (num_seen != 2002)
10287 /* Ensure if we have the "must have" bits we only see the
10288 * relevant entries.
10291 cli_list_old(cli, "\\LISTDIR\\*", (FILE_ATTRIBUTE_DIRECTORY<<8)|FILE_ATTRIBUTE_DIRECTORY, list_fn, &num_seen);
10292 printf("num_seen = %d\n", num_seen );
10293 if (num_seen != 1002)
10297 cli_list_old(cli, "\\LISTDIR\\*", (FILE_ATTRIBUTE_ARCHIVE<<8)|FILE_ATTRIBUTE_DIRECTORY, list_fn, &num_seen);
10298 printf("num_seen = %d\n", num_seen );
10299 if (num_seen != 1000)
10302 /* Delete everything. */
10303 cli_list(cli, "\\LISTDIR\\*", 0, del_fn, cli);
10304 cli_list(cli, "\\LISTDIR\\*", FILE_ATTRIBUTE_DIRECTORY, del_fn, cli);
10305 cli_rmdir(cli, "\\LISTDIR");
10308 printf("Matched %d\n", cli_list(cli, "a*.*", 0, list_fn, NULL));
10309 printf("Matched %d\n", cli_list(cli, "b*.*", 0, list_fn, NULL));
10310 printf("Matched %d\n", cli_list(cli, "xyzabc", 0, list_fn, NULL));
10313 if (!torture_close_connection(cli)) {
10317 printf("finished dirtest1\n");
10322 static bool run_error_map_extract(int dummy) {
10324 static struct cli_state *c_dos;
10325 static struct cli_state *c_nt;
10333 NTSTATUS nt_status;
10337 /* NT-Error connection */
10339 disable_spnego = true;
10340 if (!(c_nt = open_nbt_connection())) {
10341 disable_spnego = false;
10344 disable_spnego = false;
10346 status = smbXcli_negprot(c_nt->conn,
10354 if (!NT_STATUS_IS_OK(status)) {
10355 printf("%s rejected the NT-error negprot (%s)\n", host,
10356 nt_errstr(status));
10357 cli_shutdown(c_nt);
10361 status = cli_session_setup_anon(c_nt);
10362 if (!NT_STATUS_IS_OK(status)) {
10363 printf("%s rejected the NT-error initial session setup (%s)\n",host, nt_errstr(status));
10367 /* DOS-Error connection */
10369 disable_spnego = true;
10370 force_dos_errors = true;
10371 if (!(c_dos = open_nbt_connection())) {
10372 disable_spnego = false;
10373 force_dos_errors = false;
10376 disable_spnego = false;
10377 force_dos_errors = false;
10379 status = smbXcli_negprot(c_dos->conn,
10386 if (!NT_STATUS_IS_OK(status)) {
10387 printf("%s rejected the DOS-error negprot (%s)\n", host,
10388 nt_errstr(status));
10389 cli_shutdown(c_dos);
10393 status = cli_session_setup_anon(c_dos);
10394 if (!NT_STATUS_IS_OK(status)) {
10395 printf("%s rejected the DOS-error initial session setup (%s)\n",
10396 host, nt_errstr(status));
10400 c_nt->map_dos_errors = false;
10401 c_dos->map_dos_errors = false;
10403 for (error=(0xc0000000 | 0x1); error < (0xc0000000| 0xFFF); error++) {
10404 struct cli_credentials *user_creds = NULL;
10406 fstr_sprintf(user, "%X", error);
10408 user_creds = cli_session_creds_init(talloc_tos(),
10413 false, /* use_kerberos */
10414 false, /* fallback_after_kerberos */
10415 false, /* use_ccache */
10416 false); /* password_is_nt_hash */
10417 if (user_creds == NULL) {
10418 printf("cli_session_creds_init(%s) failed\n", user);
10422 status = cli_session_setup_creds(c_nt, user_creds);
10423 if (NT_STATUS_IS_OK(status)) {
10424 printf("/** Session setup succeeded. This shouldn't happen...*/\n");
10427 /* Case #1: 32-bit NT errors */
10428 if (!NT_STATUS_IS_DOS(status)) {
10429 nt_status = status;
10431 printf("/** Dos error on NT connection! (%s) */\n",
10432 nt_errstr(status));
10433 nt_status = NT_STATUS(0xc0000000);
10436 status = cli_session_setup_creds(c_dos, user_creds);
10437 if (NT_STATUS_IS_OK(status)) {
10438 printf("/** Session setup succeeded. This shouldn't happen...*/\n");
10441 /* Case #1: 32-bit NT errors */
10442 if (NT_STATUS_IS_DOS(status)) {
10443 printf("/** NT error on DOS connection! (%s) */\n",
10444 nt_errstr(status));
10445 errnum = errclass = 0;
10447 errclass = NT_STATUS_DOS_CLASS(status);
10448 errnum = NT_STATUS_DOS_CODE(status);
10451 if (NT_STATUS_V(nt_status) != error) {
10452 printf("/*\t{ This NT error code was 'sqashed'\n\t from %s to %s \n\t during the session setup }\n*/\n",
10453 get_nt_error_c_code(talloc_tos(), NT_STATUS(error)),
10454 get_nt_error_c_code(talloc_tos(), nt_status));
10457 printf("\t{%s,\t%s,\t%s},\n",
10458 smb_dos_err_class(errclass),
10459 smb_dos_err_name(errclass, errnum),
10460 get_nt_error_c_code(talloc_tos(), NT_STATUS(error)));
10462 TALLOC_FREE(user_creds);
10467 static bool run_sesssetup_bench(int dummy)
10469 static struct cli_state *c;
10470 const char *fname = "\\file.dat";
10475 if (!torture_open_connection(&c, 0)) {
10479 status = cli_ntcreate(c, fname, 0, GENERIC_ALL_ACCESS|DELETE_ACCESS,
10480 FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
10481 FILE_DELETE_ON_CLOSE, 0, &fnum, NULL);
10482 if (!NT_STATUS_IS_OK(status)) {
10483 d_printf("open %s failed: %s\n", fname, nt_errstr(status));
10487 for (i=0; i<torture_numops; i++) {
10488 status = cli_session_setup_creds(c, torture_creds);
10489 if (!NT_STATUS_IS_OK(status)) {
10490 d_printf("(%s) cli_session_setup_creds failed: %s\n",
10491 __location__, nt_errstr(status));
10495 d_printf("\r%d ", (int)cli_state_get_uid(c));
10497 status = cli_ulogoff(c);
10498 if (!NT_STATUS_IS_OK(status)) {
10499 d_printf("(%s) cli_ulogoff failed: %s\n",
10500 __location__, nt_errstr(status));
10508 static bool subst_test(const char *str, const char *user, const char *domain,
10509 uid_t uid, gid_t gid, const char *expected)
10512 bool result = true;
10514 subst = talloc_sub_specified(talloc_tos(), str, user, NULL, domain, uid, gid);
10516 if (strcmp(subst, expected) != 0) {
10517 printf("sub_specified(%s, %s, %s, %d, %d) returned [%s], expected "
10518 "[%s]\n", str, user, domain, (int)uid, (int)gid, subst,
10523 TALLOC_FREE(subst);
10527 static void chain1_open_completion(struct tevent_req *req)
10531 status = cli_openx_recv(req, &fnum);
10534 d_printf("cli_openx_recv returned %s: %d\n",
10536 NT_STATUS_IS_OK(status) ? fnum : -1);
10539 static void chain1_write_completion(struct tevent_req *req)
10543 status = cli_write_andx_recv(req, &written);
10546 d_printf("cli_write_andx_recv returned %s: %d\n",
10548 NT_STATUS_IS_OK(status) ? (int)written : -1);
10551 static void chain1_close_completion(struct tevent_req *req)
10554 bool *done = (bool *)tevent_req_callback_data_void(req);
10556 status = cli_close_recv(req);
10561 d_printf("cli_close returned %s\n", nt_errstr(status));
10564 static bool run_chain1(int dummy)
10566 struct cli_state *cli1;
10567 struct tevent_context *evt = samba_tevent_context_init(NULL);
10568 struct tevent_req *reqs[3], *smbreqs[3];
10570 const char *str = "foobar";
10571 const char *fname = "\\test_chain";
10574 printf("starting chain1 test\n");
10575 if (!torture_open_connection(&cli1, 0)) {
10579 smbXcli_conn_set_sockopt(cli1->conn, sockops);
10581 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
10583 reqs[0] = cli_openx_create(talloc_tos(), evt, cli1, fname,
10584 O_CREAT|O_RDWR, 0, &smbreqs[0]);
10585 if (reqs[0] == NULL) return false;
10586 tevent_req_set_callback(reqs[0], chain1_open_completion, NULL);
10589 reqs[1] = cli_write_andx_create(talloc_tos(), evt, cli1, 0, 0,
10590 (const uint8_t *)str, 0, strlen(str)+1,
10591 smbreqs, 1, &smbreqs[1]);
10592 if (reqs[1] == NULL) return false;
10593 tevent_req_set_callback(reqs[1], chain1_write_completion, NULL);
10595 reqs[2] = cli_smb1_close_create(talloc_tos(), evt, cli1, 0, &smbreqs[2]);
10596 if (reqs[2] == NULL) return false;
10597 tevent_req_set_callback(reqs[2], chain1_close_completion, &done);
10599 status = smb1cli_req_chain_submit(smbreqs, ARRAY_SIZE(smbreqs));
10600 if (!NT_STATUS_IS_OK(status)) {
10605 tevent_loop_once(evt);
10608 torture_close_connection(cli1);
10612 static void chain2_sesssetup_completion(struct tevent_req *req)
10615 status = cli_session_setup_guest_recv(req);
10616 d_printf("sesssetup returned %s\n", nt_errstr(status));
10619 static void chain2_tcon_completion(struct tevent_req *req)
10621 bool *done = (bool *)tevent_req_callback_data_void(req);
10623 status = cli_tcon_andx_recv(req);
10624 d_printf("tcon_and_x returned %s\n", nt_errstr(status));
10628 static bool run_chain2(int dummy)
10630 struct cli_state *cli1;
10631 struct tevent_context *evt = samba_tevent_context_init(NULL);
10632 struct tevent_req *reqs[2], *smbreqs[2];
10635 int flags = CLI_FULL_CONNECTION_FORCE_SMB1;
10637 printf("starting chain2 test\n");
10638 status = cli_start_connection(&cli1, lp_netbios_name(), host, NULL,
10639 port_to_use, SMB_SIGNING_DEFAULT, flags);
10640 if (!NT_STATUS_IS_OK(status)) {
10644 smbXcli_conn_set_sockopt(cli1->conn, sockops);
10646 reqs[0] = cli_session_setup_guest_create(talloc_tos(), evt, cli1,
10648 if (reqs[0] == NULL) return false;
10649 tevent_req_set_callback(reqs[0], chain2_sesssetup_completion, NULL);
10651 reqs[1] = cli_tcon_andx_create(talloc_tos(), evt, cli1, "IPC$",
10652 "?????", NULL, 0, &smbreqs[1]);
10653 if (reqs[1] == NULL) return false;
10654 tevent_req_set_callback(reqs[1], chain2_tcon_completion, &done);
10656 status = smb1cli_req_chain_submit(smbreqs, ARRAY_SIZE(smbreqs));
10657 if (!NT_STATUS_IS_OK(status)) {
10662 tevent_loop_once(evt);
10665 torture_close_connection(cli1);
10670 struct torture_createdel_state {
10671 struct tevent_context *ev;
10672 struct cli_state *cli;
10675 static void torture_createdel_created(struct tevent_req *subreq);
10676 static void torture_createdel_closed(struct tevent_req *subreq);
10678 static struct tevent_req *torture_createdel_send(TALLOC_CTX *mem_ctx,
10679 struct tevent_context *ev,
10680 struct cli_state *cli,
10683 struct tevent_req *req, *subreq;
10684 struct torture_createdel_state *state;
10686 req = tevent_req_create(mem_ctx, &state,
10687 struct torture_createdel_state);
10694 subreq = cli_ntcreate_send(
10695 state, ev, cli, name, 0,
10696 FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
10697 FILE_ATTRIBUTE_NORMAL,
10698 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
10699 FILE_OPEN_IF, FILE_DELETE_ON_CLOSE,
10700 SMB2_IMPERSONATION_IMPERSONATION, 0);
10702 if (tevent_req_nomem(subreq, req)) {
10703 return tevent_req_post(req, ev);
10705 tevent_req_set_callback(subreq, torture_createdel_created, req);
10709 static void torture_createdel_created(struct tevent_req *subreq)
10711 struct tevent_req *req = tevent_req_callback_data(
10712 subreq, struct tevent_req);
10713 struct torture_createdel_state *state = tevent_req_data(
10714 req, struct torture_createdel_state);
10718 status = cli_ntcreate_recv(subreq, &fnum, NULL);
10719 TALLOC_FREE(subreq);
10720 if (tevent_req_nterror(req, status)) {
10721 DEBUG(10, ("cli_ntcreate_recv returned %s\n",
10722 nt_errstr(status)));
10726 subreq = cli_close_send(state, state->ev, state->cli, fnum, 0);
10727 if (tevent_req_nomem(subreq, req)) {
10730 tevent_req_set_callback(subreq, torture_createdel_closed, req);
10733 static void torture_createdel_closed(struct tevent_req *subreq)
10735 struct tevent_req *req = tevent_req_callback_data(
10736 subreq, struct tevent_req);
10739 status = cli_close_recv(subreq);
10740 if (tevent_req_nterror(req, status)) {
10741 DEBUG(10, ("cli_close_recv returned %s\n", nt_errstr(status)));
10744 tevent_req_done(req);
10747 static NTSTATUS torture_createdel_recv(struct tevent_req *req)
10749 return tevent_req_simple_recv_ntstatus(req);
10752 struct torture_createdels_state {
10753 struct tevent_context *ev;
10754 struct cli_state *cli;
10755 const char *base_name;
10759 struct tevent_req **reqs;
10762 static void torture_createdels_done(struct tevent_req *subreq);
10764 static struct tevent_req *torture_createdels_send(TALLOC_CTX *mem_ctx,
10765 struct tevent_context *ev,
10766 struct cli_state *cli,
10767 const char *base_name,
10771 struct tevent_req *req;
10772 struct torture_createdels_state *state;
10775 req = tevent_req_create(mem_ctx, &state,
10776 struct torture_createdels_state);
10782 state->base_name = talloc_strdup(state, base_name);
10783 if (tevent_req_nomem(state->base_name, req)) {
10784 return tevent_req_post(req, ev);
10786 state->num_files = MAX(num_parallel, num_files);
10788 state->received = 0;
10790 state->reqs = talloc_array(state, struct tevent_req *, num_parallel);
10791 if (tevent_req_nomem(state->reqs, req)) {
10792 return tevent_req_post(req, ev);
10795 for (i=0; i<num_parallel; i++) {
10798 name = talloc_asprintf(state, "%s%8.8d", state->base_name,
10800 if (tevent_req_nomem(name, req)) {
10801 return tevent_req_post(req, ev);
10803 state->reqs[i] = torture_createdel_send(
10804 state->reqs, state->ev, state->cli, name);
10805 if (tevent_req_nomem(state->reqs[i], req)) {
10806 return tevent_req_post(req, ev);
10808 name = talloc_move(state->reqs[i], &name);
10809 tevent_req_set_callback(state->reqs[i],
10810 torture_createdels_done, req);
10816 static void torture_createdels_done(struct tevent_req *subreq)
10818 struct tevent_req *req = tevent_req_callback_data(
10819 subreq, struct tevent_req);
10820 struct torture_createdels_state *state = tevent_req_data(
10821 req, struct torture_createdels_state);
10822 size_t i, num_parallel = talloc_array_length(state->reqs);
10826 status = torture_createdel_recv(subreq);
10827 if (!NT_STATUS_IS_OK(status)){
10828 DEBUG(10, ("torture_createdel_recv returned %s\n",
10829 nt_errstr(status)));
10830 TALLOC_FREE(subreq);
10831 tevent_req_nterror(req, status);
10835 for (i=0; i<num_parallel; i++) {
10836 if (subreq == state->reqs[i]) {
10840 if (i == num_parallel) {
10841 DEBUG(10, ("received something we did not send\n"));
10842 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
10845 TALLOC_FREE(state->reqs[i]);
10847 if (state->sent >= state->num_files) {
10848 tevent_req_done(req);
10852 name = talloc_asprintf(state, "%s%8.8d", state->base_name,
10854 if (tevent_req_nomem(name, req)) {
10857 state->reqs[i] = torture_createdel_send(state->reqs, state->ev,
10859 if (tevent_req_nomem(state->reqs[i], req)) {
10862 name = talloc_move(state->reqs[i], &name);
10863 tevent_req_set_callback(state->reqs[i], torture_createdels_done, req);
10867 static NTSTATUS torture_createdels_recv(struct tevent_req *req)
10869 return tevent_req_simple_recv_ntstatus(req);
10872 struct swallow_notify_state {
10873 struct tevent_context *ev;
10874 struct cli_state *cli;
10876 uint32_t completion_filter;
10878 bool (*fn)(uint32_t action, const char *name, void *priv);
10882 static void swallow_notify_done(struct tevent_req *subreq);
10884 static struct tevent_req *swallow_notify_send(TALLOC_CTX *mem_ctx,
10885 struct tevent_context *ev,
10886 struct cli_state *cli,
10888 uint32_t completion_filter,
10890 bool (*fn)(uint32_t action,
10895 struct tevent_req *req, *subreq;
10896 struct swallow_notify_state *state;
10898 req = tevent_req_create(mem_ctx, &state,
10899 struct swallow_notify_state);
10905 state->fnum = fnum;
10906 state->completion_filter = completion_filter;
10907 state->recursive = recursive;
10909 state->priv = priv;
10911 subreq = cli_notify_send(state, state->ev, state->cli, state->fnum,
10912 0xffff, state->completion_filter,
10914 if (tevent_req_nomem(subreq, req)) {
10915 return tevent_req_post(req, ev);
10917 tevent_req_set_callback(subreq, swallow_notify_done, req);
10921 static void swallow_notify_done(struct tevent_req *subreq)
10923 struct tevent_req *req = tevent_req_callback_data(
10924 subreq, struct tevent_req);
10925 struct swallow_notify_state *state = tevent_req_data(
10926 req, struct swallow_notify_state);
10928 uint32_t i, num_changes;
10929 struct notify_change *changes;
10931 status = cli_notify_recv(subreq, state, &num_changes, &changes);
10932 TALLOC_FREE(subreq);
10933 if (!NT_STATUS_IS_OK(status)) {
10934 DEBUG(10, ("cli_notify_recv returned %s\n",
10935 nt_errstr(status)));
10936 tevent_req_nterror(req, status);
10940 for (i=0; i<num_changes; i++) {
10941 state->fn(changes[i].action, changes[i].name, state->priv);
10943 TALLOC_FREE(changes);
10945 subreq = cli_notify_send(state, state->ev, state->cli, state->fnum,
10946 0xffff, state->completion_filter,
10948 if (tevent_req_nomem(subreq, req)) {
10951 tevent_req_set_callback(subreq, swallow_notify_done, req);
10954 static bool print_notifies(uint32_t action, const char *name, void *priv)
10956 if (DEBUGLEVEL > 5) {
10957 d_printf("%d %s\n", (int)action, name);
10962 static void notify_bench_done(struct tevent_req *req)
10964 int *num_finished = (int *)tevent_req_callback_data_void(req);
10965 *num_finished += 1;
10968 static bool run_notify_bench(int dummy)
10970 const char *dname = "\\notify-bench";
10971 struct tevent_context *ev;
10974 struct tevent_req *req1;
10975 struct tevent_req *req2 = NULL;
10976 int i, num_unc_names;
10977 int num_finished = 0;
10979 printf("starting notify-bench test\n");
10981 if (use_multishare_conn) {
10983 unc_list = file_lines_load(multishare_conn_fname,
10984 &num_unc_names, 0, NULL);
10985 if (!unc_list || num_unc_names <= 0) {
10986 d_printf("Failed to load unc names list from '%s'\n",
10987 multishare_conn_fname);
10990 TALLOC_FREE(unc_list);
10995 ev = samba_tevent_context_init(talloc_tos());
10997 d_printf("tevent_context_init failed\n");
11001 for (i=0; i<num_unc_names; i++) {
11002 struct cli_state *cli;
11005 base_fname = talloc_asprintf(talloc_tos(), "%s\\file%3.3d.",
11007 if (base_fname == NULL) {
11011 if (!torture_open_connection(&cli, i)) {
11015 status = cli_ntcreate(cli, dname, 0,
11016 MAXIMUM_ALLOWED_ACCESS,
11017 0, FILE_SHARE_READ|FILE_SHARE_WRITE|
11019 FILE_OPEN_IF, FILE_DIRECTORY_FILE, 0,
11022 if (!NT_STATUS_IS_OK(status)) {
11023 d_printf("Could not create %s: %s\n", dname,
11024 nt_errstr(status));
11028 req1 = swallow_notify_send(talloc_tos(), ev, cli, dnum,
11029 FILE_NOTIFY_CHANGE_FILE_NAME |
11030 FILE_NOTIFY_CHANGE_DIR_NAME |
11031 FILE_NOTIFY_CHANGE_ATTRIBUTES |
11032 FILE_NOTIFY_CHANGE_LAST_WRITE,
11033 false, print_notifies, NULL);
11034 if (req1 == NULL) {
11035 d_printf("Could not create notify request\n");
11039 req2 = torture_createdels_send(talloc_tos(), ev, cli,
11040 base_fname, 10, torture_numops);
11041 if (req2 == NULL) {
11042 d_printf("Could not create createdels request\n");
11045 TALLOC_FREE(base_fname);
11047 tevent_req_set_callback(req2, notify_bench_done,
11051 while (num_finished < num_unc_names) {
11053 ret = tevent_loop_once(ev);
11055 d_printf("tevent_loop_once failed\n");
11060 if (!tevent_req_poll(req2, ev)) {
11061 d_printf("tevent_req_poll failed\n");
11064 status = torture_createdels_recv(req2);
11065 d_printf("torture_createdels_recv returned %s\n", nt_errstr(status));
11070 static bool run_mangle1(int dummy)
11072 struct cli_state *cli;
11073 const char *fname = "this_is_a_long_fname_to_be_mangled.txt";
11078 printf("starting mangle1 test\n");
11079 if (!torture_open_connection(&cli, 0)) {
11083 smbXcli_conn_set_sockopt(cli->conn, sockops);
11085 status = cli_ntcreate(cli, fname, 0, GENERIC_ALL_ACCESS|DELETE_ACCESS,
11086 FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
11087 0, 0, &fnum, NULL);
11088 if (!NT_STATUS_IS_OK(status)) {
11089 d_printf("open %s failed: %s\n", fname, nt_errstr(status));
11092 cli_close(cli, fnum);
11094 status = cli_qpathinfo_alt_name(cli, fname, alt_name);
11095 if (!NT_STATUS_IS_OK(status)) {
11096 d_printf("cli_qpathinfo_alt_name failed: %s\n",
11097 nt_errstr(status));
11100 d_printf("alt_name: %s\n", alt_name);
11102 status = cli_openx(cli, alt_name, O_RDONLY, DENY_NONE, &fnum);
11103 if (!NT_STATUS_IS_OK(status)) {
11104 d_printf("cli_openx(%s) failed: %s\n", alt_name,
11105 nt_errstr(status));
11108 cli_close(cli, fnum);
11110 status = cli_qpathinfo1(cli, alt_name, NULL, NULL, NULL, NULL, NULL);
11111 if (!NT_STATUS_IS_OK(status)) {
11112 d_printf("cli_qpathinfo1(%s) failed: %s\n", alt_name,
11113 nt_errstr(status));
11120 static NTSTATUS mangle_illegal_list_shortname_fn(struct file_info *f,
11124 if (f->short_name == NULL) {
11125 return NT_STATUS_OK;
11128 if (strlen(f->short_name) == 0) {
11129 return NT_STATUS_OK;
11132 printf("unexpected shortname: %s\n", f->short_name);
11134 return NT_STATUS_OBJECT_NAME_INVALID;
11137 static NTSTATUS mangle_illegal_list_name_fn(struct file_info *f,
11141 char *name = state;
11143 printf("name: %s\n", f->name);
11144 fstrcpy(name, f->name);
11145 return NT_STATUS_OK;
11148 static bool run_mangle_illegal(int dummy)
11150 struct cli_state *cli = NULL;
11151 struct cli_state *cli_posix = NULL;
11152 const char *fname = "\\MANGLE_ILLEGAL\\this_is_a_long_fname_to_be_mangled.txt";
11153 const char *illegal_fname = "MANGLE_ILLEGAL/foo:bar";
11154 char *mangled_path = NULL;
11160 printf("starting mangle-illegal test\n");
11162 if (!torture_open_connection(&cli, 0)) {
11166 smbXcli_conn_set_sockopt(cli->conn, sockops);
11168 if (!torture_open_connection(&cli_posix, 0)) {
11172 smbXcli_conn_set_sockopt(cli_posix->conn, sockops);
11174 status = torture_setup_unix_extensions(cli_posix);
11175 if (!NT_STATUS_IS_OK(status)) {
11179 cli_rmdir(cli, "\\MANGLE_ILLEGAL");
11180 status = cli_mkdir(cli, "\\MANGLE_ILLEGAL");
11181 if (!NT_STATUS_IS_OK(status)) {
11182 printf("mkdir1 failed : %s\n", nt_errstr(status));
11187 * Create a file with illegal NTFS characters and test that we
11188 * get a usable mangled name
11191 cli_setatr(cli_posix, illegal_fname, 0, 0);
11192 cli_posix_unlink(cli_posix, illegal_fname);
11194 status = cli_posix_open(cli_posix, illegal_fname, O_RDWR|O_CREAT|O_EXCL,
11196 if (!NT_STATUS_IS_OK(status)) {
11197 printf("POSIX create of %s failed (%s)\n",
11198 illegal_fname, nt_errstr(status));
11202 status = cli_close(cli_posix, fnum);
11203 if (!NT_STATUS_IS_OK(status)) {
11204 printf("close failed (%s)\n", nt_errstr(status));
11208 status = cli_list(cli, "\\MANGLE_ILLEGAL\\*", 0, mangle_illegal_list_name_fn, &name);
11209 if (!NT_STATUS_IS_OK(status)) {
11210 d_printf("cli_list failed: %s\n", nt_errstr(status));
11214 mangled_path = talloc_asprintf(talloc_tos(), "\\MANGLE_ILLEGAL\\%s", name);
11215 if (mangled_path == NULL) {
11219 status = cli_openx(cli, mangled_path, O_RDONLY, DENY_NONE, &fnum);
11220 if (!NT_STATUS_IS_OK(status)) {
11221 d_printf("cli_openx(%s) failed: %s\n", mangled_path, nt_errstr(status));
11222 TALLOC_FREE(mangled_path);
11225 TALLOC_FREE(mangled_path);
11226 cli_close(cli, fnum);
11228 cli_setatr(cli_posix, illegal_fname, 0, 0);
11229 cli_posix_unlink(cli_posix, illegal_fname);
11232 * Create a file with a long name and check that we got *no* short name.
11235 status = cli_ntcreate(cli, fname, 0, GENERIC_ALL_ACCESS|DELETE_ACCESS,
11236 FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
11237 0, 0, &fnum, NULL);
11238 if (!NT_STATUS_IS_OK(status)) {
11239 d_printf("open %s failed: %s\n", fname, nt_errstr(status));
11242 cli_close(cli, fnum);
11244 status = cli_list(cli, fname, 0, mangle_illegal_list_shortname_fn, &alt_name);
11245 if (!NT_STATUS_IS_OK(status)) {
11246 d_printf("cli_list failed\n");
11250 cli_unlink(cli, fname, 0);
11251 cli_rmdir(cli, "\\MANGLE_ILLEGAL");
11253 if (!torture_close_connection(cli_posix)) {
11257 if (!torture_close_connection(cli)) {
11264 static size_t null_source(uint8_t *buf, size_t n, void *priv)
11266 size_t *to_pull = (size_t *)priv;
11267 size_t thistime = *to_pull;
11269 thistime = MIN(thistime, n);
11270 if (thistime == 0) {
11274 memset(buf, 0, thistime);
11275 *to_pull -= thistime;
11279 static bool run_windows_write(int dummy)
11281 struct cli_state *cli1;
11285 const char *fname = "\\writetest.txt";
11286 struct timeval start_time;
11291 printf("starting windows_write test\n");
11292 if (!torture_open_connection(&cli1, 0)) {
11296 status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
11297 if (!NT_STATUS_IS_OK(status)) {
11298 printf("open failed (%s)\n", nt_errstr(status));
11302 smbXcli_conn_set_sockopt(cli1->conn, sockops);
11304 start_time = timeval_current();
11306 for (i=0; i<torture_numops; i++) {
11308 off_t start = i * torture_blocksize;
11309 size_t to_pull = torture_blocksize - 1;
11311 status = cli_writeall(cli1, fnum, 0, &c,
11312 start + torture_blocksize - 1, 1, NULL);
11313 if (!NT_STATUS_IS_OK(status)) {
11314 printf("cli_write failed: %s\n", nt_errstr(status));
11318 status = cli_push(cli1, fnum, 0, i * torture_blocksize, torture_blocksize,
11319 null_source, &to_pull);
11320 if (!NT_STATUS_IS_OK(status)) {
11321 printf("cli_push returned: %s\n", nt_errstr(status));
11326 seconds = timeval_elapsed(&start_time);
11327 kbytes = (double)torture_blocksize * torture_numops;
11330 printf("Wrote %d kbytes in %.2f seconds: %d kb/sec\n", (int)kbytes,
11331 (double)seconds, (int)(kbytes/seconds));
11335 cli_close(cli1, fnum);
11336 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
11337 torture_close_connection(cli1);
11341 static size_t calc_expected_return(struct cli_state *cli, size_t len_requested)
11343 size_t max_pdu = 0x1FFFF;
11345 if (cli->server_posix_capabilities & CIFS_UNIX_LARGE_READ_CAP) {
11346 max_pdu = 0xFFFFFF;
11349 if (smb1cli_conn_signing_is_active(cli->conn)) {
11353 if (smb1cli_conn_encryption_on(cli->conn)) {
11354 max_pdu = CLI_BUFFER_SIZE;
11357 if ((len_requested & 0xFFFF0000) == 0xFFFF0000) {
11358 len_requested &= 0xFFFF;
11361 return MIN(len_requested,
11362 max_pdu - (MIN_SMB_SIZE + VWV(12) + 1 /* padding byte */));
11365 static bool check_read_call(struct cli_state *cli,
11368 size_t len_requested)
11371 struct tevent_req *subreq = NULL;
11372 ssize_t len_read = 0;
11373 size_t len_expected = 0;
11374 struct tevent_context *ev = NULL;
11376 ev = samba_tevent_context_init(talloc_tos());
11381 subreq = cli_read_andx_send(talloc_tos(),
11388 if (!tevent_req_poll_ntstatus(subreq, ev, &status)) {
11392 status = cli_read_andx_recv(subreq, &len_read, &buf);
11393 if (!NT_STATUS_IS_OK(status)) {
11394 d_printf("cli_read_andx_recv failed: %s\n", nt_errstr(status));
11398 TALLOC_FREE(subreq);
11401 len_expected = calc_expected_return(cli, len_requested);
11403 if (len_expected > 0x10000 && len_read == 0x10000) {
11404 /* Windows servers only return a max of 0x10000,
11405 doesn't matter if you set CAP_LARGE_READX in
11406 the client sessionsetupX call or not. */
11407 d_printf("Windows server - returned 0x10000 on a read of 0x%x\n",
11408 (unsigned int)len_requested);
11409 } else if (len_read != len_expected) {
11410 d_printf("read of 0x%x failed: got 0x%x, expected 0x%x\n",
11411 (unsigned int)len_requested,
11412 (unsigned int)len_read,
11413 (unsigned int)len_expected);
11416 d_printf("Correct read reply.\n");
11422 /* Test large readX variants. */
11423 static bool large_readx_tests(struct cli_state *cli,
11427 /* A read of 0xFFFF0001 should *always* return 1 byte. */
11428 if (check_read_call(cli, fnum, buf, 0xFFFF0001) == false) {
11431 /* A read of 0x10000 should return 0x10000 bytes. */
11432 if (check_read_call(cli, fnum, buf, 0x10000) == false) {
11435 /* A read of 0x10000 should return 0x10001 bytes. */
11436 if (check_read_call(cli, fnum, buf, 0x10001) == false) {
11439 /* A read of 0x1FFFF - (MIN_SMB_SIZE + VWV(12) should return
11440 the requested number of bytes. */
11441 if (check_read_call(cli, fnum, buf, 0x1FFFF - (MIN_SMB_SIZE + VWV(12))) == false) {
11444 /* A read of 1MB should return 1MB bytes (on Samba). */
11445 if (check_read_call(cli, fnum, buf, 0x100000) == false) {
11449 if (check_read_call(cli, fnum, buf, 0x20001) == false) {
11452 if (check_read_call(cli, fnum, buf, 0x22000001) == false) {
11455 if (check_read_call(cli, fnum, buf, 0xFFFE0001) == false) {
11461 static bool run_large_readx(int dummy)
11463 uint8_t *buf = NULL;
11464 struct cli_state *cli1 = NULL;
11465 struct cli_state *cli2 = NULL;
11466 bool correct = false;
11467 const char *fname = "\\large_readx.dat";
11469 uint16_t fnum1 = UINT16_MAX;
11470 uint32_t normal_caps = 0;
11471 size_t file_size = 20*1024*1024;
11472 TALLOC_CTX *frame = talloc_stackframe();
11476 enum smb_signing_setting signing_setting;
11477 enum protocol_types protocol;
11481 .signing_setting = SMB_SIGNING_IF_REQUIRED,
11482 .protocol = PROTOCOL_NT1,
11484 .name = "NT1 - SIGNING_REQUIRED",
11485 .signing_setting = SMB_SIGNING_REQUIRED,
11486 .protocol = PROTOCOL_NT1,
11490 printf("starting large_readx test\n");
11492 if (!torture_open_connection(&cli1, 0)) {
11496 normal_caps = smb1cli_conn_capabilities(cli1->conn);
11498 if (!(normal_caps & CAP_LARGE_READX)) {
11499 d_printf("Server doesn't have CAP_LARGE_READX 0x%x\n",
11500 (unsigned int)normal_caps);
11504 /* Create a file of size 4MB. */
11505 status = cli_ntcreate(cli1, fname, 0, GENERIC_ALL_ACCESS,
11506 FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
11507 0, 0, &fnum1, NULL);
11509 if (!NT_STATUS_IS_OK(status)) {
11510 d_printf("open %s failed: %s\n", fname, nt_errstr(status));
11514 /* Write file_size bytes. */
11515 buf = talloc_zero_array(frame, uint8_t, file_size);
11520 status = cli_writeall(cli1,
11527 if (!NT_STATUS_IS_OK(status)) {
11528 d_printf("cli_writeall failed: %s\n", nt_errstr(status));
11532 status = cli_close(cli1, fnum1);
11533 if (!NT_STATUS_IS_OK(status)) {
11534 d_printf("cli_close failed: %s\n", nt_errstr(status));
11538 fnum1 = UINT16_MAX;
11540 for (i=0; i < ARRAY_SIZE(runs); i++) {
11541 enum smb_signing_setting saved_signing_setting = signing_state;
11542 uint16_t fnum2 = -1;
11545 (runs[i].signing_setting == SMB_SIGNING_REQUIRED))
11547 d_printf("skip[%u] - %s\n", (unsigned)i, runs[i].name);
11551 d_printf("run[%u] - %s\n", (unsigned)i, runs[i].name);
11553 signing_state = runs[i].signing_setting;
11554 cli2 = open_nbt_connection();
11555 signing_state = saved_signing_setting;
11556 if (cli2 == NULL) {
11560 status = smbXcli_negprot(cli2->conn,
11567 if (!NT_STATUS_IS_OK(status)) {
11571 status = cli_session_setup_creds(cli2, torture_creds);
11572 if (!NT_STATUS_IS_OK(status)) {
11576 status = cli_tree_connect(cli2,
11580 if (!NT_STATUS_IS_OK(status)) {
11584 cli_set_timeout(cli2, 120000); /* set a really long timeout (2 minutes) */
11586 normal_caps = smb1cli_conn_capabilities(cli2->conn);
11588 if (!(normal_caps & CAP_LARGE_READX)) {
11589 d_printf("Server doesn't have CAP_LARGE_READX 0x%x\n",
11590 (unsigned int)normal_caps);
11595 if (force_cli_encryption(cli2, share) == false) {
11598 } else if (SERVER_HAS_UNIX_CIFS(cli2)) {
11599 uint16_t major, minor;
11600 uint32_t caplow, caphigh;
11602 status = cli_unix_extensions_version(cli2,
11604 &caplow, &caphigh);
11605 if (!NT_STATUS_IS_OK(status)) {
11610 status = cli_ntcreate(cli2, fname, 0, FILE_READ_DATA,
11611 FILE_ATTRIBUTE_NORMAL, 0, FILE_OPEN,
11612 0, 0, &fnum2, NULL);
11613 if (!NT_STATUS_IS_OK(status)) {
11614 d_printf("Second open %s failed: %s\n", fname, nt_errstr(status));
11618 /* All reads must return less than file_size bytes. */
11619 if (!large_readx_tests(cli2, fnum2, buf)) {
11623 status = cli_close(cli2, fnum2);
11624 if (!NT_STATUS_IS_OK(status)) {
11625 d_printf("cli_close failed: %s\n", nt_errstr(status));
11630 if (!torture_close_connection(cli2)) {
11637 printf("Success on large_readx test\n");
11642 if (!torture_close_connection(cli2)) {
11648 if (fnum1 != UINT16_MAX) {
11649 status = cli_close(cli1, fnum1);
11650 if (!NT_STATUS_IS_OK(status)) {
11651 d_printf("cli_close failed: %s\n", nt_errstr(status));
11653 fnum1 = UINT16_MAX;
11656 status = cli_unlink(cli1, fname,
11657 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
11658 if (!NT_STATUS_IS_OK(status)) {
11659 printf("unlink failed (%s)\n", nt_errstr(status));
11662 if (!torture_close_connection(cli1)) {
11667 TALLOC_FREE(frame);
11669 printf("finished large_readx test\n");
11673 static NTSTATUS msdfs_attribute_list_fn(struct file_info *finfo,
11675 void *private_data)
11677 uint32_t *p_attr = (uint32_t *)private_data;
11679 if (strequal(finfo->name, test_filename)) {
11680 *p_attr = finfo->attr;
11683 return NT_STATUS_OK;
11686 static bool run_msdfs_attribute(int dummy)
11688 static struct cli_state *cli;
11689 bool correct = false;
11693 printf("Starting MSDFS-ATTRIBUTE test\n");
11695 if (test_filename == NULL || test_filename[0] == '\0') {
11696 printf("MSDFS-ATTRIBUTE test "
11697 "needs -f filename-of-msdfs-link\n");
11702 * NB. We use torture_open_connection_flags() not
11703 * torture_open_connection() as the latter forces
11706 if (!torture_open_connection_flags(&cli, 0, 0)) {
11710 smbXcli_conn_set_sockopt(cli->conn, sockops);
11712 status = cli_list(cli,
11714 FILE_ATTRIBUTE_DIRECTORY,
11715 msdfs_attribute_list_fn,
11718 if (!NT_STATUS_IS_OK(status)) {
11719 printf("cli_list failed with %s\n",
11720 nt_errstr(status));
11723 if ((attr & FILE_ATTRIBUTE_REPARSE_POINT) == 0) {
11724 printf("file %s should have "
11725 "FILE_ATTRIBUTE_REPARSE_POINT set. attr = 0x%x\n",
11727 (unsigned int)attr);
11731 if ((attr & FILE_ATTRIBUTE_DIRECTORY) == 0) {
11732 printf("file %s should have "
11733 "FILE_ATTRIBUTE_DIRECTORY set. attr = 0x%x\n",
11735 (unsigned int)attr);
11743 torture_close_connection(cli);
11747 static bool run_cli_echo(int dummy)
11749 struct cli_state *cli;
11752 printf("starting cli_echo test\n");
11753 if (!torture_open_connection(&cli, 0)) {
11756 smbXcli_conn_set_sockopt(cli->conn, sockops);
11758 status = cli_echo(cli, 5, data_blob_const("hello", 5));
11760 d_printf("cli_echo returned %s\n", nt_errstr(status));
11762 torture_close_connection(cli);
11763 return NT_STATUS_IS_OK(status);
11766 static int splice_status(off_t written, void *priv)
11771 static bool run_cli_splice(int dummy)
11773 uint8_t *buf = NULL;
11774 struct cli_state *cli1 = NULL;
11775 bool correct = false;
11776 const char *fname_src = "\\splice_src.dat";
11777 const char *fname_dst = "\\splice_dst.dat";
11779 uint16_t fnum1 = UINT16_MAX;
11780 uint16_t fnum2 = UINT16_MAX;
11781 size_t file_size = 2*1024*1024;
11782 size_t splice_size = 1*1024*1024 + 713;
11783 uint8_t digest1[16], digest2[16];
11786 TALLOC_CTX *frame = talloc_stackframe();
11788 printf("starting cli_splice test\n");
11790 if (!torture_open_connection(&cli1, 0)) {
11794 cli_unlink(cli1, fname_src,
11795 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
11796 cli_unlink(cli1, fname_dst,
11797 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
11799 /* Create a file */
11800 status = cli_ntcreate(cli1, fname_src, 0, GENERIC_ALL_ACCESS,
11801 FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
11802 0, 0, &fnum1, NULL);
11804 if (!NT_STATUS_IS_OK(status)) {
11805 d_printf("open %s failed: %s\n", fname_src, nt_errstr(status));
11809 /* Write file_size bytes - must be bigger than splice_size. */
11810 buf = talloc_zero_array(frame, uint8_t, file_size);
11812 d_printf("talloc_fail\n");
11816 /* Fill it with random numbers. */
11817 generate_random_buffer(buf, file_size);
11819 /* MD5 the first 1MB + 713 bytes. */
11820 gnutls_hash_fast(GNUTLS_DIG_MD5,
11825 status = cli_writeall(cli1,
11832 if (!NT_STATUS_IS_OK(status)) {
11833 d_printf("cli_writeall failed: %s\n", nt_errstr(status));
11837 status = cli_ntcreate(cli1, fname_dst, 0, GENERIC_ALL_ACCESS,
11838 FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
11839 0, 0, &fnum2, NULL);
11841 if (!NT_STATUS_IS_OK(status)) {
11842 d_printf("open %s failed: %s\n", fname_dst, nt_errstr(status));
11846 /* Now splice 1MB + 713 bytes. */
11847 status = cli_splice(cli1,
11858 if (!NT_STATUS_IS_OK(status)) {
11859 d_printf("cli_splice failed: %s\n", nt_errstr(status));
11863 /* Clear the old buffer. */
11864 memset(buf, '\0', file_size);
11866 /* Read the new file. */
11867 status = cli_read(cli1, fnum2, (char *)buf, 0, splice_size, &nread);
11868 if (!NT_STATUS_IS_OK(status)) {
11869 d_printf("cli_read failed: %s\n", nt_errstr(status));
11872 if (nread != splice_size) {
11873 d_printf("bad read of 0x%x, should be 0x%x\n",
11874 (unsigned int)nread,
11875 (unsigned int)splice_size);
11879 /* MD5 the first 1MB + 713 bytes. */
11880 gnutls_hash_fast(GNUTLS_DIG_MD5,
11885 /* Must be the same. */
11886 if (memcmp(digest1, digest2, 16) != 0) {
11887 d_printf("bad MD5 compare\n");
11892 printf("Success on cli_splice test\n");
11897 if (fnum1 != UINT16_MAX) {
11898 cli_close(cli1, fnum1);
11900 if (fnum2 != UINT16_MAX) {
11901 cli_close(cli1, fnum2);
11904 cli_unlink(cli1, fname_src,
11905 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
11906 cli_unlink(cli1, fname_dst,
11907 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
11909 if (!torture_close_connection(cli1)) {
11914 TALLOC_FREE(frame);
11918 static bool run_uid_regression_test(int dummy)
11920 static struct cli_state *cli;
11923 bool correct = True;
11924 struct smbXcli_tcon *tcon_copy = NULL;
11927 printf("starting uid regression test\n");
11929 if (!torture_open_connection(&cli, 0)) {
11933 smbXcli_conn_set_sockopt(cli->conn, sockops);
11935 /* Ok - now save then logoff our current user. */
11936 old_vuid = cli_state_get_uid(cli);
11938 status = cli_ulogoff(cli);
11939 if (!NT_STATUS_IS_OK(status)) {
11940 d_printf("(%s) cli_ulogoff failed: %s\n",
11941 __location__, nt_errstr(status));
11946 cli_state_set_uid(cli, old_vuid);
11948 /* Try an operation. */
11949 status = cli_mkdir(cli, "\\uid_reg_test");
11950 if (NT_STATUS_IS_OK(status)) {
11951 d_printf("(%s) cli_mkdir succeeded\n",
11956 /* Should be bad uid. */
11957 if (!check_error(__LINE__, status, ERRSRV, ERRbaduid,
11958 NT_STATUS_USER_SESSION_DELETED)) {
11964 old_cnum = cli_state_get_tid(cli);
11966 * This is an SMB1-only test.
11967 * Copy the tcon, not "save/restore".
11969 * In SMB1 the cli_tdis() below frees
11970 * cli->smb1.tcon so we need a copy
11971 * of the struct to put back for the
11972 * second tdis call with invalid vuid.
11974 * This is a test-only hack. Real client code
11975 * uses cli_state_save_tcon_share()/cli_state_restore_tcon_share().
11977 tcon_copy = smbXcli_tcon_copy(cli, cli->smb1.tcon);
11978 if (tcon_copy == NULL) {
11983 /* Now try a SMBtdis with the invalid vuid set to zero. */
11984 cli_state_set_uid(cli, 0);
11986 /* This should succeed. */
11987 status = cli_tdis(cli);
11989 if (NT_STATUS_IS_OK(status)) {
11990 d_printf("First tdis with invalid vuid should succeed.\n");
11992 d_printf("First tdis failed (%s)\n", nt_errstr(status));
11994 cli->smb1.tcon = tcon_copy;
11998 cli->smb1.tcon = tcon_copy;
11999 cli_state_set_uid(cli, old_vuid);
12000 cli_state_set_tid(cli, old_cnum);
12002 /* This should fail. */
12003 status = cli_tdis(cli);
12004 if (NT_STATUS_IS_OK(status)) {
12005 d_printf("Second tdis with invalid vuid should fail - succeeded instead !.\n");
12009 /* Should be bad tid. */
12010 if (!check_error(__LINE__, status, ERRSRV, ERRinvnid,
12011 NT_STATUS_NETWORK_NAME_DELETED)) {
12017 cli_rmdir(cli, "\\uid_reg_test");
12026 static const char *illegal_chars = "*\\/?<>|\":";
12027 static char force_shortname_chars[] = " +,.[];=\177";
12029 static NTSTATUS shortname_del_fn(struct file_info *finfo,
12030 const char *mask, void *state)
12032 struct cli_state *pcli = (struct cli_state *)state;
12034 NTSTATUS status = NT_STATUS_OK;
12036 slprintf(fname, sizeof(fname), "\\shortname\\%s", finfo->name);
12038 if (strcmp(finfo->name, ".") == 0 || strcmp(finfo->name, "..") == 0)
12039 return NT_STATUS_OK;
12041 if (finfo->attr & FILE_ATTRIBUTE_DIRECTORY) {
12042 status = cli_rmdir(pcli, fname);
12043 if (!NT_STATUS_IS_OK(status)) {
12044 printf("del_fn: failed to rmdir %s\n,", fname );
12047 status = cli_unlink(pcli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
12048 if (!NT_STATUS_IS_OK(status)) {
12049 printf("del_fn: failed to unlink %s\n,", fname );
12061 static NTSTATUS shortname_list_fn(struct file_info *finfo,
12062 const char *name, void *state)
12064 struct sn_state *s = (struct sn_state *)state;
12068 printf("shortname list: i = %d, name = |%s|, shortname = |%s|\n",
12069 i, finfo->name, finfo->short_name);
12072 if (strchr(force_shortname_chars, i)) {
12073 if (!finfo->short_name) {
12074 /* Shortname not created when it should be. */
12075 d_printf("(%s) ERROR: Shortname was not created for file %s containing %d\n",
12076 __location__, finfo->name, i);
12079 } else if (finfo->short_name){
12080 /* Shortname created when it should not be. */
12081 d_printf("(%s) ERROR: Shortname %s was created for file %s\n",
12082 __location__, finfo->short_name, finfo->name);
12086 return NT_STATUS_OK;
12089 static bool run_shortname_test(int dummy)
12091 static struct cli_state *cli;
12092 bool correct = True;
12098 printf("starting shortname test\n");
12100 if (!torture_open_connection(&cli, 0)) {
12104 smbXcli_conn_set_sockopt(cli->conn, sockops);
12106 cli_list(cli, "\\shortname\\*", 0, shortname_del_fn, cli);
12107 cli_list(cli, "\\shortname\\*", FILE_ATTRIBUTE_DIRECTORY, shortname_del_fn, cli);
12108 cli_rmdir(cli, "\\shortname");
12110 status = cli_mkdir(cli, "\\shortname");
12111 if (!NT_STATUS_IS_OK(status)) {
12112 d_printf("(%s) cli_mkdir of \\shortname failed: %s\n",
12113 __location__, nt_errstr(status));
12118 if (strlcpy(fname, "\\shortname\\", sizeof(fname)) >= sizeof(fname)) {
12122 if (strlcat(fname, "test .txt", sizeof(fname)) >= sizeof(fname)) {
12129 for (i = 32; i < 128; i++) {
12130 uint16_t fnum = (uint16_t)-1;
12134 if (strchr(illegal_chars, i)) {
12139 status = cli_ntcreate(cli, fname, 0, GENERIC_ALL_ACCESS, FILE_ATTRIBUTE_NORMAL,
12140 FILE_SHARE_READ|FILE_SHARE_WRITE,
12141 FILE_OVERWRITE_IF, 0, 0, &fnum, NULL);
12142 if (!NT_STATUS_IS_OK(status)) {
12143 d_printf("(%s) cli_nt_create of %s failed: %s\n",
12144 __location__, fname, nt_errstr(status));
12148 cli_close(cli, fnum);
12151 status = cli_list(cli, "\\shortname\\test*.*", 0,
12152 shortname_list_fn, &s);
12153 if (s.matched != 1) {
12154 d_printf("(%s) failed to list %s: %s\n",
12155 __location__, fname, nt_errstr(status));
12160 status = cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
12161 if (!NT_STATUS_IS_OK(status)) {
12162 d_printf("(%s) failed to delete %s: %s\n",
12163 __location__, fname, nt_errstr(status));
12176 cli_list(cli, "\\shortname\\*", 0, shortname_del_fn, cli);
12177 cli_list(cli, "\\shortname\\*", FILE_ATTRIBUTE_DIRECTORY, shortname_del_fn, cli);
12178 cli_rmdir(cli, "\\shortname");
12179 torture_close_connection(cli);
12183 TLDAPRC callback_code;
12185 static void pagedsearch_cb(struct tevent_req *req)
12188 struct tldap_message *msg;
12191 rc = tldap_search_paged_recv(req, talloc_tos(), &msg);
12192 if (!TLDAP_RC_IS_SUCCESS(rc)) {
12193 d_printf("tldap_search_paged_recv failed: %s\n",
12194 tldap_rc2string(rc));
12195 callback_code = rc;
12198 if (tldap_msg_type(msg) != TLDAP_RES_SEARCH_ENTRY) {
12202 if (!tldap_entry_dn(msg, &dn)) {
12203 d_printf("tldap_entry_dn failed\n");
12206 d_printf("%s\n", dn);
12210 enum tldap_extended_val {
12217 * Construct an extended dn control with either no value, 0 or 1
12219 * No value and 0 are equivalent (non-hyphenated GUID)
12220 * 1 has the hyphenated GUID
12222 static struct tldap_control *
12223 tldap_build_extended_control(enum tldap_extended_val val)
12225 struct tldap_control empty_control;
12226 struct asn1_data *data;
12228 ZERO_STRUCT(empty_control);
12230 if (val != EXTENDED_NONE) {
12231 data = asn1_init(talloc_tos(), ASN1_MAX_TREE_DEPTH);
12237 if (!asn1_push_tag(data, ASN1_SEQUENCE(0))) {
12241 if (!asn1_write_Integer(data, (int)val)) {
12245 if (!asn1_pop_tag(data)) {
12249 if (!asn1_blob(data, &empty_control.value)) {
12254 empty_control.oid = "1.2.840.113556.1.4.529";
12255 empty_control.critical = true;
12257 return tldap_add_control(talloc_tos(), NULL, 0, &empty_control);
12261 static bool tldap_test_dn_guid_format(struct tldap_context *ld, const char *basedn,
12262 enum tldap_extended_val control_val)
12264 struct tldap_control *control = tldap_build_extended_control(control_val);
12266 struct tldap_message **msg;
12269 rc = tldap_search(ld, basedn, TLDAP_SCOPE_BASE,
12270 "(objectClass=*)", NULL, 0, 0,
12272 0, 0, 0, 0, talloc_tos(), &msg);
12273 if (!TLDAP_RC_IS_SUCCESS(rc)) {
12274 d_printf("tldap_search for domain DN failed: %s\n",
12275 tldap_errstr(talloc_tos(), ld, rc));
12279 if (!tldap_entry_dn(msg[0], &dn)) {
12280 d_printf("tldap_search domain DN fetch failed: %s\n",
12281 tldap_errstr(talloc_tos(), ld, rc));
12285 d_printf("%s\n", dn);
12288 uint32_t time_mid, time_hi_and_version;
12289 uint32_t clock_seq[2];
12293 switch (control_val) {
12294 case EXTENDED_NONE:
12295 case EXTENDED_ZERO:
12297 * When reading GUIDs with hyphens, scanf will treat
12298 * hyphen as a hex character (and counts as part of the
12299 * width). This creates leftover GUID string which we
12300 * check will for with 'next' and closing '>'.
12302 if (12 == sscanf(dn, "<GUID=%08x%04x%04x%02x%02x%02x%02x%02x%02x%02x%02x>%c",
12303 &time_low, &time_mid,
12304 &time_hi_and_version, &clock_seq[0],
12305 &clock_seq[1], &node[0], &node[1],
12306 &node[2], &node[3], &node[4],
12307 &node[5], &next)) {
12308 /* This GUID is good */
12310 d_printf("GUID format in control (no hyphens) doesn't match output\n");
12316 if (12 == sscanf(dn,
12317 "<GUID=%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x>%c",
12318 &time_low, &time_mid,
12319 &time_hi_and_version, &clock_seq[0],
12320 &clock_seq[1], &node[0], &node[1],
12321 &node[2], &node[3], &node[4],
12322 &node[5], &next)) {
12323 /* This GUID is good */
12325 d_printf("GUID format in control (with hyphens) doesn't match output\n");
12338 static bool run_tldap(int dummy)
12340 struct tldap_context *ld;
12344 struct sockaddr_storage addr;
12345 struct tevent_context *ev;
12346 struct tevent_req *req;
12348 const char *filter;
12350 if (!resolve_name(host, &addr, 0, false)) {
12351 d_printf("could not find host %s\n", host);
12354 status = open_socket_out(&addr, 389, 9999, &fd);
12355 if (!NT_STATUS_IS_OK(status)) {
12356 d_printf("open_socket_out failed: %s\n", nt_errstr(status));
12360 ld = tldap_context_create(talloc_tos(), fd);
12363 d_printf("tldap_context_create failed\n");
12367 rc = tldap_fetch_rootdse(ld);
12368 if (!TLDAP_RC_IS_SUCCESS(rc)) {
12369 d_printf("tldap_fetch_rootdse failed: %s\n",
12370 tldap_errstr(talloc_tos(), ld, rc));
12374 basedn = tldap_talloc_single_attribute(
12375 tldap_rootdse(ld), "defaultNamingContext", talloc_tos());
12376 if (basedn == NULL) {
12377 d_printf("no defaultNamingContext\n");
12380 d_printf("defaultNamingContext: %s\n", basedn);
12382 ev = samba_tevent_context_init(talloc_tos());
12384 d_printf("tevent_context_init failed\n");
12388 rc = tldap_gensec_bind(ld, torture_creds, "ldap", host, NULL,
12389 loadparm_init_s3(talloc_tos(),
12390 loadparm_s3_helpers()),
12391 GENSEC_FEATURE_SIGN | GENSEC_FEATURE_SEAL);
12393 if (!TLDAP_RC_IS_SUCCESS(rc)) {
12394 d_printf("tldap_gensec_bind failed\n");
12398 callback_code = TLDAP_SUCCESS;
12400 req = tldap_search_paged_send(talloc_tos(), ev, ld, basedn,
12401 TLDAP_SCOPE_SUB, "(objectclass=*)",
12403 NULL, 0, NULL, 0, 0, 0, 0, 5);
12405 d_printf("tldap_search_paged_send failed\n");
12408 tevent_req_set_callback(req, pagedsearch_cb, NULL);
12410 tevent_req_poll(req, ev);
12414 rc = callback_code;
12416 if (!TLDAP_RC_IS_SUCCESS(rc)) {
12417 d_printf("tldap_search with paging failed: %s\n",
12418 tldap_errstr(talloc_tos(), ld, rc));
12422 /* test search filters against rootDSE */
12423 filter = "(&(|(name=samba)(nextRid<=10000000)(usnChanged>=10)(samba~=ambas)(!(name=s*m*a)))"
12424 "(|(name:=samba)(name:dn:2.5.13.5:=samba)(:dn:2.5.13.5:=samba)(!(name=*samba))))";
12426 rc = tldap_search(ld, "", TLDAP_SCOPE_BASE, filter,
12427 NULL, 0, 0, NULL, 0, NULL, 0, 0, 0, 0,
12428 talloc_tos(), NULL);
12429 if (!TLDAP_RC_IS_SUCCESS(rc)) {
12430 d_printf("tldap_search with complex filter failed: %s\n",
12431 tldap_errstr(talloc_tos(), ld, rc));
12436 * Tests to check for regression of:
12438 * https://bugzilla.samba.org/show_bug.cgi?id=14029
12440 * TLDAP used here to pick apart the original string DN (with GUID)
12442 if (!tldap_test_dn_guid_format(ld, basedn, EXTENDED_NONE)) {
12443 d_printf("tldap_search with extended dn (no val) failed: %s\n",
12444 tldap_errstr(talloc_tos(), ld, rc));
12447 if (!tldap_test_dn_guid_format(ld, basedn, EXTENDED_ZERO)) {
12448 d_printf("tldap_search with extended dn (0) failed: %s\n",
12449 tldap_errstr(talloc_tos(), ld, rc));
12452 if (!tldap_test_dn_guid_format(ld, basedn, EXTENDED_ONE)) {
12453 d_printf("tldap_search with extended dn (1) failed: %s\n",
12454 tldap_errstr(talloc_tos(), ld, rc));
12462 /* Torture test to ensure no regression of :
12463 https://bugzilla.samba.org/show_bug.cgi?id=7084
12466 static bool run_dir_createtime(int dummy)
12468 struct cli_state *cli;
12469 const char *dname = "\\testdir_createtime";
12470 const char *fname = "\\testdir_createtime\\testfile";
12472 struct timespec create_time;
12473 struct timespec create_time1;
12478 if (!torture_open_connection(&cli, 0)) {
12482 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
12483 /* Ensure ino is zero, SMB2 gets a real one. */
12486 /* Ensure ino is -1, SMB1 never gets a real one. */
12487 ino = (uint64_t)-1;
12490 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
12491 cli_rmdir(cli, dname);
12493 status = cli_mkdir(cli, dname);
12494 if (!NT_STATUS_IS_OK(status)) {
12495 printf("mkdir failed: %s\n", nt_errstr(status));
12499 status = cli_qpathinfo2(cli,
12509 if (!NT_STATUS_IS_OK(status)) {
12510 printf("cli_qpathinfo2 returned %s\n",
12511 nt_errstr(status));
12515 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
12516 /* SMB2 should always return an inode. */
12518 printf("SMB2 bad inode (0)\n");
12522 /* SMB1 must always return zero here. */
12524 printf("SMB1 bad inode (!0)\n");
12529 /* Sleep 3 seconds, then create a file. */
12532 status = cli_openx(cli, fname, O_RDWR | O_CREAT | O_EXCL,
12534 if (!NT_STATUS_IS_OK(status)) {
12535 printf("cli_openx failed: %s\n", nt_errstr(status));
12539 status = cli_qpathinfo2(cli,
12549 if (!NT_STATUS_IS_OK(status)) {
12550 printf("cli_qpathinfo2 (2) returned %s\n",
12551 nt_errstr(status));
12555 if (timespec_compare(&create_time1, &create_time)) {
12556 printf("run_dir_createtime: create time was updated (error)\n");
12558 printf("run_dir_createtime: create time was not updated (correct)\n");
12564 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
12565 cli_rmdir(cli, dname);
12566 if (!torture_close_connection(cli)) {
12573 static bool run_streamerror(int dummy)
12575 struct cli_state *cli;
12576 const char *dname = "\\testdir_streamerror";
12577 const char *streamname =
12578 "testdir_streamerror:{4c8cc155-6c1e-11d1-8e41-00c04fb9386d}:$DATA";
12580 time_t change_time, access_time, write_time;
12586 if (!torture_open_connection(&cli, 0)) {
12590 torture_deltree(cli, dname);
12592 status = cli_mkdir(cli, dname);
12593 if (!NT_STATUS_IS_OK(status)) {
12594 printf("mkdir failed: %s\n", nt_errstr(status));
12598 status = cli_qpathinfo1(cli, streamname, &change_time, &access_time,
12599 &write_time, &size, &attr);
12600 if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
12601 printf("pathinfo returned %s, expected "
12602 "NT_STATUS_OBJECT_NAME_NOT_FOUND\n",
12603 nt_errstr(status));
12607 status = cli_ntcreate(cli, streamname, 0x16,
12608 FILE_READ_DATA|FILE_READ_EA|
12609 FILE_READ_ATTRIBUTES|READ_CONTROL_ACCESS,
12610 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ,
12611 FILE_OPEN, 0, 0, &fnum, NULL);
12613 if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
12614 printf("ntcreate returned %s, expected "
12615 "NT_STATUS_OBJECT_NAME_NOT_FOUND\n",
12616 nt_errstr(status));
12621 cli_rmdir(cli, dname);
12625 struct pidtest_state {
12631 static void pid_echo_done(struct tevent_req *subreq);
12633 static struct tevent_req *pid_echo_send(TALLOC_CTX *mem_ctx,
12634 struct tevent_context *ev,
12635 struct cli_state *cli)
12637 struct tevent_req *req, *subreq;
12638 struct pidtest_state *state;
12640 req = tevent_req_create(mem_ctx, &state, struct pidtest_state);
12645 SSVAL(state->vwv, 0, 1);
12646 state->data = data_blob_const("hello", 5);
12648 subreq = smb1cli_req_send(state,
12652 0, 0, /* *_flags */
12653 0, 0, /* *_flags2 */
12655 0xDEADBEEF, /* pid */
12657 NULL, /* session */
12658 ARRAY_SIZE(state->vwv), state->vwv,
12659 state->data.length, state->data.data);
12661 if (tevent_req_nomem(subreq, req)) {
12662 return tevent_req_post(req, ev);
12664 tevent_req_set_callback(subreq, pid_echo_done, req);
12668 static void pid_echo_done(struct tevent_req *subreq)
12670 struct tevent_req *req = tevent_req_callback_data(
12671 subreq, struct tevent_req);
12672 struct pidtest_state *state = tevent_req_data(
12673 req, struct pidtest_state);
12675 uint32_t num_bytes;
12676 uint8_t *bytes = NULL;
12677 struct iovec *recv_iov = NULL;
12678 uint8_t *phdr = NULL;
12679 uint16_t pidlow = 0;
12680 uint16_t pidhigh = 0;
12681 struct smb1cli_req_expected_response expected[] = {
12683 .status = NT_STATUS_OK,
12688 status = smb1cli_req_recv(subreq, state,
12693 NULL, /* pvwv_offset */
12696 NULL, /* pbytes_offset */
12698 expected, ARRAY_SIZE(expected));
12700 TALLOC_FREE(subreq);
12702 if (!NT_STATUS_IS_OK(status)) {
12703 tevent_req_nterror(req, status);
12707 if (num_bytes != state->data.length) {
12708 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
12712 if (memcmp(bytes, state->data.data, num_bytes) != 0) {
12713 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
12717 /* Check pid low/high == DEADBEEF */
12718 pidlow = SVAL(phdr, HDR_PID);
12719 if (pidlow != 0xBEEF){
12720 printf("Incorrect pidlow 0x%x, should be 0xBEEF\n",
12721 (unsigned int)pidlow);
12722 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
12725 pidhigh = SVAL(phdr, HDR_PIDHIGH);
12726 if (pidhigh != 0xDEAD){
12727 printf("Incorrect pidhigh 0x%x, should be 0xDEAD\n",
12728 (unsigned int)pidhigh);
12729 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
12733 tevent_req_done(req);
12736 static NTSTATUS pid_echo_recv(struct tevent_req *req)
12738 return tevent_req_simple_recv_ntstatus(req);
12741 static bool run_pidhigh(int dummy)
12743 bool success = false;
12744 struct cli_state *cli = NULL;
12746 struct tevent_context *ev = NULL;
12747 struct tevent_req *req = NULL;
12748 TALLOC_CTX *frame = talloc_stackframe();
12750 printf("starting pid high test\n");
12751 if (!torture_open_connection(&cli, 0)) {
12754 smbXcli_conn_set_sockopt(cli->conn, sockops);
12756 ev = samba_tevent_context_init(frame);
12761 req = pid_echo_send(frame, ev, cli);
12766 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
12770 status = pid_echo_recv(req);
12771 if (NT_STATUS_IS_OK(status)) {
12772 printf("pid high test ok\n");
12778 TALLOC_FREE(frame);
12779 torture_close_connection(cli);
12784 Test Windows open on a bad POSIX symlink.
12786 static bool run_symlink_open_test(int dummy)
12788 static struct cli_state *cli;
12789 const char *fname = "non_existant_file";
12790 const char *sname = "dangling_symlink";
12791 uint16_t fnum = (uint16_t)-1;
12792 bool correct = false;
12794 TALLOC_CTX *frame = NULL;
12796 frame = talloc_stackframe();
12798 printf("Starting Windows bad symlink open test\n");
12800 if (!torture_open_connection(&cli, 0)) {
12801 TALLOC_FREE(frame);
12805 smbXcli_conn_set_sockopt(cli->conn, sockops);
12807 status = torture_setup_unix_extensions(cli);
12808 if (!NT_STATUS_IS_OK(status)) {
12809 TALLOC_FREE(frame);
12813 /* Ensure nothing exists. */
12814 cli_setatr(cli, fname, 0, 0);
12815 cli_posix_unlink(cli, fname);
12816 cli_setatr(cli, sname, 0, 0);
12817 cli_posix_unlink(cli, sname);
12819 /* Create a symlink pointing nowhere. */
12820 status = cli_posix_symlink(cli, fname, sname);
12821 if (!NT_STATUS_IS_OK(status)) {
12822 printf("cli_posix_symlink of %s -> %s failed (%s)\n",
12825 nt_errstr(status));
12829 /* Now ensure that a Windows open doesn't hang. */
12830 status = cli_ntcreate(cli,
12833 FILE_READ_DATA|FILE_WRITE_DATA,
12835 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
12843 * We get either NT_STATUS_OBJECT_NAME_NOT_FOUND or
12844 * NT_STATUS_OBJECT_PATH_NOT_FOUND depending on if
12845 * we use O_NOFOLLOW on the server or not.
12847 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND) ||
12848 NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_PATH_NOT_FOUND))
12852 printf("cli_ntcreate of %s returned %s - should return"
12853 " either (%s) or (%s)\n",
12856 nt_errstr(NT_STATUS_OBJECT_NAME_NOT_FOUND),
12857 nt_errstr(NT_STATUS_OBJECT_PATH_NOT_FOUND));
12865 if (fnum != (uint16_t)-1) {
12866 cli_close(cli, fnum);
12867 fnum = (uint16_t)-1;
12870 cli_setatr(cli, sname, 0, 0);
12871 cli_posix_unlink(cli, sname);
12872 cli_setatr(cli, fname, 0, 0);
12873 cli_posix_unlink(cli, fname);
12875 if (!torture_close_connection(cli)) {
12879 TALLOC_FREE(frame);
12883 static NTSTATUS smb1_wild_mangle_list_fn(struct file_info *finfo,
12887 char **mangled_name_return = (char **)state;
12888 bool is_mangled = strchr(finfo->name, '~');
12891 *mangled_name_return = talloc_strdup(NULL, finfo->name);
12892 if (*mangled_name_return == NULL) {
12893 return NT_STATUS_NO_MEMORY;
12896 return NT_STATUS_OK;
12899 static bool run_smb1_wild_mangle_unlink_test(int dummy)
12901 static struct cli_state *cli_posix = NULL;
12902 static struct cli_state *cli = NULL;
12903 uint16_t fnum = (uint16_t)-1;
12904 bool correct = false;
12905 const char *dname = "smb1_wild_mangle_unlink";
12906 const char *aname = "smb1_wild_mangle_unlink/a";
12907 const char *star_name = "smb1_wild_mangle_unlink/*";
12908 char *windows_unlink_name = NULL;
12909 char *mangled_name = NULL;
12912 printf("Starting SMB1 wild mangle unlink test\n");
12914 /* Open a Windows connection. */
12915 if (!torture_open_connection(&cli, 0)) {
12919 smbXcli_conn_set_sockopt(cli->conn, sockops);
12921 /* Open a POSIX connection. */
12922 if (!torture_open_connection(&cli_posix, 0)) {
12926 smbXcli_conn_set_sockopt(cli_posix->conn, sockops);
12928 status = torture_setup_unix_extensions(cli_posix);
12929 if (!NT_STATUS_IS_OK(status)) {
12930 printf("server doesn't support POSIX\n");
12935 torture_deltree(cli, dname);
12938 * Create two files - 'a' and '*'.
12939 * We need POSIX extensions for this as '*'
12940 * is not a valid Windows name.
12943 status = cli_mkdir(cli, dname);
12944 if (!NT_STATUS_IS_OK(status)) {
12945 printf("cli_mkdir of %s returned %s\n",
12947 nt_errstr(status));
12951 status = cli_posix_open(cli_posix,
12953 O_RDWR|O_CREAT|O_EXCL,
12956 if (!NT_STATUS_IS_OK(status)) {
12957 printf("cli_posix_open (create) of %s returned %s\n",
12959 nt_errstr(status));
12962 status = cli_close(cli_posix, fnum);
12963 if (!NT_STATUS_IS_OK(status)) {
12966 status = cli_posix_open(cli_posix,
12968 O_RDWR|O_CREAT|O_EXCL,
12971 if (!NT_STATUS_IS_OK(status)) {
12972 printf("cli_posix_open (create) of %s returned %s\n",
12974 nt_errstr(status));
12977 status = cli_close(cli_posix, fnum);
12978 if (!NT_STATUS_IS_OK(status)) {
12982 status = cli_list(cli,
12985 smb1_wild_mangle_list_fn,
12987 if (!NT_STATUS_IS_OK(status)) {
12988 printf("cli_list of %s returned %s\n",
12990 nt_errstr(status));
12994 if (mangled_name == NULL) {
12998 printf("mangled_name = %s\n",
13002 * Try a Windows unlink with the mangled name.
13003 * This should *NOT* unlink the 'a' name.
13006 windows_unlink_name = talloc_asprintf(cli_posix,
13011 status = cli_unlink(cli, windows_unlink_name, 0);
13012 if (!NT_STATUS_IS_OK(status)) {
13013 printf("cli_unlink of %s returned %s\n",
13014 windows_unlink_name,
13015 nt_errstr(status));
13019 /* Does 'a' still exist ? */
13020 status = cli_posix_open(cli_posix,
13025 if (!NT_STATUS_IS_OK(status)) {
13026 printf("cli_posix_open O_RNONLY of %s returned %s\n",
13028 nt_errstr(status));
13032 status = cli_close(cli_posix, fnum);
13033 if (!NT_STATUS_IS_OK(status)) {
13041 TALLOC_FREE(windows_unlink_name);
13042 TALLOC_FREE(mangled_name);
13045 torture_deltree(cli, dname);
13046 torture_close_connection(cli);
13049 if (cli_posix != NULL) {
13050 torture_close_connection(cli_posix);
13056 static bool run_smb1_wild_mangle_rename_test(int dummy)
13058 static struct cli_state *cli_posix = NULL;
13059 static struct cli_state *cli = NULL;
13060 uint16_t fnum = (uint16_t)-1;
13061 bool correct = false;
13062 const char *dname = "smb1_wild_mangle_rename";
13063 const char *fooname = "smb1_wild_mangle_rename/foo";
13064 const char *foostar_name = "smb1_wild_mangle_rename/fo*";
13065 const char *wild_name = "smb1_wild_mangle_rename/*";
13066 char *windows_rename_src = NULL;
13067 const char *windows_rename_dst = "smb1_wild_mangle_rename\\bar";
13068 char *mangled_name = NULL;
13071 printf("Starting SMB1 wild mangle rename test\n");
13073 if (!torture_open_connection(&cli_posix, 0)) {
13077 smbXcli_conn_set_sockopt(cli_posix->conn, sockops);
13079 status = torture_setup_unix_extensions(cli_posix);
13080 if (!NT_STATUS_IS_OK(status)) {
13081 printf("server doesn't support POSIX\n");
13085 /* Open a Windows connection. */
13086 if (!torture_open_connection(&cli, 0)) {
13090 smbXcli_conn_set_sockopt(cli->conn, sockops);
13092 /* Ensure we start from fresh. */
13093 torture_deltree(cli, dname);
13096 * Create two files - 'foo' and 'fo*'.
13097 * We need POSIX extensions for this as 'fo*'
13098 * is not a valid Windows name.
13101 status = cli_posix_mkdir(cli_posix, dname, 0770);
13102 if (!NT_STATUS_IS_OK(status)) {
13103 printf("cli_posix_mkdir of %s returned %s\n",
13105 nt_errstr(status));
13109 status = cli_posix_open(cli_posix,
13111 O_RDWR|O_CREAT|O_EXCL,
13114 if (!NT_STATUS_IS_OK(status)) {
13115 printf("cli_posix_open (create) of %s returned %s\n",
13117 nt_errstr(status));
13120 status = cli_close(cli_posix, fnum);
13121 if (!NT_STATUS_IS_OK(status)) {
13124 status = cli_posix_open(cli_posix,
13126 O_RDWR|O_CREAT|O_EXCL,
13129 if (!NT_STATUS_IS_OK(status)) {
13130 printf("cli_posix_open (create) of %s returned %s\n",
13132 nt_errstr(status));
13135 status = cli_close(cli_posix, fnum);
13136 if (!NT_STATUS_IS_OK(status)) {
13141 * Get the mangled name. We can re-use the
13142 * previous smb1_wild_mangle_list_fn for this.
13145 status = cli_list(cli,
13148 smb1_wild_mangle_list_fn,
13150 if (!NT_STATUS_IS_OK(status)) {
13151 printf("cli_list of %s returned %s\n",
13153 nt_errstr(status));
13157 if (mangled_name == NULL) {
13161 printf("mangled_name = %s\n",
13165 * Try a Windows rename with the mangled name.
13166 * This should *NOT* rename the 'foo' name.
13169 windows_rename_src = talloc_asprintf(cli_posix,
13174 status = cli_rename(cli,
13175 windows_rename_src,
13176 windows_rename_dst,
13178 if (!NT_STATUS_IS_OK(status)) {
13179 printf("cli_rename of %s -> %s returned %s\n",
13180 windows_rename_src,
13181 windows_rename_dst,
13182 nt_errstr(status));
13186 /* Does 'foo' still exist ? */
13187 status = cli_posix_open(cli_posix,
13192 if (!NT_STATUS_IS_OK(status)) {
13193 printf("cli_posix_open O_RNONLY of %s returned %s\n",
13195 nt_errstr(status));
13199 status = cli_close(cli_posix, fnum);
13200 if (!NT_STATUS_IS_OK(status)) {
13208 TALLOC_FREE(mangled_name);
13209 TALLOC_FREE(windows_rename_src);
13212 torture_deltree(cli, dname);
13213 torture_close_connection(cli);
13216 torture_close_connection(cli_posix);
13222 * Only testing minimal time strings, as the others
13223 * need (locale-dependent) guessing at what strftime does and
13224 * even may differ in builds.
13226 static bool timesubst_test(void)
13228 TALLOC_CTX *ctx = NULL;
13229 /* Sa 23. Dez 04:33:20 CET 2017 */
13230 const struct timeval tv = { 1514000000, 123 };
13231 const char* expect_minimal = "20171223_033320";
13232 const char* expect_minus = "20171223_033320_000123";
13234 char *env_tz, *orig_tz = NULL;
13235 bool result = true;
13237 ctx = talloc_new(NULL);
13239 env_tz = getenv("TZ");
13241 orig_tz = talloc_strdup(ctx, env_tz);
13243 setenv("TZ", "UTC", 1);
13245 s = minimal_timeval_string(ctx, &tv, false);
13247 if(!s || strcmp(s, expect_minimal)) {
13248 printf("minimal_timeval_string(ctx, tv, false) returned [%s], expected "
13249 "[%s]\n", s ? s : "<nil>", expect_minimal);
13253 s = minimal_timeval_string(ctx, &tv, true);
13254 if(!s || strcmp(s, expect_minus)) {
13255 printf("minimal_timeval_string(ctx, tv, true) returned [%s], expected "
13256 "[%s]\n", s ? s : "<nil>", expect_minus);
13262 setenv("TZ", orig_tz, 1);
13269 static bool run_local_substitute(int dummy)
13273 ok &= subst_test("%U", "bla", "", -1, -1, "bla");
13274 ok &= subst_test("%u%U", "bla", "", -1, -1, "blabla");
13275 ok &= subst_test("%g", "", "", -1, -1, "NO_GROUP");
13276 ok &= subst_test("%G", "", "", -1, -1, "NO_GROUP");
13277 ok &= subst_test("%g", "", "", -1, 0, gidtoname(0));
13278 ok &= subst_test("%G", "", "", -1, 0, gidtoname(0));
13279 ok &= subst_test("%D%u", "u", "dom", -1, 0, "domu");
13280 ok &= subst_test("%i %I", "", "", -1, -1, "0.0.0.0 0.0.0.0");
13281 ok &= subst_test("%j %J", "", "", -1, -1, "0_0_0_0 0_0_0_0");
13282 /* Substitution depends on current time, so better test the underlying
13283 formatting function. At least covers %t. */
13284 ok &= timesubst_test();
13286 /* Different captialization rules in sub_basic... */
13288 ok &= (strcmp(talloc_sub_basic(talloc_tos(), "BLA", "dom", "%U%D"),
13294 static bool run_local_base64(int dummy)
13299 for (i=1; i<2000; i++) {
13300 DATA_BLOB blob1, blob2;
13303 blob1.data = talloc_array(talloc_tos(), uint8_t, i);
13305 generate_random_buffer(blob1.data, blob1.length);
13307 b64 = base64_encode_data_blob(talloc_tos(), blob1);
13309 d_fprintf(stderr, "base64_encode_data_blob failed "
13310 "for %d bytes\n", i);
13313 blob2 = base64_decode_data_blob(b64);
13316 if (data_blob_cmp(&blob1, &blob2)) {
13317 d_fprintf(stderr, "data_blob_cmp failed for %d "
13321 TALLOC_FREE(blob1.data);
13322 data_blob_free(&blob2);
13327 static void parse_fn(const struct gencache_timeout *t,
13329 void *private_data)
13334 static bool run_local_gencache(int dummy)
13340 struct memcache *mem;
13343 mem = memcache_init(NULL, 0);
13345 d_printf("%s: memcache_init failed\n", __location__);
13348 memcache_set_global(mem);
13350 if (!gencache_set("foo", "bar", time(NULL) + 1000)) {
13351 d_printf("%s: gencache_set() failed\n", __location__);
13355 if (!gencache_get("foo", NULL, NULL, NULL)) {
13356 d_printf("%s: gencache_get() failed\n", __location__);
13360 for (i=0; i<1000000; i++) {
13361 gencache_parse("foo", parse_fn, NULL);
13364 if (!gencache_get("foo", talloc_tos(), &val, &tm)) {
13365 d_printf("%s: gencache_get() failed\n", __location__);
13370 if (!gencache_get("foo", talloc_tos(), &val, &tm)) {
13371 d_printf("%s: gencache_get() failed\n", __location__);
13375 if (strcmp(val, "bar") != 0) {
13376 d_printf("%s: gencache_get() returned %s, expected %s\n",
13377 __location__, val, "bar");
13384 if (!gencache_del("foo")) {
13385 d_printf("%s: gencache_del() failed\n", __location__);
13388 if (gencache_del("foo")) {
13389 d_printf("%s: second gencache_del() succeeded\n",
13394 if (gencache_get("foo", talloc_tos(), &val, &tm)) {
13395 d_printf("%s: gencache_get() on deleted entry "
13396 "succeeded\n", __location__);
13400 blob = data_blob_string_const_null("bar");
13401 tm = time(NULL) + 60;
13403 if (!gencache_set_data_blob("foo", blob, tm)) {
13404 d_printf("%s: gencache_set_data_blob() failed\n", __location__);
13408 if (!gencache_get_data_blob("foo", talloc_tos(), &blob, NULL, NULL)) {
13409 d_printf("%s: gencache_get_data_blob() failed\n", __location__);
13413 if (strcmp((const char *)blob.data, "bar") != 0) {
13414 d_printf("%s: gencache_get_data_blob() returned %s, expected %s\n",
13415 __location__, (const char *)blob.data, "bar");
13416 data_blob_free(&blob);
13420 data_blob_free(&blob);
13422 if (!gencache_del("foo")) {
13423 d_printf("%s: gencache_del() failed\n", __location__);
13426 if (gencache_del("foo")) {
13427 d_printf("%s: second gencache_del() succeeded\n",
13432 if (gencache_get_data_blob("foo", talloc_tos(), &blob, NULL, NULL)) {
13433 d_printf("%s: gencache_get_data_blob() on deleted entry "
13434 "succeeded\n", __location__);
13439 blob.data = (uint8_t *)&v;
13440 blob.length = sizeof(v);
13442 if (!gencache_set_data_blob("blob", blob, tm)) {
13443 d_printf("%s: gencache_set_data_blob() failed\n",
13447 if (gencache_get("blob", talloc_tos(), &val, &tm)) {
13448 d_printf("%s: gencache_get succeeded\n", __location__);
13455 static bool rbt_testflags(struct db_context *db, const char *key,
13460 struct db_record *rec;
13462 rec = dbwrap_fetch_locked(db, db, string_tdb_data(key));
13464 d_fprintf(stderr, "fetch_locked failed\n");
13468 status = dbwrap_record_store(rec, string_tdb_data(value), TDB_MODIFY);
13469 if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
13470 d_fprintf(stderr, "store TDB_MODIFY unexpected status: %s\n",
13471 nt_errstr(status));
13475 status = dbwrap_record_store(rec, string_tdb_data("overwriteme"),
13477 if (!NT_STATUS_IS_OK(status)) {
13478 d_fprintf(stderr, "store TDB_INSERT failed: %s\n",
13479 nt_errstr(status));
13483 status = dbwrap_record_store(rec, string_tdb_data(value), TDB_INSERT);
13484 if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_COLLISION)) {
13485 d_fprintf(stderr, "store TDB_INSERT unexpected status: %s\n",
13486 nt_errstr(status));
13490 status = dbwrap_record_store(rec, string_tdb_data(value), TDB_MODIFY);
13491 if (!NT_STATUS_IS_OK(status)) {
13492 d_fprintf(stderr, "store TDB_MODIFY failed: %s\n",
13493 nt_errstr(status));
13503 static bool rbt_testval(struct db_context *db, const char *key,
13506 struct db_record *rec;
13507 TDB_DATA data = string_tdb_data(value);
13512 rec = dbwrap_fetch_locked(db, db, string_tdb_data(key));
13514 d_fprintf(stderr, "fetch_locked failed\n");
13517 status = dbwrap_record_store(rec, data, 0);
13518 if (!NT_STATUS_IS_OK(status)) {
13519 d_fprintf(stderr, "store failed: %s\n", nt_errstr(status));
13524 rec = dbwrap_fetch_locked(db, db, string_tdb_data(key));
13526 d_fprintf(stderr, "second fetch_locked failed\n");
13530 dbvalue = dbwrap_record_get_value(rec);
13531 if ((dbvalue.dsize != data.dsize)
13532 || (memcmp(dbvalue.dptr, data.dptr, data.dsize) != 0)) {
13533 d_fprintf(stderr, "Got wrong data back\n");
13543 static int local_rbtree_traverse_read(struct db_record *rec, void *private_data)
13545 int *count2 = (int *)private_data;
13550 static int local_rbtree_traverse_delete(struct db_record *rec, void *private_data)
13552 int *count2 = (int *)private_data;
13554 dbwrap_record_delete(rec);
13558 static bool run_local_rbtree(int dummy)
13560 struct db_context *db;
13567 db = db_open_rbt(NULL);
13570 d_fprintf(stderr, "db_open_rbt failed\n");
13574 if (!rbt_testflags(db, "firstkey", "firstval")) {
13578 for (i = 0; i < 999; i++) {
13579 char key[sizeof("key-9223372036854775807")];
13580 char value[sizeof("value-9223372036854775807")];
13582 snprintf(key, sizeof(key), "key%ld", random());
13583 snprintf(value, sizeof(value) ,"value%ld", random());
13585 if (!rbt_testval(db, key, value)) {
13589 snprintf(value, sizeof(value) ,"value%ld", random());
13591 if (!rbt_testval(db, key, value)) {
13597 count = 0; count2 = 0;
13598 status = dbwrap_traverse_read(db, local_rbtree_traverse_read,
13600 printf("%s: read1: %d %d, %s\n", __func__, count, count2, nt_errstr(status));
13601 if ((count != count2) || (count != 1000)) {
13604 count = 0; count2 = 0;
13605 status = dbwrap_traverse(db, local_rbtree_traverse_delete,
13607 printf("%s: delete: %d %d, %s\n", __func__, count, count2, nt_errstr(status));
13608 if ((count != count2) || (count != 1000)) {
13611 count = 0; count2 = 0;
13612 status = dbwrap_traverse_read(db, local_rbtree_traverse_read,
13614 printf("%s: read2: %d %d, %s\n", __func__, count, count2, nt_errstr(status));
13615 if ((count != count2) || (count != 0)) {
13626 local test for character set functions
13628 This is a very simple test for the functionality in convert_string_error()
13630 static bool run_local_convert_string(int dummy)
13632 TALLOC_CTX *tmp_ctx = talloc_new(NULL);
13633 const char *test_strings[2] = { "March", "M\303\244rz" };
13637 for (i=0; i<2; i++) {
13638 const char *str = test_strings[i];
13639 int len = strlen(str);
13640 size_t converted_size;
13643 memset(dst, 'X', sizeof(dst));
13645 /* first try with real source length */
13646 ret = convert_string_error(CH_UNIX, CH_UTF8,
13651 d_fprintf(stderr, "Failed to convert '%s' to CH_DISPLAY\n", str);
13655 if (converted_size != len) {
13656 d_fprintf(stderr, "Converted size of '%s' should be %d - got %d\n",
13657 str, len, (int)converted_size);
13661 if (strncmp(str, dst, converted_size) != 0) {
13662 d_fprintf(stderr, "Expected '%s' to match '%s'\n", str, dst);
13666 if (strlen(str) != converted_size) {
13667 d_fprintf(stderr, "Expected '%s' length %d - got %d\n", str,
13668 (int)strlen(str), (int)converted_size);
13672 if (dst[converted_size] != 'X') {
13673 d_fprintf(stderr, "Expected no termination of '%s'\n", dst);
13677 /* now with srclen==-1, this causes the nul to be
13679 ret = convert_string_error(CH_UNIX, CH_UTF8,
13684 d_fprintf(stderr, "Failed to convert '%s' to CH_DISPLAY\n", str);
13688 if (converted_size != len+1) {
13689 d_fprintf(stderr, "Converted size of '%s' should be %d - got %d\n",
13690 str, len, (int)converted_size);
13694 if (strncmp(str, dst, converted_size) != 0) {
13695 d_fprintf(stderr, "Expected '%s' to match '%s'\n", str, dst);
13699 if (len+1 != converted_size) {
13700 d_fprintf(stderr, "Expected '%s' length %d - got %d\n", str,
13701 len+1, (int)converted_size);
13705 if (dst[converted_size] != 'X') {
13706 d_fprintf(stderr, "Expected no termination of '%s'\n", dst);
13713 TALLOC_FREE(tmp_ctx);
13716 TALLOC_FREE(tmp_ctx);
13720 static bool run_local_string_to_sid(int dummy) {
13721 struct dom_sid sid;
13723 if (string_to_sid(&sid, "S--1-5-32-545")) {
13724 printf("allowing S--1-5-32-545\n");
13727 if (string_to_sid(&sid, "S-1-5-32-+545")) {
13728 printf("allowing S-1-5-32-+545\n");
13731 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")) {
13732 printf("allowing S-1-2-3-4-5-6-7-8-9-0-1-2-3-4-5-6-7-8-9-0\n");
13735 if (string_to_sid(&sid, "S-1-5-32-545-abc")) {
13736 printf("allowing S-1-5-32-545-abc\n");
13739 if (string_to_sid(&sid, "S-300-5-32-545")) {
13740 printf("allowing S-300-5-32-545\n");
13743 if (string_to_sid(&sid, "S-1-0xfffffffffffffe-32-545")) {
13744 printf("allowing S-1-0xfffffffffffffe-32-545\n");
13747 if (string_to_sid(&sid, "S-1-0xffffffffffff-5294967297-545")) {
13748 printf("allowing S-1-0xffffffffffff-5294967297-545\n");
13751 if (!string_to_sid(&sid, "S-1-0xfffffffffffe-32-545")) {
13752 printf("could not parse S-1-0xfffffffffffe-32-545\n");
13755 if (!string_to_sid(&sid, "S-1-5-32-545")) {
13756 printf("could not parse S-1-5-32-545\n");
13759 if (!dom_sid_equal(&sid, &global_sid_Builtin_Users)) {
13760 struct dom_sid_buf buf;
13761 printf("mis-parsed S-1-5-32-545 as %s\n",
13762 dom_sid_str_buf(&sid, &buf));
13768 static bool sid_to_string_test(const char *expected) {
13771 struct dom_sid sid;
13773 if (!string_to_sid(&sid, expected)) {
13774 printf("could not parse %s\n", expected);
13778 str = dom_sid_string(NULL, &sid);
13779 if (strcmp(str, expected)) {
13780 printf("Comparison failed (%s != %s)\n", str, expected);
13787 static bool run_local_sid_to_string(int dummy) {
13788 if (!sid_to_string_test("S-1-0xffffffffffff-1-1-1-1-1-1-1-1-1-1-1-1"))
13790 if (!sid_to_string_test("S-1-545"))
13792 if (!sid_to_string_test("S-255-3840-1-1-1-1"))
13797 static bool run_local_binary_to_sid(int dummy) {
13799 struct dom_sid *sid = talloc(NULL, struct dom_sid);
13800 static const uint8_t good_binary_sid[] = {
13801 0x1, /* revision number */
13802 15, /* num auths */
13803 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, /* id_auth */
13804 0x1, 0x1, 0x1, 0x1, /* auth[0] */
13805 0x1, 0x1, 0x1, 0x1, /* auth[1] */
13806 0x1, 0x1, 0x1, 0x1, /* auth[2] */
13807 0x1, 0x1, 0x1, 0x1, /* auth[3] */
13808 0x1, 0x1, 0x1, 0x1, /* auth[4] */
13809 0x1, 0x1, 0x1, 0x1, /* auth[5] */
13810 0x1, 0x1, 0x1, 0x1, /* auth[6] */
13811 0x1, 0x1, 0x1, 0x1, /* auth[7] */
13812 0x1, 0x1, 0x1, 0x1, /* auth[8] */
13813 0x1, 0x1, 0x1, 0x1, /* auth[9] */
13814 0x1, 0x1, 0x1, 0x1, /* auth[10] */
13815 0x1, 0x1, 0x1, 0x1, /* auth[11] */
13816 0x1, 0x1, 0x1, 0x1, /* auth[12] */
13817 0x1, 0x1, 0x1, 0x1, /* auth[13] */
13818 0x1, 0x1, 0x1, 0x1, /* auth[14] */
13821 static const uint8_t long_binary_sid[] = {
13822 0x1, /* revision number */
13823 15, /* num auths */
13824 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, /* id_auth */
13825 0x1, 0x1, 0x1, 0x1, /* auth[0] */
13826 0x1, 0x1, 0x1, 0x1, /* auth[1] */
13827 0x1, 0x1, 0x1, 0x1, /* auth[2] */
13828 0x1, 0x1, 0x1, 0x1, /* auth[3] */
13829 0x1, 0x1, 0x1, 0x1, /* auth[4] */
13830 0x1, 0x1, 0x1, 0x1, /* auth[5] */
13831 0x1, 0x1, 0x1, 0x1, /* auth[6] */
13832 0x1, 0x1, 0x1, 0x1, /* auth[7] */
13833 0x1, 0x1, 0x1, 0x1, /* auth[8] */
13834 0x1, 0x1, 0x1, 0x1, /* auth[9] */
13835 0x1, 0x1, 0x1, 0x1, /* auth[10] */
13836 0x1, 0x1, 0x1, 0x1, /* auth[11] */
13837 0x1, 0x1, 0x1, 0x1, /* auth[12] */
13838 0x1, 0x1, 0x1, 0x1, /* auth[13] */
13839 0x1, 0x1, 0x1, 0x1, /* auth[14] */
13840 0x1, 0x1, 0x1, 0x1, /* auth[15] */
13841 0x1, 0x1, 0x1, 0x1, /* auth[16] */
13842 0x1, 0x1, 0x1, 0x1, /* auth[17] */
13845 static const uint8_t long_binary_sid2[] = {
13846 0x1, /* revision number */
13847 32, /* num auths */
13848 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, /* id_auth */
13849 0x1, 0x1, 0x1, 0x1, /* auth[0] */
13850 0x1, 0x1, 0x1, 0x1, /* auth[1] */
13851 0x1, 0x1, 0x1, 0x1, /* auth[2] */
13852 0x1, 0x1, 0x1, 0x1, /* auth[3] */
13853 0x1, 0x1, 0x1, 0x1, /* auth[4] */
13854 0x1, 0x1, 0x1, 0x1, /* auth[5] */
13855 0x1, 0x1, 0x1, 0x1, /* auth[6] */
13856 0x1, 0x1, 0x1, 0x1, /* auth[7] */
13857 0x1, 0x1, 0x1, 0x1, /* auth[8] */
13858 0x1, 0x1, 0x1, 0x1, /* auth[9] */
13859 0x1, 0x1, 0x1, 0x1, /* auth[10] */
13860 0x1, 0x1, 0x1, 0x1, /* auth[11] */
13861 0x1, 0x1, 0x1, 0x1, /* auth[12] */
13862 0x1, 0x1, 0x1, 0x1, /* auth[13] */
13863 0x1, 0x1, 0x1, 0x1, /* auth[14] */
13864 0x1, 0x1, 0x1, 0x1, /* auth[15] */
13865 0x1, 0x1, 0x1, 0x1, /* auth[16] */
13866 0x1, 0x1, 0x1, 0x1, /* auth[17] */
13867 0x1, 0x1, 0x1, 0x1, /* auth[18] */
13868 0x1, 0x1, 0x1, 0x1, /* auth[19] */
13869 0x1, 0x1, 0x1, 0x1, /* auth[20] */
13870 0x1, 0x1, 0x1, 0x1, /* auth[21] */
13871 0x1, 0x1, 0x1, 0x1, /* auth[22] */
13872 0x1, 0x1, 0x1, 0x1, /* auth[23] */
13873 0x1, 0x1, 0x1, 0x1, /* auth[24] */
13874 0x1, 0x1, 0x1, 0x1, /* auth[25] */
13875 0x1, 0x1, 0x1, 0x1, /* auth[26] */
13876 0x1, 0x1, 0x1, 0x1, /* auth[27] */
13877 0x1, 0x1, 0x1, 0x1, /* auth[28] */
13878 0x1, 0x1, 0x1, 0x1, /* auth[29] */
13879 0x1, 0x1, 0x1, 0x1, /* auth[30] */
13880 0x1, 0x1, 0x1, 0x1, /* auth[31] */
13883 ret = sid_parse(good_binary_sid, sizeof(good_binary_sid), sid);
13887 ret = sid_parse(long_binary_sid2, sizeof(long_binary_sid2), sid);
13891 ret = sid_parse(long_binary_sid, sizeof(long_binary_sid), sid);
13898 /* Split a path name into filename and stream name components. Canonicalise
13899 * such that an implicit $DATA token is always explicit.
13901 * The "specification" of this function can be found in the
13902 * run_local_stream_name() function in torture.c, I've tried those
13903 * combinations against a W2k3 server.
13906 static NTSTATUS split_ntfs_stream_name(TALLOC_CTX *mem_ctx, const char *fname,
13907 char **pbase, char **pstream)
13910 char *stream = NULL;
13911 char *sname; /* stream name */
13912 const char *stype; /* stream type */
13914 DEBUG(10, ("split_ntfs_stream_name called for [%s]\n", fname));
13916 sname = strchr_m(fname, ':');
13918 if (sname == NULL) {
13919 if (pbase != NULL) {
13920 base = talloc_strdup(mem_ctx, fname);
13921 NT_STATUS_HAVE_NO_MEMORY(base);
13926 if (pbase != NULL) {
13927 base = talloc_strndup(mem_ctx, fname, PTR_DIFF(sname, fname));
13928 NT_STATUS_HAVE_NO_MEMORY(base);
13933 stype = strchr_m(sname, ':');
13935 if (stype == NULL) {
13936 sname = talloc_strdup(mem_ctx, sname);
13940 if (strcasecmp_m(stype, ":$DATA") != 0) {
13942 * If there is an explicit stream type, so far we only
13943 * allow $DATA. Is there anything else allowed? -- vl
13945 DEBUG(10, ("[%s] is an invalid stream type\n", stype));
13947 return NT_STATUS_OBJECT_NAME_INVALID;
13949 sname = talloc_strndup(mem_ctx, sname, PTR_DIFF(stype, sname));
13953 if (sname == NULL) {
13955 return NT_STATUS_NO_MEMORY;
13958 if (sname[0] == '\0') {
13960 * no stream name, so no stream
13965 if (pstream != NULL) {
13966 stream = talloc_asprintf(mem_ctx, "%s:%s", sname, stype);
13967 if (stream == NULL) {
13968 TALLOC_FREE(sname);
13970 return NT_STATUS_NO_MEMORY;
13973 * upper-case the type field
13975 (void)strupper_m(strchr_m(stream, ':')+1);
13979 if (pbase != NULL) {
13982 if (pstream != NULL) {
13985 return NT_STATUS_OK;
13988 static bool test_stream_name(const char *fname, const char *expected_base,
13989 const char *expected_stream,
13990 NTSTATUS expected_status)
13994 char *stream = NULL;
13996 status = split_ntfs_stream_name(talloc_tos(), fname, &base, &stream);
13997 if (!NT_STATUS_EQUAL(status, expected_status)) {
14001 if (!NT_STATUS_IS_OK(status)) {
14005 if (base == NULL) goto error;
14007 if (strcmp(expected_base, base) != 0) goto error;
14009 if ((expected_stream != NULL) && (stream == NULL)) goto error;
14010 if ((expected_stream == NULL) && (stream != NULL)) goto error;
14012 if ((stream != NULL) && (strcmp(expected_stream, stream) != 0))
14016 TALLOC_FREE(stream);
14020 d_fprintf(stderr, "Do test_stream(%s, %s, %s, %s)\n",
14021 fname, expected_base ? expected_base : "<NULL>",
14022 expected_stream ? expected_stream : "<NULL>",
14023 nt_errstr(expected_status));
14024 d_fprintf(stderr, "-> base=%s, stream=%s, status=%s\n",
14025 base ? base : "<NULL>", stream ? stream : "<NULL>",
14026 nt_errstr(status));
14028 TALLOC_FREE(stream);
14032 static bool run_local_stream_name(int dummy)
14036 ret &= test_stream_name(
14037 "bla", "bla", NULL, NT_STATUS_OK);
14038 ret &= test_stream_name(
14039 "bla::$DATA", "bla", NULL, NT_STATUS_OK);
14040 ret &= test_stream_name(
14041 "bla:blub:", "bla", NULL, NT_STATUS_OBJECT_NAME_INVALID);
14042 ret &= test_stream_name(
14043 "bla::", NULL, NULL, NT_STATUS_OBJECT_NAME_INVALID);
14044 ret &= test_stream_name(
14045 "bla::123", "bla", NULL, NT_STATUS_OBJECT_NAME_INVALID);
14046 ret &= test_stream_name(
14047 "bla:$DATA", "bla", "$DATA:$DATA", NT_STATUS_OK);
14048 ret &= test_stream_name(
14049 "bla:x:$DATA", "bla", "x:$DATA", NT_STATUS_OK);
14050 ret &= test_stream_name(
14051 "bla:x", "bla", "x:$DATA", NT_STATUS_OK);
14056 static bool data_blob_equal(DATA_BLOB a, DATA_BLOB b)
14058 if (a.length != b.length) {
14059 printf("a.length=%d != b.length=%d\n",
14060 (int)a.length, (int)b.length);
14063 if (memcmp(a.data, b.data, a.length) != 0) {
14064 printf("a.data and b.data differ\n");
14070 static bool run_local_memcache(int dummy)
14072 struct memcache *cache;
14073 DATA_BLOB k1, k2, k3, k4, k5;
14077 TALLOC_CTX *mem_ctx;
14083 size_t size1, size2;
14086 mem_ctx = talloc_init("foo");
14087 if (mem_ctx == NULL) {
14091 /* STAT_CACHE TESTS */
14093 cache = memcache_init(NULL, sizeof(void *) == 8 ? 200 : 100);
14095 if (cache == NULL) {
14096 printf("memcache_init failed\n");
14100 d1 = data_blob_const("d1", 2);
14101 d3 = data_blob_const("d3", 2);
14103 k1 = data_blob_const("d1", 2);
14104 k2 = data_blob_const("d2", 2);
14105 k3 = data_blob_const("d3", 2);
14106 k4 = data_blob_const("d4", 2);
14107 k5 = data_blob_const("d5", 2);
14109 memcache_add(cache, STAT_CACHE, k1, d1);
14111 if (!memcache_lookup(cache, STAT_CACHE, k1, &v1)) {
14112 printf("could not find k1\n");
14115 if (!data_blob_equal(d1, v1)) {
14119 memcache_add(cache, STAT_CACHE, k1, d3);
14121 if (!memcache_lookup(cache, STAT_CACHE, k1, &v3)) {
14122 printf("could not find replaced k1\n");
14125 if (!data_blob_equal(d3, v3)) {
14129 TALLOC_FREE(cache);
14131 /* GETWD_CACHE TESTS */
14132 str1 = talloc_strdup(mem_ctx, "string1");
14133 if (str1 == NULL) {
14136 ptr2 = str1; /* Keep an alias for comparison. */
14138 str2 = talloc_strdup(mem_ctx, "string2");
14139 if (str2 == NULL) {
14143 cache = memcache_init(NULL, sizeof(void *) == 8 ? 200 : 100);
14144 if (cache == NULL) {
14145 printf("memcache_init failed\n");
14149 memcache_add_talloc(cache, GETWD_CACHE, k2, &str1);
14150 /* str1 == NULL now. */
14151 ptr1 = memcache_lookup_talloc(cache, GETWD_CACHE, k2);
14152 if (ptr1 == NULL) {
14153 printf("could not find k2\n");
14156 if (ptr1 != ptr2) {
14157 printf("fetch of k2 got wrong string\n");
14161 /* Add a blob to ensure k2 gets purged. */
14162 d3 = data_blob_talloc_zero(mem_ctx, 180);
14163 memcache_add(cache, STAT_CACHE, k3, d3);
14165 ptr2 = memcache_lookup_talloc(cache, GETWD_CACHE, k2);
14166 if (ptr2 != NULL) {
14167 printf("Did find k2, should have been purged\n");
14172 * Test that talloc size also is accounted in memcache and
14173 * causes purge of other object.
14176 str1 = talloc_zero_size(mem_ctx, 100);
14177 str2 = talloc_zero_size(mem_ctx, 100);
14179 memcache_add_talloc(cache, GETWD_CACHE, k4, &str1);
14180 memcache_add_talloc(cache, GETWD_CACHE, k5, &str1);
14182 ptr3 = memcache_lookup_talloc(cache, GETWD_CACHE, k4);
14183 if (ptr3 != NULL) {
14184 printf("Did find k4, should have been purged\n");
14189 * Test that adding a duplicate non-talloced
14190 * key/value on top of a talloced key/value takes account
14191 * of the talloc_freed value size.
14193 TALLOC_FREE(cache);
14194 TALLOC_FREE(mem_ctx);
14196 mem_ctx = talloc_init("key_replace");
14197 if (mem_ctx == NULL) {
14201 cache = memcache_init(NULL, sizeof(void *) == 8 ? 200 : 100);
14202 if (cache == NULL) {
14207 * Add a 100 byte talloced string. This will
14208 * store a (4 or 8 byte) pointer and record the
14209 * total talloced size.
14211 str1 = talloc_zero_size(mem_ctx, 100);
14212 memcache_add_talloc(cache, GETWD_CACHE, k4, &str1);
14214 * Now overwrite with a small talloced
14215 * value. This should fit in the existing size
14216 * and the total talloced size should be removed
14217 * from the cache size.
14219 str1 = talloc_zero_size(mem_ctx, 2);
14220 memcache_add_talloc(cache, GETWD_CACHE, k4, &str1);
14222 * Now store a 20 byte string. If the
14223 * total talloced size wasn't accounted for
14224 * and removed in the overwrite, then this
14227 str2 = talloc_zero_size(mem_ctx, 20);
14228 memcache_add_talloc(cache, GETWD_CACHE, k5, &str2);
14230 ptr3 = memcache_lookup_talloc(cache, GETWD_CACHE, k4);
14231 if (ptr3 == NULL) {
14232 printf("Did not find k4, should not have been purged\n");
14236 TALLOC_FREE(cache);
14237 TALLOC_FREE(mem_ctx);
14239 mem_ctx = talloc_init("foo");
14240 if (mem_ctx == NULL) {
14244 cache = memcache_init(NULL, 0);
14245 if (cache == NULL) {
14249 str1 = talloc_strdup(mem_ctx, "string1");
14250 if (str1 == NULL) {
14253 str2 = talloc_strdup(mem_ctx, "string2");
14254 if (str2 == NULL) {
14257 memcache_add_talloc(cache, SINGLETON_CACHE_TALLOC,
14258 data_blob_string_const("torture"), &str1);
14259 size1 = talloc_total_size(cache);
14261 memcache_add_talloc(cache, SINGLETON_CACHE_TALLOC,
14262 data_blob_string_const("torture"), &str2);
14263 size2 = talloc_total_size(cache);
14265 printf("size1=%d, size2=%d\n", (int)size1, (int)size2);
14267 if (size2 > size1) {
14268 printf("memcache leaks memory!\n");
14274 TALLOC_FREE(cache);
14278 static void wbclient_done(struct tevent_req *req)
14281 struct winbindd_response *wb_resp;
14282 int *i = (int *)tevent_req_callback_data_void(req);
14284 wbc_err = wb_trans_recv(req, req, &wb_resp);
14287 d_printf("wb_trans_recv %d returned %s\n", *i, wbcErrorString(wbc_err));
14290 static bool run_wbclient_multi_ping(int dummy)
14292 struct tevent_context *ev;
14293 struct wb_context **wb_ctx;
14294 struct winbindd_request wb_req;
14295 bool result = false;
14298 BlockSignals(True, SIGPIPE);
14300 ev = tevent_context_init(talloc_tos());
14305 wb_ctx = talloc_array(ev, struct wb_context *, torture_nprocs);
14306 if (wb_ctx == NULL) {
14310 ZERO_STRUCT(wb_req);
14311 wb_req.cmd = WINBINDD_PING;
14313 d_printf("torture_nprocs=%d, numops=%d\n", (int)torture_nprocs, (int)torture_numops);
14315 for (i=0; i<torture_nprocs; i++) {
14316 wb_ctx[i] = wb_context_init(ev, NULL);
14317 if (wb_ctx[i] == NULL) {
14320 for (j=0; j<torture_numops; j++) {
14321 struct tevent_req *req;
14322 req = wb_trans_send(ev, ev, wb_ctx[i],
14323 (j % 2) == 0, &wb_req);
14327 tevent_req_set_callback(req, wbclient_done, &i);
14333 while (i < torture_nprocs * torture_numops) {
14334 tevent_loop_once(ev);
14343 static bool dbtrans_inc(struct db_context *db)
14345 struct db_record *rec;
14351 rec = dbwrap_fetch_locked(db, db, string_term_tdb_data("transtest"));
14353 printf(__location__ "fetch_lock failed\n");
14357 value = dbwrap_record_get_value(rec);
14359 if (value.dsize != sizeof(uint32_t)) {
14360 printf(__location__ "value.dsize = %d\n",
14365 memcpy(&val, value.dptr, sizeof(val));
14368 status = dbwrap_record_store(
14369 rec, make_tdb_data((uint8_t *)&val, sizeof(val)), 0);
14370 if (!NT_STATUS_IS_OK(status)) {
14371 printf(__location__ "store failed: %s\n",
14372 nt_errstr(status));
14382 static bool run_local_dbtrans(int dummy)
14384 struct db_context *db;
14385 struct db_record *rec;
14391 db = db_open(talloc_tos(), "transtest.tdb", 0, TDB_DEFAULT,
14392 O_RDWR|O_CREAT, 0600, DBWRAP_LOCK_ORDER_1,
14395 printf("Could not open transtest.db\n");
14399 res = dbwrap_transaction_start(db);
14401 printf(__location__ "transaction_start failed\n");
14405 rec = dbwrap_fetch_locked(db, db, string_term_tdb_data("transtest"));
14407 printf(__location__ "fetch_lock failed\n");
14411 value = dbwrap_record_get_value(rec);
14413 if (value.dptr == NULL) {
14415 status = dbwrap_record_store(
14416 rec, make_tdb_data((uint8_t *)&initial,
14419 if (!NT_STATUS_IS_OK(status)) {
14420 printf(__location__ "store returned %s\n",
14421 nt_errstr(status));
14428 res = dbwrap_transaction_commit(db);
14430 printf(__location__ "transaction_commit failed\n");
14435 uint32_t val, val2;
14438 res = dbwrap_transaction_start(db);
14440 printf(__location__ "transaction_start failed\n");
14444 status = dbwrap_fetch_uint32_bystring(db, "transtest", &val);
14445 if (!NT_STATUS_IS_OK(status)) {
14446 printf(__location__ "dbwrap_fetch_uint32 failed: %s\n",
14447 nt_errstr(status));
14451 for (i=0; i<10; i++) {
14452 if (!dbtrans_inc(db)) {
14457 status = dbwrap_fetch_uint32_bystring(db, "transtest", &val2);
14458 if (!NT_STATUS_IS_OK(status)) {
14459 printf(__location__ "dbwrap_fetch_uint32 failed: %s\n",
14460 nt_errstr(status));
14464 if (val2 != val + 10) {
14465 printf(__location__ "val=%d, val2=%d\n",
14466 (int)val, (int)val2);
14470 printf("val2=%d\r", val2);
14472 res = dbwrap_transaction_commit(db);
14474 printf(__location__ "transaction_commit failed\n");
14484 * Just a dummy test to be run under a debugger. There's no real way
14485 * to inspect the tevent_poll specific function from outside of
14489 static bool run_local_tevent_poll(int dummy)
14491 struct tevent_context *ev;
14492 struct tevent_fd *fd1, *fd2;
14493 bool result = false;
14495 ev = tevent_context_init_byname(NULL, "poll");
14497 d_fprintf(stderr, "tevent_context_init_byname failed\n");
14501 fd1 = tevent_add_fd(ev, ev, 2, 0, NULL, NULL);
14503 d_fprintf(stderr, "tevent_add_fd failed\n");
14506 fd2 = tevent_add_fd(ev, ev, 3, 0, NULL, NULL);
14508 d_fprintf(stderr, "tevent_add_fd failed\n");
14513 fd2 = tevent_add_fd(ev, ev, 1, 0, NULL, NULL);
14515 d_fprintf(stderr, "tevent_add_fd failed\n");
14525 static bool run_local_hex_encode_buf(int dummy)
14531 for (i=0; i<sizeof(src); i++) {
14534 hex_encode_buf(buf, src, sizeof(src));
14535 if (strcmp(buf, "0001020304050607") != 0) {
14538 hex_encode_buf(buf, NULL, 0);
14539 if (buf[0] != '\0') {
14545 static const char *remove_duplicate_addrs2_test_strings_vector[] = {
14567 "1001:1111:1111:1000:0:1111:1111:1111",
14576 static const char *remove_duplicate_addrs2_test_strings_result[] = {
14590 "1001:1111:1111:1000:0:1111:1111:1111"
14593 static bool run_local_remove_duplicate_addrs2(int dummy)
14595 struct samba_sockaddr test_vector[28];
14598 /* Construct the sockaddr_storage test vector. */
14599 for (i = 0; i < 28; i++) {
14600 struct addrinfo hints;
14601 struct addrinfo *res = NULL;
14604 memset(&hints, '\0', sizeof(hints));
14605 hints.ai_flags = AI_NUMERICHOST;
14606 ret = getaddrinfo(remove_duplicate_addrs2_test_strings_vector[i],
14611 fprintf(stderr, "getaddrinfo failed on [%s]\n",
14612 remove_duplicate_addrs2_test_strings_vector[i]);
14615 memset(&test_vector[i], '\0', sizeof(test_vector[i]));
14616 memcpy(&test_vector[i].u.ss,
14622 count = remove_duplicate_addrs2(test_vector, i);
14625 fprintf(stderr, "count wrong (%zu) should be 14\n",
14630 for (i = 0; i < count; i++) {
14631 char addr[INET6_ADDRSTRLEN];
14633 print_sockaddr(addr, sizeof(addr), &test_vector[i].u.ss);
14635 if (strcmp(addr, remove_duplicate_addrs2_test_strings_result[i]) != 0) {
14636 fprintf(stderr, "mismatch on [%zu] [%s] [%s]\n",
14639 remove_duplicate_addrs2_test_strings_result[i]);
14644 printf("run_local_remove_duplicate_addrs2: success\n");
14648 static bool run_local_tdb_opener(int dummy)
14654 t = tdb_open("test.tdb", 1000, TDB_CLEAR_IF_FIRST,
14655 O_RDWR|O_CREAT, 0755);
14657 perror("tdb_open failed");
14668 static bool run_local_tdb_writer(int dummy)
14674 t = tdb_open("test.tdb", 1000, 0, O_RDWR|O_CREAT, 0755);
14676 perror("tdb_open failed");
14680 val.dptr = (uint8_t *)&v;
14681 val.dsize = sizeof(v);
14687 ret = tdb_store(t, val, val, 0);
14689 printf("%s\n", tdb_errorstr(t));
14694 data = tdb_fetch(t, val);
14695 if (data.dptr != NULL) {
14696 SAFE_FREE(data.dptr);
14702 static bool run_local_canonicalize_path(int dummy)
14704 const char *src[] = {
14711 ".././././../../../boo",
14723 "/foo/bar/../baz/",
14724 "////////////////",
14725 "/////////./././././.",
14726 "/./.././../.boo/../baz",
14727 "/a/component/path",
14728 "/a/component/path/",
14729 "/a/component/path/..",
14730 "/a/component/../path/",
14731 "///a/./././///component/../////path/",
14734 const char *dst[] = {
14757 "/a/component/path",
14758 "/a/component/path",
14766 for (i = 0; src[i] != NULL; i++) {
14767 char *d = canonicalize_absolute_path(talloc_tos(), src[i]);
14769 perror("talloc fail\n");
14772 if (strcmp(d, dst[i]) != 0) {
14774 "canonicalize mismatch %s -> %s != %s",
14775 src[i], d, dst[i]);
14782 struct session_setup_nt1_truncated_state {
14787 static void smb1_session_setup_nt1_truncated_done(struct tevent_req *subreq);
14789 static struct tevent_req *smb1_session_setup_nt1_truncated_send(
14790 TALLOC_CTX *mem_ctx,
14791 struct tevent_context *ev,
14792 struct smbXcli_conn *conn)
14794 uint16_t *vwv = NULL;
14795 uint8_t *bytes = NULL;
14796 const char *pass = "12345678";
14797 const char *uname = "z";
14798 struct session_setup_nt1_truncated_state *state = NULL;
14799 struct tevent_req *req = NULL;
14800 struct tevent_req *subreq = NULL;
14802 req = tevent_req_create(mem_ctx,
14804 struct session_setup_nt1_truncated_state);
14808 vwv = &state->vwv[0];
14809 bytes = &state->bytes[0];
14811 SCVAL(vwv+0, 0, 0xff);
14812 SCVAL(vwv+0, 1, 0);
14813 SSVAL(vwv+1, 0, 0);
14814 SSVAL(vwv+2, 0, 8192);
14815 SSVAL(vwv+3, 0, 2);
14816 SSVAL(vwv+4, 0, 1);
14817 SIVAL(vwv+5, 0, 0);
14818 SSVAL(vwv+7, 0, strlen(pass)); /* OEMPasswordLen */
14819 SSVAL(vwv+8, 0, 0); /* UnicodePasswordLen */
14820 SSVAL(vwv+9, 0, 0); /* reserved */
14821 SSVAL(vwv+10, 0, 0); /* reserved */
14822 SIVAL(vwv+11, 0, CAP_STATUS32);
14824 memcpy(bytes, pass, strlen(pass));
14825 bytes += strlen(pass);
14826 memcpy(bytes, uname, strlen(uname)+1);
14828 subreq = smb1cli_req_send(state, ev, conn,
14830 0, /* additional_flags */
14831 0, /* clear_flags */
14832 0, /* additional_flags2 */
14833 0, /* clear_flags2 */
14834 10000, /* timeout_msec */
14837 NULL, /* session */
14840 strlen(pass), /* Truncate length at password. */
14842 if (tevent_req_nomem(subreq, req)) {
14843 return tevent_req_post(req, ev);
14845 tevent_req_set_callback(subreq,
14846 smb1_session_setup_nt1_truncated_done,
14851 static void smb1_session_setup_nt1_truncated_done(struct tevent_req *subreq)
14853 struct tevent_req *req =
14854 tevent_req_callback_data(subreq,
14855 struct tevent_req);
14856 struct session_setup_nt1_truncated_state *state =
14857 tevent_req_data(req,
14858 struct session_setup_nt1_truncated_state);
14860 struct smb1cli_req_expected_response expected[] = {
14862 .status = NT_STATUS_OK,
14867 status = smb1cli_req_recv(subreq, state,
14872 NULL, /* pvwv_offset */
14875 NULL, /* pbytes_offset */
14877 expected, ARRAY_SIZE(expected));
14878 TALLOC_FREE(subreq);
14879 if (tevent_req_nterror(req, status)) {
14882 tevent_req_done(req);
14885 static NTSTATUS smb1_session_setup_nt1_truncated_recv(struct tevent_req *req)
14887 return tevent_req_simple_recv_ntstatus(req);
14890 static bool run_smb1_truncated_sesssetup(int dummy)
14892 struct tevent_context *ev;
14893 struct tevent_req *req;
14894 struct smbXcli_conn *conn;
14895 struct sockaddr_storage ss;
14900 printf("Starting send truncated SMB1 sesssetup.\n");
14902 ok = resolve_name(host, &ss, 0x20, true);
14904 d_fprintf(stderr, "Could not resolve name %s\n", host);
14908 status = open_socket_out(&ss, 445, 10000, &fd);
14909 if (!NT_STATUS_IS_OK(status)) {
14910 d_fprintf(stderr, "open_socket_out failed: %s\n",
14911 nt_errstr(status));
14915 conn = smbXcli_conn_create(talloc_tos(), fd, host, SMB_SIGNING_OFF, 0,
14917 if (conn == NULL) {
14918 d_fprintf(stderr, "smbXcli_conn_create failed\n");
14922 status = smbXcli_negprot(conn,
14929 if (!NT_STATUS_IS_OK(status)) {
14930 d_fprintf(stderr, "smbXcli_negprot failed!\n");
14934 ev = samba_tevent_context_init(talloc_tos());
14936 d_fprintf(stderr, "samba_tevent_context_init failed\n");
14940 req = smb1_session_setup_nt1_truncated_send(ev, ev, conn);
14942 d_fprintf(stderr, "smb1_session_setup_nt1_truncated_send failed\n");
14946 ok = tevent_req_poll_ntstatus(req, ev, &status);
14948 d_fprintf(stderr, "tevent_req_poll failed with status %s\n",
14949 nt_errstr(status));
14953 status = smb1_session_setup_nt1_truncated_recv(req);
14954 if (!NT_STATUS_IS_OK(status)) {
14955 d_fprintf(stderr, "smb1_session_setup_nt1_truncated_recv returned "
14956 "%s, expected NT_STATUS_OK\n",
14957 nt_errstr(status));
14965 struct smb1_negotiate_exit_state {
14969 static void smb1_negotiate_exit_done(struct tevent_req *subreq);
14971 static struct tevent_req *smb1_negotiate_exit_send(
14972 TALLOC_CTX *mem_ctx,
14973 struct tevent_context *ev,
14974 struct smbXcli_conn *conn)
14976 struct smb1_negotiate_exit_state *state = NULL;
14977 struct tevent_req *req = NULL;
14978 struct tevent_req *subreq = NULL;
14980 req = tevent_req_create(mem_ctx,
14982 struct smb1_negotiate_exit_state);
14986 subreq = smb1cli_req_send(state, ev, conn,
14988 0, /* additional_flags */
14989 0, /* clear_flags */
14990 0, /* additional_flags2 */
14991 0, /* clear_flags2 */
14992 10000, /* timeout_msec */
14995 NULL, /* session */
15000 if (tevent_req_nomem(subreq, req)) {
15001 return tevent_req_post(req, ev);
15003 tevent_req_set_callback(subreq,
15004 smb1_negotiate_exit_done,
15009 static void smb1_negotiate_exit_done(struct tevent_req *subreq)
15011 struct tevent_req *req =
15012 tevent_req_callback_data(subreq,
15013 struct tevent_req);
15014 struct smb1_negotiate_exit_state *state =
15015 tevent_req_data(req,
15016 struct smb1_negotiate_exit_state);
15018 struct smb1cli_req_expected_response expected[] = {
15020 .status = NT_STATUS_OK,
15025 status = smb1cli_req_recv(subreq, state,
15030 NULL, /* pvwv_offset */
15033 NULL, /* pbytes_offset */
15035 expected, ARRAY_SIZE(expected));
15036 TALLOC_FREE(subreq);
15037 if (tevent_req_nterror(req, status)) {
15040 tevent_req_done(req);
15043 static NTSTATUS smb1_negotiate_exit_recv(struct tevent_req *req)
15045 return tevent_req_simple_recv_ntstatus(req);
15048 static bool do_smb1_exit(TALLOC_CTX *mem_ctx,
15049 struct tevent_context *ev,
15050 struct smbXcli_conn *conn)
15052 struct tevent_req *req;
15055 NTSTATUS expected_status = NT_STATUS_DOS(ERRSRV, ERRinvnid);;
15057 req = smb1_negotiate_exit_send(ev, ev, conn);
15059 d_fprintf(stderr, "smb1_negotiate_exit_send failed\n");
15063 ok = tevent_req_poll_ntstatus(req, ev, &status);
15065 d_fprintf(stderr, "tevent_req_poll failed with status %s\n",
15066 nt_errstr(status));
15070 status = smb1_negotiate_exit_recv(req);
15071 if (!NT_STATUS_EQUAL(status, expected_status)) {
15072 d_fprintf(stderr, "smb1_negotiate_exit_recv returned "
15073 "%s, expected ERRSRV, ERRinvnid\n",
15074 nt_errstr(status));
15080 static bool run_smb1_negotiate_exit(int dummy)
15082 struct tevent_context *ev;
15083 struct smbXcli_conn *conn;
15084 struct sockaddr_storage ss;
15089 printf("Starting send SMB1 negotiate+exit.\n");
15091 ok = resolve_name(host, &ss, 0x20, true);
15093 d_fprintf(stderr, "Could not resolve name %s\n", host);
15097 status = open_socket_out(&ss, 445, 10000, &fd);
15098 if (!NT_STATUS_IS_OK(status)) {
15099 d_fprintf(stderr, "open_socket_out failed: %s\n",
15100 nt_errstr(status));
15104 conn = smbXcli_conn_create(talloc_tos(), fd, host, SMB_SIGNING_OFF, 0,
15106 if (conn == NULL) {
15107 d_fprintf(stderr, "smbXcli_conn_create failed\n");
15111 status = smbXcli_negprot(conn,
15118 if (!NT_STATUS_IS_OK(status)) {
15119 d_fprintf(stderr, "smbXcli_negprot failed!\n");
15123 ev = samba_tevent_context_init(talloc_tos());
15125 d_fprintf(stderr, "samba_tevent_context_init failed\n");
15130 * Call do_smb1_exit twice to catch a server crash, the
15131 * server sends the first return code then crashes.
15133 ok = do_smb1_exit(ev, ev, conn);
15135 d_fprintf(stderr, "do_smb1_exit (1) failed\n");
15138 ok = do_smb1_exit(ev, ev, conn);
15140 d_fprintf(stderr, "do_smb1_exit (2) failed\n");
15148 static bool run_smb1_negotiate_tcon(int dummy)
15150 struct cli_state *cli = NULL;
15152 uint16_t max_xmit = 0;
15155 printf("Starting send SMB1 negotiate+tcon.\n");
15156 cli = open_nbt_connection();
15158 d_fprintf(stderr, "open_nbt_connection failed!\n");
15161 smbXcli_conn_set_sockopt(cli->conn, sockops);
15163 status = smbXcli_negprot(cli->conn,
15170 if (!NT_STATUS_IS_OK(status)) {
15171 d_fprintf(stderr, "smbXcli_negprot failed %s!\n",
15172 nt_errstr(status));
15175 status = cli_raw_tcon(cli,
15181 if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
15182 d_fprintf(stderr, "cli_raw_tcon failed - got %s "
15183 "(should get NT_STATUS_ACCESS_DENIED)!\n",
15184 nt_errstr(status));
15190 static bool run_ign_bad_negprot(int dummy)
15192 struct tevent_context *ev;
15193 struct tevent_req *req;
15194 struct smbXcli_conn *conn;
15195 struct sockaddr_storage ss;
15200 printf("starting ignore bad negprot\n");
15202 ok = resolve_name(host, &ss, 0x20, true);
15204 d_fprintf(stderr, "Could not resolve name %s\n", host);
15208 status = open_socket_out(&ss, 445, 10000, &fd);
15209 if (!NT_STATUS_IS_OK(status)) {
15210 d_fprintf(stderr, "open_socket_out failed: %s\n",
15211 nt_errstr(status));
15215 conn = smbXcli_conn_create(talloc_tos(), fd, host, SMB_SIGNING_OFF, 0,
15217 if (conn == NULL) {
15218 d_fprintf(stderr, "smbXcli_conn_create failed\n");
15222 status = smbXcli_negprot(conn,
15229 if (NT_STATUS_IS_OK(status)) {
15230 d_fprintf(stderr, "smbXcli_negprot succeeded!\n");
15234 ev = samba_tevent_context_init(talloc_tos());
15236 d_fprintf(stderr, "samba_tevent_context_init failed\n");
15240 req = smb1cli_session_setup_nt1_send(
15241 ev, ev, conn, 0, getpid(), NULL, 65503, 2, 1, 0, "", "",
15242 data_blob_null, data_blob_null, 0x40,
15243 "Windows 2000 2195", "Windows 2000 5.0");
15245 d_fprintf(stderr, "smb1cli_session_setup_nt1_send failed\n");
15249 ok = tevent_req_poll_ntstatus(req, ev, &status);
15251 d_fprintf(stderr, "tevent_req_poll failed\n");
15255 status = smb1cli_session_setup_nt1_recv(req, NULL, NULL, NULL, NULL,
15257 if (!NT_STATUS_EQUAL(status, NT_STATUS_CONNECTION_RESET)) {
15258 d_fprintf(stderr, "smb1cli_session_setup_nt1_recv returned "
15259 "%s, expected NT_STATUS_CONNECTION_RESET\n",
15260 nt_errstr(status));
15266 printf("starting ignore bad negprot\n");
15272 static double create_procs(bool (*fn)(int), bool *result)
15275 volatile pid_t *child_status;
15276 volatile bool *child_status_out;
15279 struct timeval start;
15283 child_status = (volatile pid_t *)anonymous_shared_allocate(sizeof(pid_t)*torture_nprocs);
15284 if (!child_status) {
15285 printf("Failed to setup shared memory\n");
15289 child_status_out = (volatile bool *)anonymous_shared_allocate(sizeof(bool)*torture_nprocs);
15290 if (!child_status_out) {
15291 printf("Failed to setup result status shared memory\n");
15295 for (i = 0; i < torture_nprocs; i++) {
15296 child_status[i] = 0;
15297 child_status_out[i] = True;
15300 start = timeval_current();
15302 for (i=0;i<torture_nprocs;i++) {
15305 pid_t mypid = getpid();
15306 sys_srandom(((int)mypid) ^ ((int)time(NULL)));
15308 slprintf(myname,sizeof(myname),"CLIENT%d", i);
15311 if (torture_open_connection(¤t_cli, i)) break;
15312 if (tries-- == 0) {
15313 printf("pid %d failed to start\n", (int)getpid());
15319 child_status[i] = getpid();
15321 while (child_status[i] && timeval_elapsed(&start) < 5) smb_msleep(2);
15323 child_status_out[i] = fn(i);
15330 for (i=0;i<torture_nprocs;i++) {
15331 if (child_status[i]) synccount++;
15333 if (synccount == torture_nprocs) break;
15335 } while (timeval_elapsed(&start) < 30);
15337 if (synccount != torture_nprocs) {
15338 printf("FAILED TO START %d CLIENTS (started %d)\n", torture_nprocs, synccount);
15340 return timeval_elapsed(&start);
15343 /* start the client load */
15344 start = timeval_current();
15346 for (i=0;i<torture_nprocs;i++) {
15347 child_status[i] = 0;
15350 printf("%d clients started\n", torture_nprocs);
15352 for (i=0;i<torture_nprocs;i++) {
15353 while (waitpid(0, &status, 0) == -1 && errno == EINTR) /* noop */ ;
15358 for (i=0;i<torture_nprocs;i++) {
15359 if (!child_status_out[i]) {
15363 return timeval_elapsed(&start);
15366 #define FLAG_MULTIPROC 1
15372 } torture_ops[] = {
15375 .fn = run_fdpasstest,
15379 .fn = run_locktest1,
15383 .fn = run_locktest2,
15387 .fn = run_locktest3,
15391 .fn = run_locktest4,
15395 .fn = run_locktest5,
15399 .fn = run_locktest6,
15403 .fn = run_locktest7,
15407 .fn = run_locktest8,
15411 .fn = run_locktest9a,
15415 .fn = run_locktest9b,
15419 .fn = run_locktest10,
15423 .fn = run_locktest11,
15427 .fn = run_locktest12,
15431 .fn = run_locktest13,
15435 .fn = run_unlinktest,
15439 .fn = run_browsetest,
15443 .fn = run_attrtest,
15447 .fn = run_trans2test,
15451 .fn = run_maxfidtest,
15452 .flags = FLAG_MULTIPROC,
15457 .flags = FLAG_MULTIPROC,
15460 .name = "RANDOMIPC",
15461 .fn = run_randomipc,
15464 .name = "NEGNOWAIT",
15465 .fn = run_negprot_nowait,
15487 #ifdef HAVE_KERNEL_OPLOCKS_LINUX
15499 .fn = run_dirtest1,
15502 .name = "DIR-CREATETIME",
15503 .fn = run_dir_createtime,
15507 .fn = torture_denytest1,
15511 .fn = torture_denytest2,
15515 .fn = run_tcon_test,
15519 .fn = run_tcon_devtype_test,
15523 .fn = run_readwritetest,
15527 .fn = run_readwritemulti,
15528 .flags = FLAG_MULTIPROC
15532 .fn = run_readwritelarge,
15535 .name = "RW-SIGNING",
15536 .fn = run_readwritelarge_signtest,
15540 .fn = run_opentest,
15544 .fn = run_simple_posix_open_test,
15547 .name = "POSIX-APPEND",
15548 .fn = run_posix_append,
15551 .name = "POSIX-SYMLINK-ACL",
15552 .fn = run_acl_symlink_test,
15555 .name = "POSIX-SYMLINK-EA",
15556 .fn = run_ea_symlink_test,
15559 .name = "POSIX-STREAM-DELETE",
15560 .fn = run_posix_stream_delete,
15563 .name = "POSIX-OFD-LOCK",
15564 .fn = run_posix_ofd_lock_test,
15567 .name = "POSIX-BLOCKING-LOCK",
15568 .fn = run_posix_blocking_lock,
15571 .name = "POSIX-MKDIR",
15572 .fn = run_posix_mkdir_test,
15575 .name = "POSIX-ACL-OPLOCK",
15576 .fn = run_posix_acl_oplock_test,
15579 .name = "POSIX-ACL-SHAREROOT",
15580 .fn = run_posix_acl_shareroot_test,
15583 .name = "POSIX-LS-WILDCARD",
15584 .fn = run_posix_ls_wildcard_test,
15587 .name = "POSIX-LS-SINGLE",
15588 .fn = run_posix_ls_single_test,
15591 .name = "POSIX-READLINK",
15592 .fn = run_posix_readlink_test,
15595 .name = "POSIX-STAT",
15596 .fn = run_posix_stat_test,
15599 .name = "POSIX-SYMLINK-PARENT",
15600 .fn = run_posix_symlink_parent_test,
15603 .name = "POSIX-SYMLINK-CHMOD",
15604 .fn = run_posix_symlink_chmod_test,
15607 .name = "POSIX-SYMLINK-RENAME",
15608 .fn = run_posix_symlink_rename_test,
15611 .name = "POSIX-DIR-DEFAULT-ACL",
15612 .fn = run_posix_dir_default_acl_test,
15615 .name = "POSIX-SYMLINK-GETPATHINFO",
15616 .fn = run_posix_symlink_getpathinfo_test,
15619 .name = "POSIX-SYMLINK-SETPATHINFO",
15620 .fn = run_posix_symlink_setpathinfo_test,
15623 .name = "WINDOWS-BAD-SYMLINK",
15624 .fn = run_symlink_open_test,
15627 .name = "SMB1-WILD-MANGLE-UNLINK",
15628 .fn = run_smb1_wild_mangle_unlink_test,
15631 .name = "SMB1-WILD-MANGLE-RENAME",
15632 .fn = run_smb1_wild_mangle_rename_test,
15635 .name = "CASE-INSENSITIVE-CREATE",
15636 .fn = run_case_insensitive_create,
15639 .name = "ASYNC-ECHO",
15640 .fn = run_async_echo,
15643 .name = "UID-REGRESSION-TEST",
15644 .fn = run_uid_regression_test,
15647 .name = "SHORTNAME-TEST",
15648 .fn = run_shortname_test,
15651 .name = "ADDRCHANGE",
15652 .fn = run_addrchange,
15656 .name = "OPENATTR",
15657 .fn = run_openattrtest,
15669 .name = "RENAME-ACCESS",
15670 .fn = run_rename_access,
15673 .name = "OWNER-RIGHTS",
15674 .fn = run_owner_rights,
15678 .fn = run_deletetest,
15681 .name = "DELETE-STREAM",
15682 .fn = run_delete_stream,
15685 .name = "DELETE-PRINT",
15686 .fn = run_delete_print_test,
15689 .name = "DELETE-LN",
15690 .fn = run_deletetest_ln,
15693 .name = "PROPERTIES",
15694 .fn = run_properties,
15698 .fn = torture_mangle,
15705 .name = "MANGLE-ILLEGAL",
15706 .fn = run_mangle_illegal,
15713 .name = "TRANS2SCAN",
15714 .fn = torture_trans2_scan,
15717 .name = "NTTRANSSCAN",
15718 .fn = torture_nttrans_scan,
15722 .fn = torture_utable,
15725 .name = "CASETABLE",
15726 .fn = torture_casetable,
15729 .name = "ERRMAPEXTRACT",
15730 .fn = run_error_map_extract,
15733 .name = "PIPE_NUMBER",
15734 .fn = run_pipe_number,
15738 .fn = run_tcon2_test,
15742 .fn = torture_ioctl_test,
15746 .fn = torture_chkpath_test,
15750 .fn = run_fdsesstest,
15757 .name = "SESSSETUP_BENCH",
15758 .fn = run_sesssetup_bench,
15773 .name = "WINDOWS-WRITE",
15774 .fn = run_windows_write,
15777 .name = "LARGE_READX",
15778 .fn = run_large_readx,
15781 .name = "MSDFS-ATTRIBUTE",
15782 .fn = run_msdfs_attribute,
15785 .name = "NTTRANS-CREATE",
15786 .fn = run_nttrans_create,
15789 .name = "NTTRANS-FSCTL",
15790 .fn = run_nttrans_fsctl,
15793 .name = "CLI_ECHO",
15794 .fn = run_cli_echo,
15797 .name = "CLI_SPLICE",
15798 .fn = run_cli_splice,
15805 .name = "STREAMERROR",
15806 .fn = run_streamerror,
15809 .name = "NOTIFY-BENCH",
15810 .fn = run_notify_bench,
15813 .name = "NOTIFY-BENCH2",
15814 .fn = run_notify_bench2,
15817 .name = "NOTIFY-BENCH3",
15818 .fn = run_notify_bench3,
15821 .name = "BAD-NBT-SESSION",
15822 .fn = run_bad_nbt_session,
15825 .name = "IGN-BAD-NEGPROT",
15826 .fn = run_ign_bad_negprot,
15829 .name = "SMB-ANY-CONNECT",
15830 .fn = run_smb_any_connect,
15833 .name = "NOTIFY-ONLINE",
15834 .fn = run_notify_online,
15837 .name = "SMB2-BASIC",
15838 .fn = run_smb2_basic,
15841 .name = "SMB2-NEGPROT",
15842 .fn = run_smb2_negprot,
15845 .name = "SMB2-ANONYMOUS",
15846 .fn = run_smb2_anonymous,
15849 .name = "SMB2-SESSION-RECONNECT",
15850 .fn = run_smb2_session_reconnect,
15853 .name = "SMB2-TCON-DEPENDENCE",
15854 .fn = run_smb2_tcon_dependence,
15857 .name = "SMB2-MULTI-CHANNEL",
15858 .fn = run_smb2_multi_channel,
15861 .name = "SMB2-SESSION-REAUTH",
15862 .fn = run_smb2_session_reauth,
15865 .name = "SMB2-FTRUNCATE",
15866 .fn = run_smb2_ftruncate,
15869 .name = "SMB2-DIR-FSYNC",
15870 .fn = run_smb2_dir_fsync,
15873 .name = "SMB2-PATH-SLASH",
15874 .fn = run_smb2_path_slash,
15877 .name = "SMB1-SYSTEM-SECURITY",
15878 .fn = run_smb1_system_security,
15881 .name = "SMB2-SACL",
15882 .fn = run_smb2_sacl,
15885 .name = "SMB2-QUOTA1",
15886 .fn = run_smb2_quota1,
15889 .name = "SMB2-INVALID-PIPENAME",
15890 .fn = run_smb2_invalid_pipename,
15893 .name = "SMB2-STREAM-ACL",
15894 .fn = run_smb2_stream_acl,
15897 .name = "SMB2-LIST-DIR-ASYNC",
15898 .fn = run_list_dir_async_test,
15901 .name = "SMB2-DEL-ON-CLOSE-NONEMPTY",
15902 .fn = run_delete_on_close_non_empty,
15905 .name = "SMB2-DEL-ON-CLOSE-NONWRITE-DELETE-YES",
15906 .fn = run_delete_on_close_nonwrite_delete_yes_test,
15909 .name = "SMB2-DEL-ON-CLOSE-NONWRITE-DELETE-NO",
15910 .fn = run_delete_on_close_nonwrite_delete_no_test,
15913 .name = "SMB2-DFS-PATHS",
15914 .fn = run_smb2_dfs_paths,
15917 .name = "SMB2-NON-DFS-SHARE",
15918 .fn = run_smb2_non_dfs_share,
15921 .name = "SMB2-DFS-SHARE-NON-DFS-PATH",
15922 .fn = run_smb2_dfs_share_non_dfs_path,
15925 .name = "SMB2-DFS-FILENAME-LEADING-BACKSLASH",
15926 .fn = run_smb2_dfs_filename_leading_backslash,
15929 .name = "SMB2-PIPE-READ-ASYNC-DISCONNECT",
15930 .fn = run_smb2_pipe_read_async_disconnect,
15933 .name = "SMB1-TRUNCATED-SESSSETUP",
15934 .fn = run_smb1_truncated_sesssetup,
15937 .name = "SMB1-NEGOTIATE-EXIT",
15938 .fn = run_smb1_negotiate_exit,
15941 .name = "SMB1-NEGOTIATE-TCON",
15942 .fn = run_smb1_negotiate_tcon,
15945 .name = "SMB1-DFS-PATHS",
15946 .fn = run_smb1_dfs_paths,
15949 .name = "SMB1-DFS-SEARCH-PATHS",
15950 .fn = run_smb1_dfs_search_paths,
15953 .name = "SMB1-DFS-OPERATIONS",
15954 .fn = run_smb1_dfs_operations,
15957 .name = "SMB1-DFS-BADPATH",
15958 .fn = run_smb1_dfs_check_badpath,
15961 .name = "CLEANUP1",
15962 .fn = run_cleanup1,
15965 .name = "CLEANUP2",
15966 .fn = run_cleanup2,
15969 .name = "CLEANUP4",
15970 .fn = run_cleanup4,
15973 .name = "OPLOCK-CANCEL",
15974 .fn = run_oplock_cancel,
15981 .name = "LOCAL-SUBSTITUTE",
15982 .fn = run_local_substitute,
15985 .name = "LOCAL-GENCACHE",
15986 .fn = run_local_gencache,
15989 .name = "LOCAL-DBWRAP-WATCH1",
15990 .fn = run_dbwrap_watch1,
15993 .name = "LOCAL-DBWRAP-WATCH2",
15994 .fn = run_dbwrap_watch2,
15997 .name = "LOCAL-DBWRAP-WATCH3",
15998 .fn = run_dbwrap_watch3,
16001 .name = "LOCAL-DBWRAP-WATCH4",
16002 .fn = run_dbwrap_watch4,
16005 .name = "LOCAL-DBWRAP-DO-LOCKED1",
16006 .fn = run_dbwrap_do_locked1,
16009 .name = "LOCAL-MESSAGING-READ1",
16010 .fn = run_messaging_read1,
16013 .name = "LOCAL-MESSAGING-READ2",
16014 .fn = run_messaging_read2,
16017 .name = "LOCAL-MESSAGING-READ3",
16018 .fn = run_messaging_read3,
16021 .name = "LOCAL-MESSAGING-READ4",
16022 .fn = run_messaging_read4,
16025 .name = "LOCAL-MESSAGING-FDPASS1",
16026 .fn = run_messaging_fdpass1,
16029 .name = "LOCAL-MESSAGING-FDPASS2",
16030 .fn = run_messaging_fdpass2,
16033 .name = "LOCAL-MESSAGING-FDPASS2a",
16034 .fn = run_messaging_fdpass2a,
16037 .name = "LOCAL-MESSAGING-FDPASS2b",
16038 .fn = run_messaging_fdpass2b,
16041 .name = "LOCAL-MESSAGING-SEND-ALL",
16042 .fn = run_messaging_send_all,
16045 .name = "LOCAL-BASE64",
16046 .fn = run_local_base64,
16049 .name = "LOCAL-RBTREE",
16050 .fn = run_local_rbtree,
16053 .name = "LOCAL-MEMCACHE",
16054 .fn = run_local_memcache,
16057 .name = "LOCAL-STREAM-NAME",
16058 .fn = run_local_stream_name,
16061 .name = "LOCAL-STR-MATCH-MSWILD",
16062 .fn = run_str_match_mswild,
16065 .name = "LOCAL-STR-MATCH-REGEX-SUB1",
16066 .fn = run_str_match_regex_sub1,
16069 .name = "WBCLIENT-MULTI-PING",
16070 .fn = run_wbclient_multi_ping,
16073 .name = "LOCAL-string_to_sid",
16074 .fn = run_local_string_to_sid,
16077 .name = "LOCAL-sid_to_string",
16078 .fn = run_local_sid_to_string,
16081 .name = "LOCAL-binary_to_sid",
16082 .fn = run_local_binary_to_sid,
16085 .name = "LOCAL-DBTRANS",
16086 .fn = run_local_dbtrans,
16089 .name = "LOCAL-TEVENT-POLL",
16090 .fn = run_local_tevent_poll,
16093 .name = "LOCAL-CONVERT-STRING",
16094 .fn = run_local_convert_string,
16097 .name = "LOCAL-CONV-AUTH-INFO",
16098 .fn = run_local_conv_auth_info,
16101 .name = "LOCAL-hex_encode_buf",
16102 .fn = run_local_hex_encode_buf,
16105 .name = "LOCAL-IDMAP-TDB-COMMON",
16106 .fn = run_idmap_tdb_common_test,
16109 .name = "LOCAL-remove_duplicate_addrs2",
16110 .fn = run_local_remove_duplicate_addrs2,
16113 .name = "local-tdb-opener",
16114 .fn = run_local_tdb_opener,
16117 .name = "local-tdb-writer",
16118 .fn = run_local_tdb_writer,
16121 .name = "LOCAL-DBWRAP-CTDB1",
16122 .fn = run_local_dbwrap_ctdb1,
16125 .name = "LOCAL-BENCH-PTHREADPOOL",
16126 .fn = run_bench_pthreadpool,
16129 .name = "LOCAL-PTHREADPOOL-TEVENT",
16130 .fn = run_pthreadpool_tevent,
16133 .name = "LOCAL-G-LOCK1",
16137 .name = "LOCAL-G-LOCK2",
16141 .name = "LOCAL-G-LOCK3",
16145 .name = "LOCAL-G-LOCK4",
16149 .name = "LOCAL-G-LOCK4A",
16150 .fn = run_g_lock4a,
16153 .name = "LOCAL-G-LOCK5",
16157 .name = "LOCAL-G-LOCK6",
16161 .name = "LOCAL-G-LOCK7",
16165 .name = "LOCAL-G-LOCK8",
16169 .name = "LOCAL-G-LOCK-PING-PONG",
16170 .fn = run_g_lock_ping_pong,
16173 .name = "LOCAL-CANONICALIZE-PATH",
16174 .fn = run_local_canonicalize_path,
16177 .name = "LOCAL-NAMEMAP-CACHE1",
16178 .fn = run_local_namemap_cache1,
16181 .name = "LOCAL-IDMAP-CACHE1",
16182 .fn = run_local_idmap_cache1,
16185 .name = "qpathinfo-bufsize",
16186 .fn = run_qpathinfo_bufsize,
16189 .name = "hide-new-files-timeout",
16190 .fn = run_hidenewfiles,
16193 .name = "hide-new-files-timeout-showdirs",
16194 .fn = run_hidenewfiles_showdirs,
16196 #ifdef CLUSTER_SUPPORT
16198 .name = "ctdbd-conn1",
16199 .fn = run_ctdbd_conn1,
16203 .name = "readdir-timestamp",
16204 .fn = run_readdir_timestamp,
16207 .name = "rpc-scale",
16208 .fn = run_rpc_scale,
16211 .name = "LOCAL-TDB-VALIDATE",
16212 .fn = run_tdb_validate,
16219 /****************************************************************************
16220 run a specified test or "ALL"
16221 ****************************************************************************/
16222 static bool run_test(const char *name)
16225 bool result = True;
16226 bool found = False;
16229 if (strequal(name,"ALL")) {
16230 for (i=0;torture_ops[i].name;i++) {
16231 run_test(torture_ops[i].name);
16236 for (i=0;torture_ops[i].name;i++) {
16237 fstr_sprintf(randomfname, "\\XX%x",
16238 (unsigned)random());
16240 if (strequal(name, torture_ops[i].name)) {
16242 printf("Running %s\n", name);
16243 if (torture_ops[i].flags & FLAG_MULTIPROC) {
16244 t = create_procs(torture_ops[i].fn, &result);
16247 printf("TEST %s FAILED!\n", name);
16250 struct timeval start;
16251 start = timeval_current();
16252 if (!torture_ops[i].fn(0)) {
16254 printf("TEST %s FAILED!\n", name);
16256 t = timeval_elapsed(&start);
16258 printf("%s took %g secs\n\n", name, t);
16263 printf("Did not find a test named %s\n", name);
16271 static void usage(void)
16275 printf("WARNING samba4 test suite is much more complete nowadays.\n");
16276 printf("Please use samba4 torture.\n\n");
16278 printf("Usage: smbtorture //server/share <options> TEST1 TEST2 ...\n");
16280 printf("\t-d debuglevel\n");
16281 printf("\t-U user%%pass\n");
16282 printf("\t-k use kerberos\n");
16283 printf("\t-N numprocs\n");
16284 printf("\t-n my_netbios_name\n");
16285 printf("\t-W workgroup\n");
16286 printf("\t-o num_operations\n");
16287 printf("\t-O socket_options\n");
16288 printf("\t-m maximum protocol\n");
16289 printf("\t-L use oplocks\n");
16290 printf("\t-c CLIENT.TXT specify client load file for NBENCH\n");
16291 printf("\t-A showall\n");
16292 printf("\t-p port\n");
16293 printf("\t-s seed\n");
16294 printf("\t-b unclist_filename specify multiple shares for multiple connections\n");
16295 printf("\t-f filename filename to test\n");
16296 printf("\t-e encrypt\n");
16299 printf("tests are:");
16300 for (i=0;torture_ops[i].name;i++) {
16301 printf(" %s", torture_ops[i].name);
16305 printf("default test is ALL\n");
16310 /****************************************************************************
16312 ****************************************************************************/
16313 int main(int argc,char *argv[])
16319 bool correct = True;
16320 TALLOC_CTX *frame = talloc_stackframe();
16321 int seed = time(NULL);
16322 struct loadparm_context *lp_ctx = NULL;
16324 #ifdef HAVE_SETBUFFER
16325 setbuffer(stdout, NULL, 0);
16328 setup_logging("smbtorture", DEBUG_STDOUT);
16333 lp_ctx = loadparm_init_s3(frame, loadparm_s3_helpers());
16334 if (lp_ctx == NULL) {
16336 "Failed to initialise the global parameter structure.\n");
16340 if (is_default_dyn_CONFIGFILE()) {
16341 if(getenv("SMB_CONF_PATH")) {
16342 set_dyn_CONFIGFILE(getenv("SMB_CONF_PATH"));
16345 lp_load_global(get_dyn_CONFIGFILE());
16352 for(p = argv[1]; *p; p++)
16356 if (strncmp(argv[1], "//", 2)) {
16360 fstrcpy(host, &argv[1][2]);
16361 p = strchr_m(&host[2],'/');
16366 fstrcpy(share, p+1);
16368 fstrcpy(myname, get_myname(talloc_tos()));
16370 fprintf(stderr, "Failed to get my hostname.\n");
16374 if (*username == 0 && getenv("LOGNAME")) {
16375 fstrcpy(username,getenv("LOGNAME"));
16381 fstrcpy(workgroup, lp_workgroup());
16383 while ((opt = getopt(argc, argv, "p:hW:U:n:N:O:o:m:Ll:d:Aec:ks:b:B:f:"))
16387 port_to_use = atoi(optarg);
16390 seed = atoi(optarg);
16393 fstrcpy(workgroup,optarg);
16396 lpcfg_set_cmdline(lp_ctx, "client max protocol", optarg);
16399 torture_nprocs = atoi(optarg);
16402 torture_numops = atoi(optarg);
16405 lpcfg_set_cmdline(lp_ctx, "log level", optarg);
16411 use_oplocks = True;
16414 local_path = optarg;
16417 torture_showall = True;
16420 fstrcpy(myname, optarg);
16423 client_txt = optarg;
16430 use_kerberos = True;
16432 d_printf("No kerberos support compiled in\n");
16438 fstrcpy(username,optarg);
16439 p = strchr_m(username,'%');
16442 fstrcpy(password, p+1);
16447 fstrcpy(multishare_conn_fname, optarg);
16448 use_multishare_conn = True;
16451 torture_blocksize = atoi(optarg);
16454 test_filename = SMB_STRDUP(optarg);
16457 printf("Unknown option %c (%d)\n", (char)opt, opt);
16462 d_printf("using seed %d\n", seed);
16466 if(use_kerberos && !gotuser) gotpass = True;
16469 char pwd[256] = {0};
16472 rc = samba_getpass("Password:", pwd, sizeof(pwd), false, false);
16474 fstrcpy(password, pwd);
16479 printf("host=%s share=%s user=%s myname=%s\n",
16480 host, share, username, myname);
16482 torture_creds = cli_session_creds_init(frame,
16488 false, /* fallback_after_kerberos */
16489 false, /* use_ccache */
16490 false); /* password_is_nt_hash */
16491 if (torture_creds == NULL) {
16492 d_printf("cli_session_creds_init() failed.\n");
16496 if (argc == optind) {
16497 correct = run_test("ALL");
16499 for (i=optind;i<argc;i++) {
16500 if (!run_test(argv[i])) {
16506 TALLOC_FREE(frame);