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 "tldap_tls_connect.h"
31 #include "../librpc/gen_ndr/svcctl.h"
32 #include "../lib/util/memcache.h"
33 #include "nsswitch/winbind_client.h"
34 #include "dbwrap/dbwrap.h"
35 #include "dbwrap/dbwrap_open.h"
36 #include "dbwrap/dbwrap_rbt.h"
37 #include "async_smb.h"
38 #include "libsmb/libsmb.h"
39 #include "libsmb/clirap.h"
41 #include "libsmb/nmblib.h"
42 #include "../lib/util/tevent_ntstatus.h"
44 #include "../libcli/smb/read_smb.h"
45 #include "../libcli/smb/smbXcli_base.h"
46 #include "lib/util/sys_rw_data.h"
47 #include "lib/util/base64.h"
48 #include "lib/util/time.h"
49 #include "lib/gencache.h"
50 #include "lib/util/sys_rw.h"
51 #include "lib/util/asn1.h"
52 #include "lib/util/util_file.h"
53 #include "lib/param/param.h"
54 #include "auth/gensec/gensec.h"
55 #include "lib/util/string_wrappers.h"
56 #include "source3/lib/substitute.h"
59 #include <gnutls/gnutls.h>
60 #include <gnutls/crypto.h>
65 fstring host, workgroup, share, password, username, myname;
66 struct cli_credentials *torture_creds;
67 static const char *sockops="TCP_NODELAY";
69 static int port_to_use=0;
70 int torture_numops=100;
71 int torture_blocksize=1024*1024;
72 static int procnum; /* records process count number when forking */
73 static struct cli_state *current_cli;
74 static fstring randomfname;
75 static bool use_oplocks;
76 static bool use_level_II_oplocks;
77 static const char *client_txt = "client_oplocks.txt";
78 static bool disable_spnego;
79 static bool use_kerberos;
80 static bool force_dos_errors;
81 static fstring multishare_conn_fname;
82 static bool use_multishare_conn = False;
83 static bool do_encrypt;
84 static const char *local_path = NULL;
85 static enum smb_signing_setting signing_state = SMB_SIGNING_DEFAULT;
88 bool torture_showall = False;
90 static double create_procs(bool (*fn)(int), bool *result);
92 /********************************************************************
93 Ensure a connection is encrypted.
94 ********************************************************************/
96 static bool force_cli_encryption(struct cli_state *c,
97 const char *sharename)
99 uint16_t major, minor;
100 uint32_t caplow, caphigh;
103 if (!SERVER_HAS_UNIX_CIFS(c)) {
104 d_printf("Encryption required and "
105 "server that doesn't support "
106 "UNIX extensions - failing connect\n");
110 status = cli_unix_extensions_version(c, &major, &minor, &caplow,
112 if (!NT_STATUS_IS_OK(status)) {
113 d_printf("Encryption required and "
114 "can't get UNIX CIFS extensions "
115 "version from server: %s\n", nt_errstr(status));
119 if (!(caplow & CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP)) {
120 d_printf("Encryption required and "
121 "share %s doesn't support "
122 "encryption.\n", sharename);
126 status = cli_smb1_setup_encryption(c, torture_creds);
127 if (!NT_STATUS_IS_OK(status)) {
128 d_printf("Encryption required and "
129 "setup failed with error %s.\n",
138 static struct cli_state *open_nbt_connection(void)
144 if (disable_spnego) {
145 flags |= CLI_FULL_CONNECTION_DONT_SPNEGO;
149 flags |= CLI_FULL_CONNECTION_OPLOCKS;
152 if (use_level_II_oplocks) {
153 flags |= CLI_FULL_CONNECTION_LEVEL_II_OPLOCKS;
156 if (force_dos_errors) {
157 flags |= CLI_FULL_CONNECTION_FORCE_DOS_ERRORS;
160 status = cli_connect_nb(host, NULL, port_to_use, 0x20, myname,
161 signing_state, flags, &c);
162 if (!NT_STATUS_IS_OK(status)) {
163 printf("Failed to connect with %s. Error %s\n", host, nt_errstr(status) );
167 cli_set_timeout(c, 120000); /* set a really long timeout (2 minutes) */
172 /****************************************************************************
173 Send a corrupt session request. See rfc1002.txt 4.3 and 4.3.2.
174 ****************************************************************************/
176 static bool cli_bad_session_request(int fd,
177 struct nmb_name *calling, struct nmb_name *called)
186 uint8_t message_type;
188 struct tevent_context *ev;
189 struct tevent_req *req;
191 frame = talloc_stackframe();
193 iov[0].iov_base = len_buf;
194 iov[0].iov_len = sizeof(len_buf);
196 /* put in the destination name */
198 iov[1].iov_base = name_mangle(talloc_tos(), called->name,
200 if (iov[1].iov_base == NULL) {
203 iov[1].iov_len = name_len((unsigned char *)iov[1].iov_base,
204 talloc_get_size(iov[1].iov_base));
208 iov[2].iov_base = name_mangle(talloc_tos(), calling->name,
210 if (iov[2].iov_base == NULL) {
213 iov[2].iov_len = name_len((unsigned char *)iov[2].iov_base,
214 talloc_get_size(iov[2].iov_base));
216 /* Deliberately corrupt the name len (first byte) */
217 *((uint8_t *)iov[2].iov_base) = 100;
219 /* send a session request (RFC 1002) */
220 /* setup the packet length
221 * Remove four bytes from the length count, since the length
222 * field in the NBT Session Service header counts the number
223 * of bytes which follow. The cli_send_smb() function knows
224 * about this and accounts for those four bytes.
228 _smb_setlen(len_buf, iov[1].iov_len + iov[2].iov_len);
229 SCVAL(len_buf,0,0x81);
231 len = write_data_iov(fd, iov, 3);
236 ev = samba_tevent_context_init(frame);
240 req = read_smb_send(frame, ev, fd);
244 if (!tevent_req_poll(req, ev)) {
247 len = read_smb_recv(req, talloc_tos(), &inbuf, &err);
254 message_type = CVAL(inbuf, 0);
255 if (message_type != 0x83) {
256 d_fprintf(stderr, "Expected msg type 0x83, got 0x%2.2x\n",
261 if (smb_len(inbuf) != 1) {
262 d_fprintf(stderr, "Expected smb_len 1, got %d\n",
263 (int)smb_len(inbuf));
267 error = CVAL(inbuf, 4);
269 d_fprintf(stderr, "Expected error 0x82, got %d\n",
280 /* Insert a NULL at the first separator of the given path and return a pointer
281 * to the remainder of the string.
284 terminate_path_at_separator(char * path)
292 if ((p = strchr_m(path, '/'))) {
297 if ((p = strchr_m(path, '\\'))) {
307 parse a //server/share type UNC name
309 bool smbcli_parse_unc(const char *unc_name, TALLOC_CTX *mem_ctx,
310 char **hostname, char **sharename)
314 *hostname = *sharename = NULL;
316 if (strncmp(unc_name, "\\\\", 2) &&
317 strncmp(unc_name, "//", 2)) {
321 *hostname = talloc_strdup(mem_ctx, &unc_name[2]);
322 p = terminate_path_at_separator(*hostname);
325 *sharename = talloc_strdup(mem_ctx, p);
326 terminate_path_at_separator(*sharename);
329 if (*hostname && *sharename) {
333 TALLOC_FREE(*hostname);
334 TALLOC_FREE(*sharename);
338 static bool torture_open_connection_share(struct cli_state **c,
339 const char *hostname,
340 const char *sharename,
345 status = cli_full_connection_creds(c,
354 if (!NT_STATUS_IS_OK(status)) {
355 printf("failed to open share connection: //%s/%s port:%d - %s\n",
356 hostname, sharename, port_to_use, nt_errstr(status));
360 cli_set_timeout(*c, 120000); /* set a really long timeout (2 minutes) */
363 return force_cli_encryption(*c,
369 bool torture_open_connection_flags(struct cli_state **c, int conn_index, int flags)
371 char **unc_list = NULL;
372 int num_unc_names = 0;
375 if (use_multishare_conn==True) {
377 unc_list = file_lines_load(multishare_conn_fname, &num_unc_names, 0, NULL);
378 if (!unc_list || num_unc_names <= 0) {
379 printf("Failed to load unc names list from '%s'\n", multishare_conn_fname);
383 if (!smbcli_parse_unc(unc_list[conn_index % num_unc_names],
385 printf("Failed to parse UNC name %s\n",
386 unc_list[conn_index % num_unc_names]);
387 TALLOC_FREE(unc_list);
391 result = torture_open_connection_share(c, h, s, flags);
393 /* h, s were copied earlier */
394 TALLOC_FREE(unc_list);
398 return torture_open_connection_share(c, host, share, flags);
401 bool torture_open_connection(struct cli_state **c, int conn_index)
403 int flags = CLI_FULL_CONNECTION_FORCE_SMB1;
406 flags |= CLI_FULL_CONNECTION_OPLOCKS;
408 if (use_level_II_oplocks) {
409 flags |= CLI_FULL_CONNECTION_LEVEL_II_OPLOCKS;
412 return torture_open_connection_flags(c, conn_index, flags);
415 bool torture_init_connection(struct cli_state **pcli)
417 struct cli_state *cli;
419 cli = open_nbt_connection();
428 bool torture_cli_session_setup2(struct cli_state *cli, uint16_t *new_vuid)
430 uint16_t old_vuid = cli_state_get_uid(cli);
434 cli_state_set_uid(cli, 0);
435 status = cli_session_setup_creds(cli, torture_creds);
436 ret = NT_STATUS_IS_OK(status);
437 *new_vuid = cli_state_get_uid(cli);
438 cli_state_set_uid(cli, old_vuid);
443 bool torture_close_connection(struct cli_state *c)
448 status = cli_tdis(c);
449 if (!NT_STATUS_IS_OK(status)) {
450 printf("tdis failed (%s)\n", nt_errstr(status));
459 void torture_conn_set_sockopt(struct cli_state *cli)
461 smbXcli_conn_set_sockopt(cli->conn, sockops);
464 static NTSTATUS torture_delete_fn(struct file_info *finfo,
469 char *filename = NULL;
470 char *dirname = NULL;
472 TALLOC_CTX *frame = talloc_stackframe();
473 struct cli_state *cli = (struct cli_state *)state;
475 if (ISDOT(finfo->name) || ISDOTDOT(finfo->name)) {
480 dirname = talloc_strdup(frame, pattern);
481 if (dirname == NULL) {
483 return NT_STATUS_NO_MEMORY;
485 p = strrchr_m(dirname, '\\');
487 /* Remove the terminating '\' */
490 if (dirname[0] != '\0') {
491 filename = talloc_asprintf(frame,
496 filename = talloc_asprintf(frame,
500 if (filename == NULL) {
502 return NT_STATUS_NO_MEMORY;
504 if (finfo->attr & FILE_ATTRIBUTE_DIRECTORY) {
505 char *subdirname = talloc_asprintf(frame,
508 if (subdirname == NULL) {
510 return NT_STATUS_NO_MEMORY;
512 status = cli_list(cli,
514 FILE_ATTRIBUTE_DIRECTORY |
515 FILE_ATTRIBUTE_HIDDEN |
516 FILE_ATTRIBUTE_SYSTEM,
519 if (!NT_STATUS_IS_OK(status)) {
520 printf("torture_delete_fn: cli_list "
521 "of %s failed (%s)\n",
527 status = cli_rmdir(cli, filename);
529 status = cli_unlink(cli,
531 FILE_ATTRIBUTE_SYSTEM |
532 FILE_ATTRIBUTE_HIDDEN);
534 if (!NT_STATUS_IS_OK(status)) {
535 if (finfo->attr & FILE_ATTRIBUTE_DIRECTORY) {
536 printf("torture_delete_fn: cli_rmdir"
537 " of %s failed (%s)\n",
541 printf("torture_delete_fn: cli_unlink"
542 " of %s failed (%s)\n",
551 void torture_deltree(struct cli_state *cli, const char *dname)
556 /* It might be a file */
557 (void)cli_unlink(cli,
559 FILE_ATTRIBUTE_SYSTEM |
560 FILE_ATTRIBUTE_HIDDEN);
562 mask = talloc_asprintf(cli,
566 printf("torture_deltree: talloc_asprintf failed\n");
570 status = cli_list(cli,
572 FILE_ATTRIBUTE_DIRECTORY |
573 FILE_ATTRIBUTE_HIDDEN|
574 FILE_ATTRIBUTE_SYSTEM,
577 if (!NT_STATUS_IS_OK(status)) {
578 printf("torture_deltree: cli_list of %s failed (%s)\n",
583 status = cli_rmdir(cli, dname);
584 if (!NT_STATUS_IS_OK(status)) {
585 printf("torture_deltree: cli_rmdir of %s failed (%s)\n",
591 /* check if the server produced the expected dos or nt error code */
592 static bool check_both_error(int line, NTSTATUS status,
593 uint8_t eclass, uint32_t ecode, NTSTATUS nterr)
595 if (NT_STATUS_IS_DOS(status)) {
599 /* Check DOS error */
600 cclass = NT_STATUS_DOS_CLASS(status);
601 num = NT_STATUS_DOS_CODE(status);
603 if (eclass != cclass || ecode != num) {
604 printf("unexpected error code class=%d code=%d\n",
605 (int)cclass, (int)num);
606 printf(" expected %d/%d %s (line=%d)\n",
607 (int)eclass, (int)ecode, nt_errstr(nterr), line);
612 if (!NT_STATUS_EQUAL(nterr, status)) {
613 printf("unexpected error code %s\n",
615 printf(" expected %s (line=%d)\n",
616 nt_errstr(nterr), line);
625 /* check if the server produced the expected error code */
626 static bool check_error(int line, NTSTATUS status,
627 uint8_t eclass, uint32_t ecode, NTSTATUS nterr)
629 if (NT_STATUS_IS_DOS(status)) {
633 /* Check DOS error */
635 cclass = NT_STATUS_DOS_CLASS(status);
636 num = NT_STATUS_DOS_CODE(status);
638 if (eclass != cclass || ecode != num) {
639 printf("unexpected error code class=%d code=%d\n",
640 (int)cclass, (int)num);
641 printf(" expected %d/%d %s (line=%d)\n",
642 (int)eclass, (int)ecode, nt_errstr(nterr),
650 if (NT_STATUS_V(nterr) != NT_STATUS_V(status)) {
651 printf("unexpected error code %s\n",
653 printf(" expected %s (line=%d)\n", nt_errstr(nterr),
662 NTSTATUS cli_qpathinfo1(struct cli_state *cli,
670 int timezone = smb1cli_conn_server_time_zone(cli->conn);
671 time_t (*date_fn)(const void *buf, int serverzone) = NULL;
672 uint8_t *rdata = NULL;
676 status = cli_qpathinfo(talloc_tos(),
684 if (!NT_STATUS_IS_OK(status)) {
688 date_fn = make_unix_date;
690 date_fn = make_unix_date2;
694 *change_time = date_fn(rdata + 0, timezone);
697 *access_time = date_fn(rdata + 4, timezone);
700 *write_time = date_fn(rdata + 8, timezone);
703 *size = PULL_LE_U32(rdata, 12);
706 *pattr = PULL_LE_U16(rdata, l1_attrFile);
711 static bool wait_lock(struct cli_state *c, int fnum, uint32_t offset, uint32_t len)
715 status = cli_lock32(c, fnum, offset, len, -1, WRITE_LOCK);
717 while (!NT_STATUS_IS_OK(status)) {
718 if (!check_both_error(__LINE__, status, ERRDOS,
719 ERRlock, NT_STATUS_LOCK_NOT_GRANTED)) {
723 status = cli_lock32(c, fnum, offset, len, -1, WRITE_LOCK);
730 static bool rw_torture(struct cli_state *c)
732 const char *lockfname = "\\torture.lck";
736 pid_t pid2, pid = getpid();
743 memset(buf, '\0', sizeof(buf));
745 status = cli_openx(c, lockfname, O_RDWR | O_CREAT | O_EXCL,
747 if (!NT_STATUS_IS_OK(status)) {
748 status = cli_openx(c, lockfname, O_RDWR, DENY_NONE, &fnum2);
750 if (!NT_STATUS_IS_OK(status)) {
751 printf("open of %s failed (%s)\n",
752 lockfname, nt_errstr(status));
756 for (i=0;i<torture_numops;i++) {
757 unsigned n = (unsigned)sys_random()%10;
760 printf("%d\r", i); fflush(stdout);
762 slprintf(fname, sizeof(fstring) - 1, "\\torture.%u", n);
764 if (!wait_lock(c, fnum2, n*sizeof(int), sizeof(int))) {
768 status = cli_openx(c, fname, O_RDWR | O_CREAT | O_TRUNC,
770 if (!NT_STATUS_IS_OK(status)) {
771 printf("open failed (%s)\n", nt_errstr(status));
776 status = cli_writeall(c, fnum, 0, (uint8_t *)&pid, 0,
778 if (!NT_STATUS_IS_OK(status)) {
779 printf("write failed (%s)\n", nt_errstr(status));
784 status = cli_writeall(c, fnum, 0, (uint8_t *)buf,
785 sizeof(pid)+(j*sizeof(buf)),
787 if (!NT_STATUS_IS_OK(status)) {
788 printf("write failed (%s)\n",
796 status = cli_read(c, fnum, (char *)&pid2, 0, sizeof(pid),
798 if (!NT_STATUS_IS_OK(status)) {
799 printf("read failed (%s)\n", nt_errstr(status));
801 } else if (nread != sizeof(pid)) {
802 printf("read/write compare failed: "
803 "recv %ld req %ld\n", (unsigned long)nread,
804 (unsigned long)sizeof(pid));
809 printf("data corruption!\n");
813 status = cli_close(c, fnum);
814 if (!NT_STATUS_IS_OK(status)) {
815 printf("close failed (%s)\n", nt_errstr(status));
819 status = cli_unlink(c, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
820 if (!NT_STATUS_IS_OK(status)) {
821 printf("unlink failed (%s)\n", nt_errstr(status));
825 status = cli_unlock(c, fnum2, n*sizeof(int), sizeof(int));
826 if (!NT_STATUS_IS_OK(status)) {
827 printf("unlock failed (%s)\n", nt_errstr(status));
833 cli_unlink(c, lockfname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
840 static bool run_torture(int dummy)
842 struct cli_state *cli;
847 smbXcli_conn_set_sockopt(cli->conn, sockops);
849 ret = rw_torture(cli);
851 if (!torture_close_connection(cli)) {
858 static bool rw_torture3(struct cli_state *c, char *lockfname)
860 uint16_t fnum = (uint16_t)-1;
865 unsigned countprev = 0;
868 NTSTATUS status = NT_STATUS_OK;
871 for (i = 0; i < sizeof(buf); i += sizeof(uint32_t))
873 SIVAL(buf, i, sys_random());
880 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
881 if (!NT_STATUS_IS_OK(status)) {
882 printf("unlink failed (%s) (normal, this file should "
883 "not exist)\n", nt_errstr(status));
886 status = cli_openx(c, lockfname, O_RDWR | O_CREAT | O_EXCL,
888 if (!NT_STATUS_IS_OK(status)) {
889 printf("first open read/write of %s failed (%s)\n",
890 lockfname, nt_errstr(status));
896 for (i = 0; i < 500 && fnum == (uint16_t)-1; i++)
898 status = cli_openx(c, lockfname, O_RDONLY,
900 if (NT_STATUS_IS_OK(status)) {
905 if (!NT_STATUS_IS_OK(status)) {
906 printf("second open read-only of %s failed (%s)\n",
907 lockfname, nt_errstr(status));
913 for (count = 0; count < sizeof(buf); count += sent)
915 if (count >= countprev) {
916 printf("%d %8d\r", i, count);
919 countprev += (sizeof(buf) / 20);
924 sent = ((unsigned)sys_random()%(20))+ 1;
925 if (sent > sizeof(buf) - count)
927 sent = sizeof(buf) - count;
930 status = cli_writeall(c, fnum, 0, (uint8_t *)buf+count,
932 if (!NT_STATUS_IS_OK(status)) {
933 printf("write failed (%s)\n",
940 status = cli_read(c, fnum, buf_rd+count, count,
941 sizeof(buf)-count, &sent);
942 if(!NT_STATUS_IS_OK(status)) {
943 printf("read failed offset:%d size:%ld (%s)\n",
944 count, (unsigned long)sizeof(buf)-count,
948 } else if (sent > 0) {
949 if (memcmp(buf_rd+count, buf+count, sent) != 0)
951 printf("read/write compare failed\n");
952 printf("offset: %d req %ld recvd %ld\n", count, (unsigned long)sizeof(buf)-count, (unsigned long)sent);
961 status = cli_close(c, fnum);
962 if (!NT_STATUS_IS_OK(status)) {
963 printf("close failed (%s)\n", nt_errstr(status));
970 static bool rw_torture2(struct cli_state *c1, struct cli_state *c2)
972 const char *lockfname = "\\torture2.lck";
982 status = cli_unlink(c1, lockfname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
983 if (!NT_STATUS_IS_OK(status)) {
984 printf("unlink failed (%s) (normal, this file should not exist)\n", nt_errstr(status));
987 status = cli_openx(c1, lockfname, O_RDWR | O_CREAT | O_EXCL,
989 if (!NT_STATUS_IS_OK(status)) {
990 printf("first open read/write of %s failed (%s)\n",
991 lockfname, nt_errstr(status));
995 status = cli_openx(c2, lockfname, O_RDONLY, DENY_NONE, &fnum2);
996 if (!NT_STATUS_IS_OK(status)) {
997 printf("second open read-only of %s failed (%s)\n",
998 lockfname, nt_errstr(status));
999 cli_close(c1, fnum1);
1003 for (i = 0; i < torture_numops; i++)
1005 size_t buf_size = ((unsigned)sys_random()%(sizeof(buf)-1))+ 1;
1007 printf("%d\r", i); fflush(stdout);
1010 generate_random_buffer((unsigned char *)buf, buf_size);
1012 status = cli_writeall(c1, fnum1, 0, (uint8_t *)buf, 0,
1014 if (!NT_STATUS_IS_OK(status)) {
1015 printf("write failed (%s)\n", nt_errstr(status));
1020 status = cli_read(c2, fnum2, buf_rd, 0, buf_size, &bytes_read);
1021 if(!NT_STATUS_IS_OK(status)) {
1022 printf("read failed (%s)\n", nt_errstr(status));
1025 } else if (bytes_read != buf_size) {
1026 printf("read failed\n");
1027 printf("read %ld, expected %ld\n",
1028 (unsigned long)bytes_read,
1029 (unsigned long)buf_size);
1034 if (memcmp(buf_rd, buf, buf_size) != 0)
1036 printf("read/write compare failed\n");
1042 status = cli_close(c2, fnum2);
1043 if (!NT_STATUS_IS_OK(status)) {
1044 printf("close failed (%s)\n", nt_errstr(status));
1048 status = cli_close(c1, fnum1);
1049 if (!NT_STATUS_IS_OK(status)) {
1050 printf("close failed (%s)\n", nt_errstr(status));
1054 status = cli_unlink(c1, lockfname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1055 if (!NT_STATUS_IS_OK(status)) {
1056 printf("unlink failed (%s)\n", nt_errstr(status));
1063 static bool run_readwritetest(int dummy)
1065 struct cli_state *cli1, *cli2;
1066 bool test1, test2 = False;
1068 if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
1071 smbXcli_conn_set_sockopt(cli1->conn, sockops);
1072 smbXcli_conn_set_sockopt(cli2->conn, sockops);
1074 printf("starting readwritetest\n");
1076 test1 = rw_torture2(cli1, cli2);
1077 printf("Passed readwritetest v1: %s\n", BOOLSTR(test1));
1080 test2 = rw_torture2(cli1, cli1);
1081 printf("Passed readwritetest v2: %s\n", BOOLSTR(test2));
1084 if (!torture_close_connection(cli1)) {
1088 if (!torture_close_connection(cli2)) {
1092 return (test1 && test2);
1095 static bool run_readwritemulti(int dummy)
1097 struct cli_state *cli;
1102 smbXcli_conn_set_sockopt(cli->conn, sockops);
1104 printf("run_readwritemulti: fname %s\n", randomfname);
1105 test = rw_torture3(cli, randomfname);
1107 if (!torture_close_connection(cli)) {
1114 static bool run_readwritelarge_internal(void)
1116 static struct cli_state *cli1;
1118 const char *lockfname = "\\large.dat";
1121 bool correct = True;
1124 if (!torture_open_connection(&cli1, 0)) {
1127 smbXcli_conn_set_sockopt(cli1->conn, sockops);
1128 memset(buf,'\0',sizeof(buf));
1130 printf("starting readwritelarge_internal\n");
1132 cli_unlink(cli1, lockfname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1134 status = cli_openx(cli1, lockfname, O_RDWR | O_CREAT | O_EXCL,
1136 if (!NT_STATUS_IS_OK(status)) {
1137 printf("open read/write of %s failed (%s)\n", lockfname, nt_errstr(status));
1141 cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 0, sizeof(buf), NULL);
1143 status = cli_qfileinfo_basic(cli1, fnum1, NULL, &fsize, NULL, NULL,
1145 if (!NT_STATUS_IS_OK(status)) {
1146 printf("qfileinfo failed (%s)\n", nt_errstr(status));
1150 if (fsize == sizeof(buf))
1151 printf("readwritelarge_internal test 1 succeeded (size = %lx)\n",
1152 (unsigned long)fsize);
1154 printf("readwritelarge_internal test 1 failed (size = %lx)\n",
1155 (unsigned long)fsize);
1159 status = cli_close(cli1, fnum1);
1160 if (!NT_STATUS_IS_OK(status)) {
1161 printf("close failed (%s)\n", nt_errstr(status));
1165 status = cli_unlink(cli1, lockfname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1166 if (!NT_STATUS_IS_OK(status)) {
1167 printf("unlink failed (%s)\n", nt_errstr(status));
1171 status = cli_openx(cli1, lockfname, O_RDWR | O_CREAT | O_EXCL,
1173 if (!NT_STATUS_IS_OK(status)) {
1174 printf("open read/write of %s failed (%s)\n", lockfname, nt_errstr(status));
1178 cli_smbwrite(cli1, fnum1, buf, 0, sizeof(buf), NULL);
1180 status = cli_qfileinfo_basic(cli1, fnum1, NULL, &fsize, NULL, NULL,
1182 if (!NT_STATUS_IS_OK(status)) {
1183 printf("qfileinfo failed (%s)\n", nt_errstr(status));
1187 if (fsize == sizeof(buf))
1188 printf("readwritelarge_internal test 2 succeeded (size = %lx)\n",
1189 (unsigned long)fsize);
1191 printf("readwritelarge_internal test 2 failed (size = %lx)\n",
1192 (unsigned long)fsize);
1196 status = cli_close(cli1, fnum1);
1197 if (!NT_STATUS_IS_OK(status)) {
1198 printf("close failed (%s)\n", nt_errstr(status));
1202 if (!torture_close_connection(cli1)) {
1208 static bool run_readwritelarge(int dummy)
1210 return run_readwritelarge_internal();
1213 static bool run_readwritelarge_signtest(int dummy)
1216 signing_state = SMB_SIGNING_REQUIRED;
1217 ret = run_readwritelarge_internal();
1218 signing_state = SMB_SIGNING_DEFAULT;
1225 #define ival(s) strtol(s, NULL, 0)
1227 /* run a test that simulates an approximate netbench client load */
1228 static bool run_netbench(int client)
1230 struct cli_state *cli;
1235 const char *params[20];
1236 bool correct = True;
1242 smbXcli_conn_set_sockopt(cli->conn, sockops);
1246 slprintf(cname,sizeof(cname)-1, "client%d", client);
1248 f = fopen(client_txt, "r");
1255 while (fgets(line, sizeof(line)-1, f)) {
1259 line[strlen(line)-1] = 0;
1261 /* printf("[%d] %s\n", line_count, line); */
1263 all_string_sub(line,"client1", cname, sizeof(line));
1265 /* parse the command parameters */
1266 params[0] = strtok_r(line, " ", &saveptr);
1268 while (params[i]) params[++i] = strtok_r(NULL, " ", &saveptr);
1272 if (i < 2) continue;
1274 if (!strncmp(params[0],"SMB", 3)) {
1275 printf("ERROR: You are using a dbench 1 load file\n");
1279 if (!strcmp(params[0],"NTCreateX")) {
1280 nb_createx(params[1], ival(params[2]), ival(params[3]),
1282 } else if (!strcmp(params[0],"Close")) {
1283 nb_close(ival(params[1]));
1284 } else if (!strcmp(params[0],"Rename")) {
1285 nb_rename(params[1], params[2]);
1286 } else if (!strcmp(params[0],"Unlink")) {
1287 nb_unlink(params[1]);
1288 } else if (!strcmp(params[0],"Deltree")) {
1289 nb_deltree(params[1]);
1290 } else if (!strcmp(params[0],"Rmdir")) {
1291 nb_rmdir(params[1]);
1292 } else if (!strcmp(params[0],"QUERY_PATH_INFORMATION")) {
1293 nb_qpathinfo(params[1]);
1294 } else if (!strcmp(params[0],"QUERY_FILE_INFORMATION")) {
1295 nb_qfileinfo(ival(params[1]));
1296 } else if (!strcmp(params[0],"QUERY_FS_INFORMATION")) {
1297 nb_qfsinfo(ival(params[1]));
1298 } else if (!strcmp(params[0],"FIND_FIRST")) {
1299 nb_findfirst(params[1]);
1300 } else if (!strcmp(params[0],"WriteX")) {
1301 nb_writex(ival(params[1]),
1302 ival(params[2]), ival(params[3]), ival(params[4]));
1303 } else if (!strcmp(params[0],"ReadX")) {
1304 nb_readx(ival(params[1]),
1305 ival(params[2]), ival(params[3]), ival(params[4]));
1306 } else if (!strcmp(params[0],"Flush")) {
1307 nb_flush(ival(params[1]));
1309 printf("Unknown operation %s\n", params[0]);
1317 if (!torture_close_connection(cli)) {
1325 /* run a test that simulates an approximate netbench client load */
1326 static bool run_nbench(int dummy)
1329 bool correct = True;
1331 nbio_shmem(torture_nprocs);
1335 signal(SIGALRM, nb_alarm);
1337 t = create_procs(run_netbench, &correct);
1340 printf("\nThroughput %g MB/sec\n",
1341 1.0e-6 * nbio_total() / t);
1347 This test checks for two things:
1349 1) correct support for retaining locks over a close (ie. the server
1350 must not use posix semantics)
1351 2) support for lock timeouts
1353 static bool run_locktest1(int dummy)
1355 struct cli_state *cli1, *cli2;
1356 const char *fname = "\\lockt1.lck";
1357 uint16_t fnum1, fnum2, fnum3;
1359 unsigned lock_timeout;
1362 if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
1365 smbXcli_conn_set_sockopt(cli1->conn, sockops);
1366 smbXcli_conn_set_sockopt(cli2->conn, sockops);
1368 printf("starting locktest1\n");
1370 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1372 status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
1374 if (!NT_STATUS_IS_OK(status)) {
1375 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
1379 status = cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum2);
1380 if (!NT_STATUS_IS_OK(status)) {
1381 printf("open2 of %s failed (%s)\n", fname, nt_errstr(status));
1385 status = cli_openx(cli2, fname, O_RDWR, DENY_NONE, &fnum3);
1386 if (!NT_STATUS_IS_OK(status)) {
1387 printf("open3 of %s failed (%s)\n", fname, nt_errstr(status));
1391 status = cli_lock32(cli1, fnum1, 0, 4, 0, WRITE_LOCK);
1392 if (!NT_STATUS_IS_OK(status)) {
1393 printf("lock1 failed (%s)\n", nt_errstr(status));
1397 status = cli_lock32(cli2, fnum3, 0, 4, 0, WRITE_LOCK);
1398 if (NT_STATUS_IS_OK(status)) {
1399 printf("lock2 succeeded! This is a locking bug\n");
1402 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1403 NT_STATUS_LOCK_NOT_GRANTED)) {
1408 lock_timeout = (1 + (random() % 20));
1409 printf("Testing lock timeout with timeout=%u\n", lock_timeout);
1411 status = cli_lock32(cli2, fnum3, 0, 4, lock_timeout * 1000, WRITE_LOCK);
1412 if (NT_STATUS_IS_OK(status)) {
1413 printf("lock3 succeeded! This is a locking bug\n");
1416 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1417 NT_STATUS_FILE_LOCK_CONFLICT)) {
1423 if (ABS(t2 - t1) < lock_timeout-1) {
1424 printf("error: This server appears not to support timed lock requests\n");
1427 printf("server slept for %u seconds for a %u second timeout\n",
1428 (unsigned int)(t2-t1), lock_timeout);
1430 status = cli_close(cli1, fnum2);
1431 if (!NT_STATUS_IS_OK(status)) {
1432 printf("close1 failed (%s)\n", nt_errstr(status));
1436 status = cli_lock32(cli2, fnum3, 0, 4, 0, WRITE_LOCK);
1437 if (NT_STATUS_IS_OK(status)) {
1438 printf("lock4 succeeded! This is a locking bug\n");
1441 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1442 NT_STATUS_FILE_LOCK_CONFLICT)) {
1447 status = cli_close(cli1, fnum1);
1448 if (!NT_STATUS_IS_OK(status)) {
1449 printf("close2 failed (%s)\n", nt_errstr(status));
1453 status = cli_close(cli2, fnum3);
1454 if (!NT_STATUS_IS_OK(status)) {
1455 printf("close3 failed (%s)\n", nt_errstr(status));
1459 status = cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1460 if (!NT_STATUS_IS_OK(status)) {
1461 printf("unlink failed (%s)\n", nt_errstr(status));
1466 if (!torture_close_connection(cli1)) {
1470 if (!torture_close_connection(cli2)) {
1474 printf("Passed locktest1\n");
1479 this checks to see if a secondary tconx can use open files from an
1482 static bool run_tcon_test(int dummy)
1484 static struct cli_state *cli;
1485 const char *fname = "\\tcontest.tmp";
1487 uint32_t cnum1, cnum2, cnum3;
1488 struct smbXcli_tcon *orig_tcon = NULL;
1489 char *orig_share = NULL;
1490 uint16_t vuid1, vuid2;
1495 memset(buf, '\0', sizeof(buf));
1497 if (!torture_open_connection(&cli, 0)) {
1500 smbXcli_conn_set_sockopt(cli->conn, sockops);
1502 printf("starting tcontest\n");
1504 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1506 status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
1507 if (!NT_STATUS_IS_OK(status)) {
1508 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
1512 cnum1 = cli_state_get_tid(cli);
1513 vuid1 = cli_state_get_uid(cli);
1515 status = cli_writeall(cli, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
1516 if (!NT_STATUS_IS_OK(status)) {
1517 printf("initial write failed (%s)", nt_errstr(status));
1521 cli_state_save_tcon_share(cli, &orig_tcon, &orig_share);
1523 status = cli_tree_connect_creds(cli, share, "?????", torture_creds);
1524 if (!NT_STATUS_IS_OK(status)) {
1525 printf("%s refused 2nd tree connect (%s)\n", host,
1527 cli_state_restore_tcon_share(cli, orig_tcon, orig_share);
1532 cnum2 = cli_state_get_tid(cli);
1533 cnum3 = MAX(cnum1, cnum2) + 1; /* any invalid number */
1534 vuid2 = cli_state_get_uid(cli) + 1;
1536 /* try a write with the wrong tid */
1537 cli_state_set_tid(cli, cnum2);
1539 status = cli_writeall(cli, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
1540 if (NT_STATUS_IS_OK(status)) {
1541 printf("* server allows write with wrong TID\n");
1544 printf("server fails write with wrong TID : %s\n",
1549 /* try a write with an invalid tid */
1550 cli_state_set_tid(cli, cnum3);
1552 status = cli_writeall(cli, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
1553 if (NT_STATUS_IS_OK(status)) {
1554 printf("* server allows write with invalid TID\n");
1557 printf("server fails write with invalid TID : %s\n",
1561 /* try a write with an invalid vuid */
1562 cli_state_set_uid(cli, vuid2);
1563 cli_state_set_tid(cli, cnum1);
1565 status = cli_writeall(cli, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
1566 if (NT_STATUS_IS_OK(status)) {
1567 printf("* server allows write with invalid VUID\n");
1570 printf("server fails write with invalid VUID : %s\n",
1574 cli_state_set_tid(cli, cnum1);
1575 cli_state_set_uid(cli, vuid1);
1577 status = cli_close(cli, fnum1);
1578 if (!NT_STATUS_IS_OK(status)) {
1579 printf("close failed (%s)\n", nt_errstr(status));
1580 cli_state_restore_tcon_share(cli, orig_tcon, orig_share);
1585 cli_state_set_tid(cli, cnum2);
1587 status = cli_tdis(cli);
1588 if (!NT_STATUS_IS_OK(status)) {
1589 printf("secondary tdis failed (%s)\n", nt_errstr(status));
1590 cli_state_restore_tcon_share(cli, orig_tcon, orig_share);
1595 cli_state_restore_tcon_share(cli, orig_tcon, orig_share);
1597 cli_state_set_tid(cli, cnum1);
1599 if (!torture_close_connection(cli)) {
1608 checks for old style tcon support
1610 static bool run_tcon2_test(int dummy)
1612 static struct cli_state *cli;
1613 uint16_t cnum, max_xmit;
1617 if (!torture_open_connection(&cli, 0)) {
1620 smbXcli_conn_set_sockopt(cli->conn, sockops);
1622 printf("starting tcon2 test\n");
1624 if (asprintf(&service, "\\\\%s\\%s", host, share) == -1) {
1628 status = cli_raw_tcon(cli, service, password, "?????", &max_xmit, &cnum);
1632 if (!NT_STATUS_IS_OK(status)) {
1633 printf("tcon2 failed : %s\n", nt_errstr(status));
1635 printf("tcon OK : max_xmit=%d cnum=%d\n",
1636 (int)max_xmit, (int)cnum);
1639 if (!torture_close_connection(cli)) {
1643 printf("Passed tcon2 test\n");
1647 static bool tcon_devtest(struct cli_state *cli,
1648 const char *myshare, const char *devtype,
1649 const char *return_devtype,
1650 NTSTATUS expected_error)
1655 status = cli_tree_connect_creds(cli, myshare, devtype, torture_creds);
1657 if (NT_STATUS_IS_OK(expected_error)) {
1658 if (NT_STATUS_IS_OK(status)) {
1659 if (return_devtype != NULL &&
1660 strequal(cli->dev, return_devtype)) {
1663 printf("tconX to share %s with type %s "
1664 "succeeded but returned the wrong "
1665 "device type (got [%s] but should have got [%s])\n",
1666 myshare, devtype, cli->dev, return_devtype);
1670 printf("tconX to share %s with type %s "
1671 "should have succeeded but failed\n",
1677 if (NT_STATUS_IS_OK(status)) {
1678 printf("tconx to share %s with type %s "
1679 "should have failed but succeeded\n",
1683 if (NT_STATUS_EQUAL(status, expected_error)) {
1686 printf("Returned unexpected error\n");
1695 checks for correct tconX support
1697 static bool run_tcon_devtype_test(int dummy)
1699 static struct cli_state *cli1 = NULL;
1700 int flags = CLI_FULL_CONNECTION_FORCE_SMB1;
1704 status = cli_full_connection_creds(&cli1,
1710 NULL, /* service_type */
1714 if (!NT_STATUS_IS_OK(status)) {
1715 printf("could not open connection\n");
1719 if (!tcon_devtest(cli1, "IPC$", "A:", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1722 if (!tcon_devtest(cli1, "IPC$", "?????", "IPC", NT_STATUS_OK))
1725 if (!tcon_devtest(cli1, "IPC$", "LPT:", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1728 if (!tcon_devtest(cli1, "IPC$", "IPC", "IPC", NT_STATUS_OK))
1731 if (!tcon_devtest(cli1, "IPC$", "FOOBA", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1734 if (!tcon_devtest(cli1, share, "A:", "A:", NT_STATUS_OK))
1737 if (!tcon_devtest(cli1, share, "?????", "A:", NT_STATUS_OK))
1740 if (!tcon_devtest(cli1, share, "LPT:", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1743 if (!tcon_devtest(cli1, share, "IPC", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1746 if (!tcon_devtest(cli1, share, "FOOBA", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1752 printf("Passed tcondevtest\n");
1759 This test checks that
1761 1) the server supports multiple locking contexts on the one SMB
1762 connection, distinguished by PID.
1764 2) the server correctly fails overlapping locks made by the same PID (this
1765 goes against POSIX behaviour, which is why it is tricky to implement)
1767 3) the server denies unlock requests by an incorrect client PID
1769 static bool run_locktest2(int dummy)
1771 static struct cli_state *cli;
1772 const char *fname = "\\lockt2.lck";
1773 uint16_t fnum1, fnum2, fnum3;
1774 bool correct = True;
1777 if (!torture_open_connection(&cli, 0)) {
1781 smbXcli_conn_set_sockopt(cli->conn, sockops);
1783 printf("starting locktest2\n");
1785 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1789 status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
1790 if (!NT_STATUS_IS_OK(status)) {
1791 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
1795 status = cli_openx(cli, fname, O_RDWR, DENY_NONE, &fnum2);
1796 if (!NT_STATUS_IS_OK(status)) {
1797 printf("open2 of %s failed (%s)\n", fname, nt_errstr(status));
1803 status = cli_openx(cli, fname, O_RDWR, DENY_NONE, &fnum3);
1804 if (!NT_STATUS_IS_OK(status)) {
1805 printf("open3 of %s failed (%s)\n", fname, nt_errstr(status));
1811 status = cli_lock32(cli, fnum1, 0, 4, 0, WRITE_LOCK);
1812 if (!NT_STATUS_IS_OK(status)) {
1813 printf("lock1 failed (%s)\n", nt_errstr(status));
1817 status = cli_lock32(cli, fnum1, 0, 4, 0, WRITE_LOCK);
1818 if (NT_STATUS_IS_OK(status)) {
1819 printf("WRITE lock1 succeeded! This is a locking bug\n");
1822 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1823 NT_STATUS_LOCK_NOT_GRANTED)) {
1828 status = cli_lock32(cli, fnum2, 0, 4, 0, WRITE_LOCK);
1829 if (NT_STATUS_IS_OK(status)) {
1830 printf("WRITE lock2 succeeded! This is a locking bug\n");
1833 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1834 NT_STATUS_LOCK_NOT_GRANTED)) {
1839 status = cli_lock32(cli, fnum2, 0, 4, 0, READ_LOCK);
1840 if (NT_STATUS_IS_OK(status)) {
1841 printf("READ lock2 succeeded! This is a locking bug\n");
1844 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1845 NT_STATUS_FILE_LOCK_CONFLICT)) {
1850 status = cli_lock32(cli, fnum1, 100, 4, 0, WRITE_LOCK);
1851 if (!NT_STATUS_IS_OK(status)) {
1852 printf("lock at 100 failed (%s)\n", nt_errstr(status));
1855 if (NT_STATUS_IS_OK(cli_unlock(cli, fnum1, 100, 4))) {
1856 printf("unlock at 100 succeeded! This is a locking bug\n");
1860 status = cli_unlock(cli, fnum1, 0, 4);
1861 if (NT_STATUS_IS_OK(status)) {
1862 printf("unlock1 succeeded! This is a locking bug\n");
1865 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1866 NT_STATUS_RANGE_NOT_LOCKED)) {
1871 status = cli_unlock(cli, fnum1, 0, 8);
1872 if (NT_STATUS_IS_OK(status)) {
1873 printf("unlock2 succeeded! This is a locking bug\n");
1876 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1877 NT_STATUS_RANGE_NOT_LOCKED)) {
1882 status = cli_lock32(cli, fnum3, 0, 4, 0, WRITE_LOCK);
1883 if (NT_STATUS_IS_OK(status)) {
1884 printf("lock3 succeeded! This is a locking bug\n");
1887 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1888 NT_STATUS_LOCK_NOT_GRANTED)) {
1895 status = cli_close(cli, fnum1);
1896 if (!NT_STATUS_IS_OK(status)) {
1897 printf("close1 failed (%s)\n", nt_errstr(status));
1901 status = cli_close(cli, fnum2);
1902 if (!NT_STATUS_IS_OK(status)) {
1903 printf("close2 failed (%s)\n", nt_errstr(status));
1907 status = cli_close(cli, fnum3);
1908 if (!NT_STATUS_IS_OK(status)) {
1909 printf("close3 failed (%s)\n", nt_errstr(status));
1913 if (!torture_close_connection(cli)) {
1917 printf("locktest2 finished\n");
1924 This test checks that
1926 1) the server supports the full offset range in lock requests
1928 static bool run_locktest3(int dummy)
1930 static struct cli_state *cli1, *cli2;
1931 const char *fname = "\\lockt3.lck";
1932 uint16_t fnum1, fnum2;
1935 bool correct = True;
1938 #define NEXT_OFFSET offset += (~(uint32_t)0) / torture_numops
1940 if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
1943 smbXcli_conn_set_sockopt(cli1->conn, sockops);
1944 smbXcli_conn_set_sockopt(cli2->conn, sockops);
1946 printf("starting locktest3\n");
1948 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1950 status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
1952 if (!NT_STATUS_IS_OK(status)) {
1953 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
1957 status = cli_openx(cli2, fname, O_RDWR, DENY_NONE, &fnum2);
1958 if (!NT_STATUS_IS_OK(status)) {
1959 printf("open2 of %s failed (%s)\n", fname, nt_errstr(status));
1963 for (offset=i=0;i<torture_numops;i++) {
1966 status = cli_lock32(cli1, fnum1, offset-1, 1, 0, WRITE_LOCK);
1967 if (!NT_STATUS_IS_OK(status)) {
1968 printf("lock1 %d failed (%s)\n",
1974 status = cli_lock32(cli2, fnum2, offset-2, 1, 0, WRITE_LOCK);
1975 if (!NT_STATUS_IS_OK(status)) {
1976 printf("lock2 %d failed (%s)\n",
1983 for (offset=i=0;i<torture_numops;i++) {
1986 status = cli_lock32(cli1, fnum1, offset-2, 1, 0, WRITE_LOCK);
1987 if (NT_STATUS_IS_OK(status)) {
1988 printf("error: lock1 %d succeeded!\n", i);
1992 status = cli_lock32(cli2, fnum2, offset-1, 1, 0, WRITE_LOCK);
1993 if (NT_STATUS_IS_OK(status)) {
1994 printf("error: lock2 %d succeeded!\n", i);
1998 status = cli_lock32(cli1, fnum1, offset-1, 1, 0, WRITE_LOCK);
1999 if (NT_STATUS_IS_OK(status)) {
2000 printf("error: lock3 %d succeeded!\n", i);
2004 status = cli_lock32(cli2, fnum2, offset-2, 1, 0, WRITE_LOCK);
2005 if (NT_STATUS_IS_OK(status)) {
2006 printf("error: lock4 %d succeeded!\n", i);
2011 for (offset=i=0;i<torture_numops;i++) {
2014 status = cli_unlock(cli1, fnum1, offset-1, 1);
2015 if (!NT_STATUS_IS_OK(status)) {
2016 printf("unlock1 %d failed (%s)\n",
2022 status = cli_unlock(cli2, fnum2, offset-2, 1);
2023 if (!NT_STATUS_IS_OK(status)) {
2024 printf("unlock2 %d failed (%s)\n",
2031 status = cli_close(cli1, fnum1);
2032 if (!NT_STATUS_IS_OK(status)) {
2033 printf("close1 failed (%s)\n", nt_errstr(status));
2037 status = cli_close(cli2, fnum2);
2038 if (!NT_STATUS_IS_OK(status)) {
2039 printf("close2 failed (%s)\n", nt_errstr(status));
2043 status = cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2044 if (!NT_STATUS_IS_OK(status)) {
2045 printf("unlink failed (%s)\n", nt_errstr(status));
2049 if (!torture_close_connection(cli1)) {
2053 if (!torture_close_connection(cli2)) {
2057 printf("finished locktest3\n");
2062 static bool test_cli_read(struct cli_state *cli, uint16_t fnum,
2063 char *buf, off_t offset, size_t size,
2064 size_t *nread, size_t expect)
2069 status = cli_read(cli, fnum, buf, offset, size, &l_nread);
2071 if(!NT_STATUS_IS_OK(status)) {
2073 } else if (l_nread != expect) {
2084 #define EXPECTED(ret, v) if ((ret) != (v)) { \
2085 printf("** "); correct = False; \
2089 looks at overlapping locks
2091 static bool run_locktest4(int dummy)
2093 static struct cli_state *cli1, *cli2;
2094 const char *fname = "\\lockt4.lck";
2095 uint16_t fnum1, fnum2, f;
2098 bool correct = True;
2101 if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
2105 smbXcli_conn_set_sockopt(cli1->conn, sockops);
2106 smbXcli_conn_set_sockopt(cli2->conn, sockops);
2108 printf("starting locktest4\n");
2110 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2112 cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
2113 cli_openx(cli2, fname, O_RDWR, DENY_NONE, &fnum2);
2115 memset(buf, 0, sizeof(buf));
2117 status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 0, sizeof(buf),
2119 if (!NT_STATUS_IS_OK(status)) {
2120 printf("Failed to create file: %s\n", nt_errstr(status));
2125 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 4, 0, WRITE_LOCK)) &&
2126 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 2, 4, 0, WRITE_LOCK));
2127 EXPECTED(ret, False);
2128 printf("the same process %s set overlapping write locks\n", ret?"can":"cannot");
2130 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 10, 4, 0, READ_LOCK)) &&
2131 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 12, 4, 0, READ_LOCK));
2132 EXPECTED(ret, True);
2133 printf("the same process %s set overlapping read locks\n", ret?"can":"cannot");
2135 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 20, 4, 0, WRITE_LOCK)) &&
2136 NT_STATUS_IS_OK(cli_lock32(cli2, fnum2, 22, 4, 0, WRITE_LOCK));
2137 EXPECTED(ret, False);
2138 printf("a different connection %s set overlapping write locks\n", ret?"can":"cannot");
2140 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 30, 4, 0, READ_LOCK)) &&
2141 NT_STATUS_IS_OK(cli_lock32(cli2, fnum2, 32, 4, 0, READ_LOCK));
2142 EXPECTED(ret, True);
2143 printf("a different connection %s set overlapping read locks\n", ret?"can":"cannot");
2145 ret = (cli_setpid(cli1, 1),
2146 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 40, 4, 0, WRITE_LOCK))) &&
2147 (cli_setpid(cli1, 2),
2148 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 42, 4, 0, WRITE_LOCK)));
2149 EXPECTED(ret, False);
2150 printf("a different pid %s set overlapping write locks\n", ret?"can":"cannot");
2152 ret = (cli_setpid(cli1, 1),
2153 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 50, 4, 0, READ_LOCK))) &&
2154 (cli_setpid(cli1, 2),
2155 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 52, 4, 0, READ_LOCK)));
2156 EXPECTED(ret, True);
2157 printf("a different pid %s set overlapping read locks\n", ret?"can":"cannot");
2159 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 60, 4, 0, READ_LOCK)) &&
2160 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 60, 4, 0, READ_LOCK));
2161 EXPECTED(ret, True);
2162 printf("the same process %s set the same read lock twice\n", ret?"can":"cannot");
2164 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 70, 4, 0, WRITE_LOCK)) &&
2165 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 70, 4, 0, WRITE_LOCK));
2166 EXPECTED(ret, False);
2167 printf("the same process %s set the same write lock twice\n", ret?"can":"cannot");
2169 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 80, 4, 0, READ_LOCK)) &&
2170 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 80, 4, 0, WRITE_LOCK));
2171 EXPECTED(ret, False);
2172 printf("the same process %s overlay a read lock with a write lock\n", ret?"can":"cannot");
2174 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 90, 4, 0, WRITE_LOCK)) &&
2175 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 90, 4, 0, READ_LOCK));
2176 EXPECTED(ret, True);
2177 printf("the same process %s overlay a write lock with a read lock\n", ret?"can":"cannot");
2179 ret = (cli_setpid(cli1, 1),
2180 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 100, 4, 0, WRITE_LOCK))) &&
2181 (cli_setpid(cli1, 2),
2182 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 100, 4, 0, READ_LOCK)));
2183 EXPECTED(ret, False);
2184 printf("a different pid %s overlay a write lock with a read lock\n", ret?"can":"cannot");
2186 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 110, 4, 0, READ_LOCK)) &&
2187 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 112, 4, 0, READ_LOCK)) &&
2188 NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 110, 6));
2189 EXPECTED(ret, False);
2190 printf("the same process %s coalesce read locks\n", ret?"can":"cannot");
2193 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 120, 4, 0, WRITE_LOCK)) &&
2194 test_cli_read(cli2, fnum2, buf, 120, 4, NULL, 4);
2195 EXPECTED(ret, False);
2196 printf("this server %s strict write locking\n", ret?"doesn't do":"does");
2198 status = cli_lock32(cli1, fnum1, 130, 4, 0, READ_LOCK);
2199 ret = NT_STATUS_IS_OK(status);
2201 status = cli_writeall(cli2, fnum2, 0, (uint8_t *)buf, 130, 4,
2203 ret = NT_STATUS_IS_OK(status);
2205 EXPECTED(ret, False);
2206 printf("this server %s strict read locking\n", ret?"doesn't do":"does");
2209 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 140, 4, 0, READ_LOCK)) &&
2210 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 140, 4, 0, READ_LOCK)) &&
2211 NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 140, 4)) &&
2212 NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 140, 4));
2213 EXPECTED(ret, True);
2214 printf("this server %s do recursive read locking\n", ret?"does":"doesn't");
2217 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 150, 4, 0, WRITE_LOCK)) &&
2218 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 150, 4, 0, READ_LOCK)) &&
2219 NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 150, 4)) &&
2220 test_cli_read(cli2, fnum2, buf, 150, 4, NULL, 4) &&
2221 !(NT_STATUS_IS_OK(cli_writeall(cli2, fnum2, 0, (uint8_t *)buf,
2223 NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 150, 4));
2224 EXPECTED(ret, True);
2225 printf("this server %s do recursive lock overlays\n", ret?"does":"doesn't");
2227 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 160, 4, 0, READ_LOCK)) &&
2228 NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 160, 4)) &&
2229 NT_STATUS_IS_OK(cli_writeall(cli2, fnum2, 0, (uint8_t *)buf,
2231 test_cli_read(cli2, fnum2, buf, 160, 4, NULL, 4);
2232 EXPECTED(ret, True);
2233 printf("the same process %s remove a read lock using write locking\n", ret?"can":"cannot");
2235 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 170, 4, 0, WRITE_LOCK)) &&
2236 NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 170, 4)) &&
2237 NT_STATUS_IS_OK(cli_writeall(cli2, fnum2, 0, (uint8_t *)buf,
2239 test_cli_read(cli2, fnum2, buf, 170, 4, NULL, 4);
2240 EXPECTED(ret, True);
2241 printf("the same process %s remove a write lock using read locking\n", ret?"can":"cannot");
2243 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 190, 4, 0, WRITE_LOCK)) &&
2244 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 190, 4, 0, READ_LOCK)) &&
2245 NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 190, 4)) &&
2246 !NT_STATUS_IS_OK(cli_writeall(cli2, fnum2, 0, (uint8_t *)buf,
2248 test_cli_read(cli2, fnum2, buf, 190, 4, NULL, 4);
2249 EXPECTED(ret, True);
2250 printf("the same process %s remove the first lock first\n", ret?"does":"doesn't");
2252 cli_close(cli1, fnum1);
2253 cli_close(cli2, fnum2);
2254 cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
2255 cli_openx(cli1, fname, O_RDWR, DENY_NONE, &f);
2256 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 8, 0, READ_LOCK)) &&
2257 NT_STATUS_IS_OK(cli_lock32(cli1, f, 0, 1, 0, READ_LOCK)) &&
2258 NT_STATUS_IS_OK(cli_close(cli1, fnum1)) &&
2259 NT_STATUS_IS_OK(cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1)) &&
2260 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 7, 1, 0, WRITE_LOCK));
2262 cli_close(cli1, fnum1);
2263 EXPECTED(ret, True);
2264 printf("the server %s have the NT byte range lock bug\n", !ret?"does":"doesn't");
2267 cli_close(cli1, fnum1);
2268 cli_close(cli2, fnum2);
2269 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2270 torture_close_connection(cli1);
2271 torture_close_connection(cli2);
2273 printf("finished locktest4\n");
2278 looks at lock upgrade/downgrade.
2280 static bool run_locktest5(int dummy)
2282 static struct cli_state *cli1, *cli2;
2283 const char *fname = "\\lockt5.lck";
2284 uint16_t fnum1, fnum2, fnum3;
2287 bool correct = True;
2290 if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
2294 smbXcli_conn_set_sockopt(cli1->conn, sockops);
2295 smbXcli_conn_set_sockopt(cli2->conn, sockops);
2297 printf("starting locktest5\n");
2299 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2301 cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
2302 cli_openx(cli2, fname, O_RDWR, DENY_NONE, &fnum2);
2303 cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum3);
2305 memset(buf, 0, sizeof(buf));
2307 status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 0, sizeof(buf),
2309 if (!NT_STATUS_IS_OK(status)) {
2310 printf("Failed to create file: %s\n", nt_errstr(status));
2315 /* Check for NT bug... */
2316 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 8, 0, READ_LOCK)) &&
2317 NT_STATUS_IS_OK(cli_lock32(cli1, fnum3, 0, 1, 0, READ_LOCK));
2318 cli_close(cli1, fnum1);
2319 cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
2320 status = cli_lock32(cli1, fnum1, 7, 1, 0, WRITE_LOCK);
2321 ret = NT_STATUS_IS_OK(status);
2322 EXPECTED(ret, True);
2323 printf("this server %s the NT locking bug\n", ret ? "doesn't have" : "has");
2324 cli_close(cli1, fnum1);
2325 cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
2326 cli_unlock(cli1, fnum3, 0, 1);
2328 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 4, 0, WRITE_LOCK)) &&
2329 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 1, 1, 0, READ_LOCK));
2330 EXPECTED(ret, True);
2331 printf("the same process %s overlay a write with a read lock\n", ret?"can":"cannot");
2333 status = cli_lock32(cli2, fnum2, 0, 4, 0, READ_LOCK);
2334 ret = NT_STATUS_IS_OK(status);
2335 EXPECTED(ret, False);
2337 printf("a different process %s get a read lock on the first process lock stack\n", ret?"can":"cannot");
2339 /* Unlock the process 2 lock. */
2340 cli_unlock(cli2, fnum2, 0, 4);
2342 status = cli_lock32(cli1, fnum3, 0, 4, 0, READ_LOCK);
2343 ret = NT_STATUS_IS_OK(status);
2344 EXPECTED(ret, False);
2346 printf("the same process on a different fnum %s get a read lock\n", ret?"can":"cannot");
2348 /* Unlock the process 1 fnum3 lock. */
2349 cli_unlock(cli1, fnum3, 0, 4);
2351 /* Stack 2 more locks here. */
2352 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 4, 0, READ_LOCK)) &&
2353 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 4, 0, READ_LOCK));
2355 EXPECTED(ret, True);
2356 printf("the same process %s stack read locks\n", ret?"can":"cannot");
2358 /* Unlock the first process lock, then check this was the WRITE lock that was
2361 ret = NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 0, 4)) &&
2362 NT_STATUS_IS_OK(cli_lock32(cli2, fnum2, 0, 4, 0, READ_LOCK));
2364 EXPECTED(ret, True);
2365 printf("the first unlock removes the %s lock\n", ret?"WRITE":"READ");
2367 /* Unlock the process 2 lock. */
2368 cli_unlock(cli2, fnum2, 0, 4);
2370 /* We should have 3 stacked locks here. Ensure we need to do 3 unlocks. */
2372 ret = NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 1, 1)) &&
2373 NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 0, 4)) &&
2374 NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 0, 4));
2376 EXPECTED(ret, True);
2377 printf("the same process %s unlock the stack of 4 locks\n", ret?"can":"cannot");
2379 /* Ensure the next unlock fails. */
2380 ret = NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 0, 4));
2381 EXPECTED(ret, False);
2382 printf("the same process %s count the lock stack\n", !ret?"can":"cannot");
2384 /* Ensure connection 2 can get a write lock. */
2385 status = cli_lock32(cli2, fnum2, 0, 4, 0, WRITE_LOCK);
2386 ret = NT_STATUS_IS_OK(status);
2387 EXPECTED(ret, True);
2389 printf("a different process %s get a write lock on the unlocked stack\n", ret?"can":"cannot");
2393 cli_close(cli1, fnum1);
2394 cli_close(cli2, fnum2);
2395 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2396 if (!torture_close_connection(cli1)) {
2399 if (!torture_close_connection(cli2)) {
2403 printf("finished locktest5\n");
2409 tries the unusual lockingX locktype bits
2411 static bool run_locktest6(int dummy)
2413 static struct cli_state *cli;
2414 const char *fname[1] = { "\\lock6.txt" };
2419 if (!torture_open_connection(&cli, 0)) {
2423 smbXcli_conn_set_sockopt(cli->conn, sockops);
2425 printf("starting locktest6\n");
2428 printf("Testing %s\n", fname[i]);
2430 cli_unlink(cli, fname[i], FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2432 cli_openx(cli, fname[i], O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
2433 status = cli_locktype(cli, fnum, 0, 8, 0, LOCKING_ANDX_CHANGE_LOCKTYPE);
2434 cli_close(cli, fnum);
2435 printf("CHANGE_LOCKTYPE gave %s\n", nt_errstr(status));
2437 cli_openx(cli, fname[i], O_RDWR, DENY_NONE, &fnum);
2438 status = cli_locktype(cli, fnum, 0, 8, 0, LOCKING_ANDX_CANCEL_LOCK);
2439 cli_close(cli, fnum);
2440 printf("CANCEL_LOCK gave %s\n", nt_errstr(status));
2442 cli_unlink(cli, fname[i], FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2445 torture_close_connection(cli);
2447 printf("finished locktest6\n");
2451 static bool run_locktest7(int dummy)
2453 struct cli_state *cli1;
2454 const char *fname = "\\lockt7.lck";
2457 bool correct = False;
2461 if (!torture_open_connection(&cli1, 0)) {
2465 smbXcli_conn_set_sockopt(cli1->conn, sockops);
2467 printf("starting locktest7\n");
2469 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2471 cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
2473 memset(buf, 0, sizeof(buf));
2475 status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 0, sizeof(buf),
2477 if (!NT_STATUS_IS_OK(status)) {
2478 printf("Failed to create file: %s\n", nt_errstr(status));
2482 cli_setpid(cli1, 1);
2484 status = cli_lock32(cli1, fnum1, 130, 4, 0, READ_LOCK);
2485 if (!NT_STATUS_IS_OK(status)) {
2486 printf("Unable to apply read lock on range 130:4, "
2487 "error was %s\n", nt_errstr(status));
2490 printf("pid1 successfully locked range 130:4 for READ\n");
2493 status = cli_read(cli1, fnum1, buf, 130, 4, &nread);
2494 if (!NT_STATUS_IS_OK(status)) {
2495 printf("pid1 unable to read the range 130:4, error was %s\n",
2498 } else if (nread != 4) {
2499 printf("pid1 unable to read the range 130:4, "
2500 "recv %ld req %d\n", (unsigned long)nread, 4);
2503 printf("pid1 successfully read the range 130:4\n");
2506 status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
2507 if (!NT_STATUS_IS_OK(status)) {
2508 printf("pid1 unable to write to the range 130:4, error was "
2509 "%s\n", nt_errstr(status));
2510 if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
2511 printf("Incorrect error (should be NT_STATUS_FILE_LOCK_CONFLICT)\n");
2515 printf("pid1 successfully wrote to the range 130:4 (should be denied)\n");
2519 cli_setpid(cli1, 2);
2521 status = cli_read(cli1, fnum1, buf, 130, 4, &nread);
2522 if (!NT_STATUS_IS_OK(status)) {
2523 printf("pid2 unable to read the range 130:4, error was %s\n",
2526 } else if (nread != 4) {
2527 printf("pid2 unable to read the range 130:4, "
2528 "recv %ld req %d\n", (unsigned long)nread, 4);
2531 printf("pid2 successfully read the range 130:4\n");
2534 status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
2535 if (!NT_STATUS_IS_OK(status)) {
2536 printf("pid2 unable to write to the range 130:4, error was "
2537 "%s\n", nt_errstr(status));
2538 if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
2539 printf("Incorrect error (should be NT_STATUS_FILE_LOCK_CONFLICT)\n");
2543 printf("pid2 successfully wrote to the range 130:4 (should be denied)\n");
2547 cli_setpid(cli1, 1);
2548 cli_unlock(cli1, fnum1, 130, 4);
2550 status = cli_lock32(cli1, fnum1, 130, 4, 0, WRITE_LOCK);
2551 if (!NT_STATUS_IS_OK(status)) {
2552 printf("Unable to apply write lock on range 130:4, error was %s\n", nt_errstr(status));
2555 printf("pid1 successfully locked range 130:4 for WRITE\n");
2558 status = cli_read(cli1, fnum1, buf, 130, 4, &nread);
2559 if (!NT_STATUS_IS_OK(status)) {
2560 printf("pid1 unable to read the range 130:4, error was %s\n",
2563 } else if (nread != 4) {
2564 printf("pid1 unable to read the range 130:4, "
2565 "recv %ld req %d\n", (unsigned long)nread, 4);
2568 printf("pid1 successfully read the range 130:4\n");
2571 status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
2572 if (!NT_STATUS_IS_OK(status)) {
2573 printf("pid1 unable to write to the range 130:4, error was "
2574 "%s\n", nt_errstr(status));
2577 printf("pid1 successfully wrote to the range 130:4\n");
2580 cli_setpid(cli1, 2);
2582 status = cli_read(cli1, fnum1, buf, 130, 4, &nread);
2583 if (!NT_STATUS_IS_OK(status)) {
2584 printf("pid2 unable to read the range 130:4, error was "
2585 "%s\n", nt_errstr(status));
2586 if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
2587 printf("Incorrect error (should be NT_STATUS_FILE_LOCK_CONFLICT)\n");
2591 printf("pid2 successfully read the range 130:4 (should be denied) recv %ld\n",
2592 (unsigned long)nread);
2596 status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
2597 if (!NT_STATUS_IS_OK(status)) {
2598 printf("pid2 unable to write to the range 130:4, error was "
2599 "%s\n", nt_errstr(status));
2600 if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
2601 printf("Incorrect error (should be NT_STATUS_FILE_LOCK_CONFLICT)\n");
2605 printf("pid2 successfully wrote to the range 130:4 (should be denied)\n");
2609 cli_unlock(cli1, fnum1, 130, 0);
2613 cli_close(cli1, fnum1);
2614 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2615 torture_close_connection(cli1);
2617 printf("finished locktest7\n");
2622 * This demonstrates a problem with our use of GPFS share modes: A file
2623 * descriptor sitting in the pending close queue holding a GPFS share mode
2624 * blocks opening a file another time. Happens with Word 2007 temp files.
2625 * With "posix locking = yes" and "gpfs:sharemodes = yes" enabled, the third
2626 * open is denied with NT_STATUS_SHARING_VIOLATION.
2629 static bool run_locktest8(int dummy)
2631 struct cli_state *cli1;
2632 const char *fname = "\\lockt8.lck";
2633 uint16_t fnum1, fnum2;
2635 bool correct = False;
2638 if (!torture_open_connection(&cli1, 0)) {
2642 smbXcli_conn_set_sockopt(cli1->conn, sockops);
2644 printf("starting locktest8\n");
2646 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2648 status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_WRITE,
2650 if (!NT_STATUS_IS_OK(status)) {
2651 d_fprintf(stderr, "cli_openx returned %s\n", nt_errstr(status));
2655 memset(buf, 0, sizeof(buf));
2657 status = cli_openx(cli1, fname, O_RDONLY, DENY_NONE, &fnum2);
2658 if (!NT_STATUS_IS_OK(status)) {
2659 d_fprintf(stderr, "cli_openx second time returned %s\n",
2664 status = cli_lock32(cli1, fnum2, 1, 1, 0, READ_LOCK);
2665 if (!NT_STATUS_IS_OK(status)) {
2666 printf("Unable to apply read lock on range 1:1, error was "
2667 "%s\n", nt_errstr(status));
2671 status = cli_close(cli1, fnum1);
2672 if (!NT_STATUS_IS_OK(status)) {
2673 d_fprintf(stderr, "cli_close(fnum1) %s\n", nt_errstr(status));
2677 status = cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
2678 if (!NT_STATUS_IS_OK(status)) {
2679 d_fprintf(stderr, "cli_openx third time returned %s\n",
2687 cli_close(cli1, fnum1);
2688 cli_close(cli1, fnum2);
2689 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2690 torture_close_connection(cli1);
2692 printf("finished locktest8\n");
2697 * This test is designed to be run in conjunction with
2698 * external NFS or POSIX locks taken in the filesystem.
2699 * It checks that the smbd server will block until the
2700 * lock is released and then acquire it. JRA.
2703 static bool got_alarm;
2704 static struct cli_state *alarm_cli;
2706 static void alarm_handler(int dummy)
2711 static void alarm_handler_parent(int dummy)
2713 smbXcli_conn_disconnect(alarm_cli->conn, NT_STATUS_LOCAL_DISCONNECT);
2716 static void do_local_lock(const char *fname, int read_fd, int write_fd)
2721 const char *local_pathname = NULL;
2724 local_pathname = talloc_asprintf(talloc_tos(),
2725 "%s/%s", local_path, fname);
2726 if (!local_pathname) {
2727 printf("child: alloc fail\n");
2731 unlink(local_pathname);
2732 fd = open(local_pathname, O_RDWR|O_CREAT, 0666);
2734 printf("child: open of %s failed %s.\n",
2735 local_pathname, strerror(errno));
2739 /* Now take a fcntl lock. */
2740 lock.l_type = F_WRLCK;
2741 lock.l_whence = SEEK_SET;
2744 lock.l_pid = getpid();
2746 ret = fcntl(fd,F_SETLK,&lock);
2748 printf("child: failed to get lock 0:4 on file %s. Error %s\n",
2749 local_pathname, strerror(errno));
2752 printf("child: got lock 0:4 on file %s.\n",
2757 CatchSignal(SIGALRM, alarm_handler);
2759 /* Signal the parent. */
2760 if (write(write_fd, &c, 1) != 1) {
2761 printf("child: start signal fail %s.\n",
2768 /* Wait for the parent to be ready. */
2769 if (read(read_fd, &c, 1) != 1) {
2770 printf("child: reply signal fail %s.\n",
2778 printf("child: released lock 0:4 on file %s.\n",
2784 static bool _run_locktest9X(const char *fname, int timeout)
2786 struct cli_state *cli1;
2787 char *fpath = talloc_asprintf(talloc_tos(), "\\%s", fname);
2789 bool correct = False;
2790 int pipe_in[2], pipe_out[2];
2794 struct timeval start;
2798 printf("starting locktest9X: %s\n", fname);
2800 if (local_path == NULL) {
2801 d_fprintf(stderr, "locktest9X must be given a local path via -l <localpath>\n");
2805 if (pipe(pipe_in) == -1 || pipe(pipe_out) == -1) {
2810 if (child_pid == -1) {
2814 if (child_pid == 0) {
2816 do_local_lock(fname, pipe_out[0], pipe_in[1]);
2826 ret = read(pipe_in[0], &c, 1);
2828 d_fprintf(stderr, "failed to read start signal from child. %s\n",
2833 if (!torture_open_connection(&cli1, 0)) {
2837 smbXcli_conn_set_sockopt(cli1->conn, sockops);
2839 status = cli_openx(cli1, fpath, O_RDWR, DENY_NONE,
2841 if (!NT_STATUS_IS_OK(status)) {
2842 d_fprintf(stderr, "cli_openx returned %s\n", nt_errstr(status));
2846 /* Ensure the child has the lock. */
2847 status = cli_lock32(cli1, fnum, 0, 4, 0, WRITE_LOCK);
2848 if (NT_STATUS_IS_OK(status)) {
2849 d_fprintf(stderr, "Got the lock on range 0:4 - this should not happen !\n");
2852 d_printf("Child has the lock.\n");
2855 /* Tell the child to wait 5 seconds then exit. */
2856 ret = write(pipe_out[1], &c, 1);
2858 d_fprintf(stderr, "failed to send exit signal to child. %s\n",
2863 /* Wait 20 seconds for the lock. */
2865 CatchSignal(SIGALRM, alarm_handler_parent);
2868 start = timeval_current();
2870 status = cli_lock32(cli1, fnum, 0, 4, timeout, WRITE_LOCK);
2871 if (!NT_STATUS_IS_OK(status)) {
2872 d_fprintf(stderr, "Unable to apply write lock on range 0:4, error was "
2873 "%s\n", nt_errstr(status));
2878 seconds = timeval_elapsed(&start);
2880 printf("Parent got the lock after %.2f seconds.\n",
2883 status = cli_close(cli1, fnum);
2884 if (!NT_STATUS_IS_OK(status)) {
2885 d_fprintf(stderr, "cli_close(fnum1) %s\n", nt_errstr(status));
2892 cli_close(cli1, fnum);
2893 torture_close_connection(cli1);
2897 printf("finished locktest9X: %s\n", fname);
2901 static bool run_locktest9a(int dummy)
2903 return _run_locktest9X("lock9a.dat", -1);
2906 static bool run_locktest9b(int dummy)
2908 return _run_locktest9X("lock9b.dat", 10000);
2911 struct locktest10_state {
2916 static void locktest10_lockingx_done(struct tevent_req *subreq);
2917 static void locktest10_read_andx_done(struct tevent_req *subreq);
2919 static bool run_locktest10(int dummy)
2921 struct tevent_context *ev = NULL;
2922 struct cli_state *cli1 = NULL;
2923 struct cli_state *cli2 = NULL;
2924 struct smb1_lock_element lck = { 0 };
2925 struct tevent_req *reqs[2] = { NULL };
2926 struct tevent_req *smbreqs[2] = { NULL };
2927 const char fname[] = "\\lockt10.lck";
2928 uint16_t fnum1, fnum2;
2932 struct locktest10_state state = { .ok = true };
2935 printf("starting locktest10\n");
2937 ev = samba_tevent_context_init(NULL);
2939 d_fprintf(stderr, "samba_tevent_context_init failed\n");
2943 ok = torture_open_connection(&cli1, 0);
2947 smbXcli_conn_set_sockopt(cli1->conn, sockops);
2949 ok = torture_open_connection(&cli2, 1);
2953 smbXcli_conn_set_sockopt(cli2->conn, sockops);
2955 status = cli_openx(cli1, fname, O_CREAT|O_RDWR, DENY_NONE, &fnum1);
2956 if (!NT_STATUS_IS_OK(status)) {
2958 "cli_openx failed: %s\n",
2963 status = cli_writeall(cli1, fnum1, 0, &data, 0, sizeof(data), NULL);
2964 if (!NT_STATUS_IS_OK(status)) {
2966 "cli_writeall failed: %s\n",
2971 status = cli_openx(cli2, fname, O_CREAT|O_RDWR, DENY_NONE, &fnum2);
2972 if (!NT_STATUS_IS_OK(status)) {
2974 "cli_openx failed: %s\n",
2979 status = cli_locktype(
2980 cli2, fnum2, 0, 1, 0, LOCKING_ANDX_EXCLUSIVE_LOCK);
2981 if (!NT_STATUS_IS_OK(status)) {
2983 "cli_locktype failed: %s\n",
2988 lck = (struct smb1_lock_element) {
2989 .pid = cli_getpid(cli1), .offset = 0, .length = 1,
2992 reqs[0] = cli_lockingx_create(
2994 ev, /* tevent_context */
2997 LOCKING_ANDX_EXCLUSIVE_LOCK, /* typeoflock */
2998 0, /* newoplocklevel */
3000 0, /* num_unlocks */
3004 &smbreqs[0]); /* psmbreq */
3005 if (reqs[0] == NULL) {
3006 d_fprintf(stderr, "cli_lockingx_create failed\n");
3009 tevent_req_set_callback(reqs[0], locktest10_lockingx_done, &state);
3011 reqs[1] = cli_read_andx_create(
3018 &smbreqs[1]); /* psmbreq */
3019 if (reqs[1] == NULL) {
3020 d_fprintf(stderr, "cli_read_andx_create failed\n");
3023 tevent_req_set_callback(reqs[1], locktest10_read_andx_done, &state);
3025 status = smb1cli_req_chain_submit(smbreqs, ARRAY_SIZE(smbreqs));
3026 if (!NT_STATUS_IS_OK(status)) {
3028 "smb1cli_req_chain_submit failed: %s\n",
3033 while (!state.done) {
3034 tevent_loop_once(ev);
3037 torture_close_connection(cli1);
3046 static void locktest10_lockingx_done(struct tevent_req *subreq)
3048 struct locktest10_state *state = tevent_req_callback_data_void(subreq);
3051 status = cli_lockingx_recv(subreq);
3052 TALLOC_FREE(subreq);
3054 if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
3055 d_printf("cli_lockingx returned %s\n", nt_errstr(status));
3060 static void locktest10_read_andx_done(struct tevent_req *subreq)
3062 struct locktest10_state *state = tevent_req_callback_data_void(subreq);
3063 ssize_t received = -1;
3064 uint8_t *rcvbuf = NULL;
3067 status = cli_read_andx_recv(subreq, &received, &rcvbuf);
3069 if (!NT_STATUS_EQUAL(status, NT_STATUS_REQUEST_ABORTED)) {
3070 d_printf("cli_read_andx returned %s\n", nt_errstr(status));
3075 TALLOC_FREE(subreq);
3078 static bool run_locktest11(int dummy)
3080 struct cli_state *cli1;
3081 const char *fname = "\\lockt11.lck";
3086 if (!torture_open_connection(&cli1, 0)) {
3090 smbXcli_conn_set_sockopt(cli1->conn, sockops);
3092 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3094 status = cli_openx(cli1, fname, O_CREAT|O_RDWR, DENY_NONE, &fnum);
3095 if (!NT_STATUS_IS_OK(status)) {
3097 "cli_openx returned %s\n",
3103 * Test that LOCKING_ANDX_CANCEL_LOCK without any locks
3104 * returns NT_STATUS_OK
3107 status = cli_lockingx(
3110 LOCKING_ANDX_CANCEL_LOCK, /* typeoflock */
3111 0, /* newoplocklevel */
3113 0, /* num_unlocks */
3118 if (!NT_STATUS_IS_OK(status)) {
3119 d_printf("cli_lockingX returned %s\n", nt_errstr(status));
3125 cli_close(cli1, fnum);
3126 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3131 struct deferred_close_state {
3132 struct tevent_context *ev;
3133 struct cli_state *cli;
3137 static void deferred_close_waited(struct tevent_req *subreq);
3138 static void deferred_close_done(struct tevent_req *subreq);
3140 static struct tevent_req *deferred_close_send(
3141 TALLOC_CTX *mem_ctx,
3142 struct tevent_context *ev,
3144 struct cli_state *cli,
3147 struct tevent_req *req = NULL, *subreq = NULL;
3148 struct deferred_close_state *state = NULL;
3149 struct timeval wakeup_time = timeval_current_ofs(wait_secs, 0);
3151 req = tevent_req_create(
3152 mem_ctx, &state, struct deferred_close_state);
3160 subreq = tevent_wakeup_send(state, state->ev, wakeup_time);
3161 if (tevent_req_nomem(subreq, req)) {
3162 return tevent_req_post(req, ev);
3164 tevent_req_set_callback(subreq, deferred_close_waited, req);
3168 static void deferred_close_waited(struct tevent_req *subreq)
3170 struct tevent_req *req = tevent_req_callback_data(
3171 subreq, struct tevent_req);
3172 struct deferred_close_state *state = tevent_req_data(
3173 req, struct deferred_close_state);
3176 ok = tevent_wakeup_recv(subreq);
3177 TALLOC_FREE(subreq);
3179 tevent_req_oom(req);
3183 subreq = cli_close_send(state, state->ev, state->cli, state->fnum, 0);
3184 if (tevent_req_nomem(subreq, req)) {
3187 tevent_req_set_callback(subreq, deferred_close_done, req);
3190 static void deferred_close_done(struct tevent_req *subreq)
3192 NTSTATUS status = cli_close_recv(subreq);
3193 tevent_req_simple_finish_ntstatus(subreq, status);
3196 static NTSTATUS deferred_close_recv(struct tevent_req *req)
3198 return tevent_req_simple_recv_ntstatus(req);
3201 struct lockread_state {
3202 struct smb1_lock_element lck;
3203 struct tevent_req *reqs[2];
3204 struct tevent_req *smbreqs[2];
3205 NTSTATUS lock_status;
3206 NTSTATUS read_status;
3210 static void lockread_lockingx_done(struct tevent_req *subreq);
3211 static void lockread_read_andx_done(struct tevent_req *subreq);
3213 static struct tevent_req *lockread_send(
3214 TALLOC_CTX *mem_ctx,
3215 struct tevent_context *ev,
3216 struct cli_state *cli,
3219 struct tevent_req *req = NULL;
3220 struct lockread_state *state = NULL;
3223 req = tevent_req_create(mem_ctx, &state, struct lockread_state);
3228 state->lck = (struct smb1_lock_element) {
3229 .pid = cli_getpid(cli), .offset = 0, .length = 1,
3232 state->reqs[0] = cli_lockingx_create(
3234 ev, /* tevent_context */
3237 LOCKING_ANDX_EXCLUSIVE_LOCK, /* typeoflock */
3238 0, /* newoplocklevel */
3239 10000, /* timeout */
3240 0, /* num_unlocks */
3243 &state->lck, /* locks */
3244 &state->smbreqs[0]); /* psmbreq */
3245 if (tevent_req_nomem(state->reqs[0], req)) {
3246 return tevent_req_post(req, ev);
3248 tevent_req_set_callback(
3249 state->reqs[0], lockread_lockingx_done, req);
3251 state->reqs[1] = cli_read_andx_create(
3258 &state->smbreqs[1]); /* psmbreq */
3259 if (tevent_req_nomem(state->reqs[1], req)) {
3260 return tevent_req_post(req, ev);
3262 tevent_req_set_callback(
3263 state->reqs[1], lockread_read_andx_done, req);
3265 status = smb1cli_req_chain_submit(state->smbreqs, 2);
3266 if (tevent_req_nterror(req, status)) {
3267 return tevent_req_post(req, ev);
3272 static void lockread_lockingx_done(struct tevent_req *subreq)
3274 struct tevent_req *req = tevent_req_callback_data(
3275 subreq, struct tevent_req);
3276 struct lockread_state *state = tevent_req_data(
3277 req, struct lockread_state);
3278 state->lock_status = cli_lockingx_recv(subreq);
3279 TALLOC_FREE(subreq);
3281 "lockingx returned %s\n",
3282 nt_errstr(state->lock_status));
3285 static void lockread_read_andx_done(struct tevent_req *subreq)
3287 struct tevent_req *req = tevent_req_callback_data(
3288 subreq, struct tevent_req);
3289 struct lockread_state *state = tevent_req_data(
3290 req, struct lockread_state);
3291 ssize_t received = -1;
3292 uint8_t *rcvbuf = NULL;
3294 state->read_status = cli_read_andx_recv(subreq, &received, &rcvbuf);
3297 "read returned %s\n",
3298 nt_errstr(state->read_status));
3300 if (!NT_STATUS_IS_OK(state->read_status)) {
3301 TALLOC_FREE(subreq);
3302 tevent_req_done(req);
3307 state->readbuf = talloc_memdup(state, rcvbuf, received);
3308 TALLOC_FREE(subreq);
3309 if (tevent_req_nomem(state->readbuf, req)) {
3313 TALLOC_FREE(subreq);
3314 tevent_req_done(req);
3317 static NTSTATUS lockread_recv(
3318 struct tevent_req *req,
3319 NTSTATUS *lock_status,
3320 NTSTATUS *read_status,
3321 TALLOC_CTX *mem_ctx,
3324 struct lockread_state *state = tevent_req_data(
3325 req, struct lockread_state);
3328 if (tevent_req_is_nterror(req, &status)) {
3332 *lock_status = state->lock_status;
3333 *read_status = state->read_status;
3334 if (state->readbuf != NULL) {
3335 *read_buf = talloc_move(mem_ctx, &state->readbuf);
3340 return NT_STATUS_OK;
3343 struct lock12_state {
3347 static void lock12_closed(struct tevent_req *subreq);
3348 static void lock12_read(struct tevent_req *subreq);
3350 static struct tevent_req *lock12_send(
3351 TALLOC_CTX *mem_ctx,
3352 struct tevent_context *ev,
3353 struct cli_state *cli,
3357 struct tevent_req *req = NULL, *subreq = NULL;
3358 struct lock12_state *state = NULL;
3360 req = tevent_req_create(mem_ctx, &state, struct lock12_state);
3365 subreq = deferred_close_send(state, ev, 1, cli, fnum1);
3366 if (tevent_req_nomem(subreq, req)) {
3367 return tevent_req_post(req, ev);
3369 tevent_req_set_callback(subreq, lock12_closed, req);
3371 subreq = lockread_send(state, ev, cli, fnum2);
3372 if (tevent_req_nomem(subreq, req)) {
3373 return tevent_req_post(req, ev);
3375 tevent_req_set_callback(subreq, lock12_read, req);
3380 static void lock12_closed(struct tevent_req *subreq)
3382 struct tevent_req *req = tevent_req_callback_data(
3383 subreq, struct tevent_req);
3386 status = deferred_close_recv(subreq);
3387 TALLOC_FREE(subreq);
3388 DBG_DEBUG("close returned %s\n", nt_errstr(status));
3389 if (tevent_req_nterror(req, status)) {
3394 static void lock12_read(struct tevent_req *subreq)
3396 struct tevent_req *req = tevent_req_callback_data(
3397 subreq, struct tevent_req);
3398 struct lock12_state *state = tevent_req_data(
3399 req, struct lock12_state);
3400 NTSTATUS status, lock_status, read_status;
3401 uint8_t *buf = NULL;
3403 status = lockread_recv(
3404 subreq, &lock_status, &read_status, state, &buf);
3405 TALLOC_FREE(subreq);
3406 if (tevent_req_nterror(req, status) ||
3407 tevent_req_nterror(req, lock_status) ||
3408 tevent_req_nterror(req, read_status)) {
3411 tevent_req_done(req);
3414 static NTSTATUS lock12_recv(struct tevent_req *req)
3419 if (tevent_req_is_nterror(req, &status)) {
3422 return NT_STATUS_OK;
3425 static bool run_locktest12(int dummy)
3427 struct tevent_context *ev = NULL;
3428 struct tevent_req *req = NULL;
3429 struct cli_state *cli = NULL;
3430 const char fname[] = "\\lockt12.lck";
3431 uint16_t fnum1, fnum2;
3437 printf("starting locktest12\n");
3439 ev = samba_tevent_context_init(NULL);
3441 d_fprintf(stderr, "samba_tevent_context_init failed\n");
3445 ok = torture_open_connection(&cli, 0);
3449 smbXcli_conn_set_sockopt(cli->conn, sockops);
3451 status = cli_openx(cli, fname, O_CREAT|O_RDWR, DENY_NONE, &fnum1);
3452 if (!NT_STATUS_IS_OK(status)) {
3454 "cli_openx failed: %s\n",
3459 status = cli_openx(cli, fname, O_CREAT|O_RDWR, DENY_NONE, &fnum2);
3460 if (!NT_STATUS_IS_OK(status)) {
3462 "cli_openx failed: %s\n",
3467 status = cli_writeall(cli, fnum1, 0, &data, 0, sizeof(data), NULL);
3468 if (!NT_STATUS_IS_OK(status)) {
3470 "cli_writeall failed: %s\n",
3475 status = cli_locktype(
3476 cli, fnum1, 0, 1, 0, LOCKING_ANDX_EXCLUSIVE_LOCK);
3477 if (!NT_STATUS_IS_OK(status)) {
3479 "cli_locktype failed: %s\n",
3484 req = lock12_send(ev, ev, cli, fnum1, fnum2);
3486 d_fprintf(stderr, "lock12_send failed\n");
3490 ok = tevent_req_poll_ntstatus(req, ev, &status);
3492 d_fprintf(stderr, "tevent_req_poll_ntstatus failed\n");
3496 if (!NT_STATUS_IS_OK(status)) {
3498 "tevent_req_poll_ntstatus returned %s\n",
3503 status = lock12_recv(req);
3504 if (!NT_STATUS_IS_OK(status)) {
3505 d_fprintf(stderr, "lock12 returned %s\n", nt_errstr(status));
3512 torture_close_connection(cli);
3517 struct lock_ntcancel_state {
3518 struct timeval start;
3519 struct smb1_lock_element lck;
3520 struct tevent_req *subreq;
3523 static void lock_ntcancel_waited(struct tevent_req *subreq);
3524 static void lock_ntcancel_done(struct tevent_req *subreq);
3526 static struct tevent_req *lock_ntcancel_send(
3527 TALLOC_CTX *mem_ctx,
3528 struct tevent_context *ev,
3529 struct cli_state *cli,
3532 struct tevent_req *req = NULL, *subreq = NULL;
3533 struct lock_ntcancel_state *state = NULL;
3535 req = tevent_req_create(mem_ctx, &state, struct lock_ntcancel_state);
3539 state->lck = (struct smb1_lock_element) {
3540 .pid = cli_getpid(cli), .offset = 0, .length = 1,
3542 state->start = timeval_current();
3544 state->subreq = cli_lockingx_send(
3545 state, /* mem_ctx */
3546 ev, /* tevent_context */
3549 LOCKING_ANDX_EXCLUSIVE_LOCK, /* typeoflock */
3550 0, /* newoplocklevel */
3551 10000, /* timeout */
3552 0, /* num_unlocks */
3555 &state->lck); /* locks */
3556 if (tevent_req_nomem(state->subreq, req)) {
3557 return tevent_req_post(req, ev);
3559 tevent_req_set_callback(state->subreq, lock_ntcancel_done, req);
3561 subreq = tevent_wakeup_send(state, ev, timeval_current_ofs(1, 0));
3562 if (tevent_req_nomem(subreq, req)) {
3563 return tevent_req_post(req, ev);
3565 tevent_req_set_callback(subreq, lock_ntcancel_waited, req);
3569 static void lock_ntcancel_waited(struct tevent_req *subreq)
3571 struct tevent_req *req = tevent_req_callback_data(
3572 subreq, struct tevent_req);
3573 struct lock_ntcancel_state *state = tevent_req_data(
3574 req, struct lock_ntcancel_state);
3577 ok = tevent_wakeup_recv(subreq);
3578 TALLOC_FREE(subreq);
3580 tevent_req_oom(req);
3584 ok = tevent_req_cancel(state->subreq);
3586 d_fprintf(stderr, "Could not cancel subreq\n");
3587 tevent_req_oom(req);
3592 static void lock_ntcancel_done(struct tevent_req *subreq)
3594 struct tevent_req *req = tevent_req_callback_data(
3595 subreq, struct tevent_req);
3596 struct lock_ntcancel_state *state = tevent_req_data(
3597 req, struct lock_ntcancel_state);
3601 status = cli_lockingx_recv(subreq);
3602 TALLOC_FREE(subreq);
3604 if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
3605 d_printf("cli_lockingx returned %s\n", nt_errstr(status));
3606 tevent_req_nterror(req, NT_STATUS_UNSUCCESSFUL);
3610 elapsed = timeval_elapsed(&state->start);
3613 d_printf("cli_lockingx was too slow, cancel did not work\n");
3614 tevent_req_nterror(req, NT_STATUS_UNSUCCESSFUL);
3618 tevent_req_done(req);
3621 static NTSTATUS lock_ntcancel_recv(struct tevent_req *req)
3623 return tevent_req_simple_recv_ntstatus(req);
3626 static bool run_locktest13(int dummy)
3628 struct tevent_context *ev = NULL;
3629 struct tevent_req *req = NULL;
3630 struct cli_state *cli = NULL;
3631 const char fname[] = "\\lockt13.lck";
3632 uint16_t fnum1, fnum2;
3638 printf("starting locktest13\n");
3640 ev = samba_tevent_context_init(NULL);
3642 d_fprintf(stderr, "samba_tevent_context_init failed\n");
3646 ok = torture_open_connection(&cli, 0);
3650 smbXcli_conn_set_sockopt(cli->conn, sockops);
3652 status = cli_openx(cli, fname, O_CREAT|O_RDWR, DENY_NONE, &fnum1);
3653 if (!NT_STATUS_IS_OK(status)) {
3655 "cli_openx failed: %s\n",
3660 status = cli_openx(cli, fname, O_CREAT|O_RDWR, DENY_NONE, &fnum2);
3661 if (!NT_STATUS_IS_OK(status)) {
3663 "cli_openx failed: %s\n",
3668 status = cli_writeall(cli, fnum1, 0, &data, 0, sizeof(data), NULL);
3669 if (!NT_STATUS_IS_OK(status)) {
3671 "cli_writeall failed: %s\n",
3676 status = cli_locktype(
3677 cli, fnum1, 0, 1, 0, LOCKING_ANDX_EXCLUSIVE_LOCK);
3678 if (!NT_STATUS_IS_OK(status)) {
3680 "cli_locktype failed: %s\n",
3685 req = lock_ntcancel_send(ev, ev, cli, fnum2);
3687 d_fprintf(stderr, "lock_ntcancel_send failed\n");
3691 ok = tevent_req_poll_ntstatus(req, ev, &status);
3693 d_fprintf(stderr, "tevent_req_poll_ntstatus failed\n");
3697 if (!NT_STATUS_IS_OK(status)) {
3699 "tevent_req_poll_ntstatus returned %s\n",
3704 status = lock_ntcancel_recv(req);
3705 if (!NT_STATUS_IS_OK(status)) {
3707 "lock_ntcancel returned %s\n",
3715 torture_close_connection(cli);
3721 test whether fnums and tids open on one VC are available on another (a major
3724 static bool run_fdpasstest(int dummy)
3726 struct cli_state *cli1, *cli2;
3727 const char *fname = "\\fdpass.tst";
3732 if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
3735 smbXcli_conn_set_sockopt(cli1->conn, sockops);
3736 smbXcli_conn_set_sockopt(cli2->conn, sockops);
3738 printf("starting fdpasstest\n");
3740 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3742 status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
3744 if (!NT_STATUS_IS_OK(status)) {
3745 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
3749 status = cli_writeall(cli1, fnum1, 0, (const uint8_t *)"hello world\n", 0,
3751 if (!NT_STATUS_IS_OK(status)) {
3752 printf("write failed (%s)\n", nt_errstr(status));
3756 cli_state_set_uid(cli2, cli_state_get_uid(cli1));
3757 cli_state_set_tid(cli2, cli_state_get_tid(cli1));
3758 cli_setpid(cli2, cli_getpid(cli1));
3760 if (test_cli_read(cli2, fnum1, buf, 0, 13, NULL, 13)) {
3761 printf("read succeeded! nasty security hole [%s]\n", buf);
3765 cli_close(cli1, fnum1);
3766 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3768 torture_close_connection(cli1);
3769 torture_close_connection(cli2);
3771 printf("finished fdpasstest\n");
3775 static bool run_fdsesstest(int dummy)
3777 struct cli_state *cli;
3779 uint16_t saved_vuid;
3781 uint32_t saved_cnum;
3782 const char *fname = "\\fdsess.tst";
3783 const char *fname1 = "\\fdsess1.tst";
3790 if (!torture_open_connection(&cli, 0))
3792 smbXcli_conn_set_sockopt(cli->conn, sockops);
3794 if (!torture_cli_session_setup2(cli, &new_vuid))
3797 saved_cnum = cli_state_get_tid(cli);
3798 if (!NT_STATUS_IS_OK(cli_tree_connect(cli, share, "?????", NULL)))
3800 new_cnum = cli_state_get_tid(cli);
3801 cli_state_set_tid(cli, saved_cnum);
3803 printf("starting fdsesstest\n");
3805 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3806 cli_unlink(cli, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3808 status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
3809 if (!NT_STATUS_IS_OK(status)) {
3810 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
3814 status = cli_writeall(cli, fnum1, 0, (const uint8_t *)"hello world\n", 0, 13,
3816 if (!NT_STATUS_IS_OK(status)) {
3817 printf("write failed (%s)\n", nt_errstr(status));
3821 saved_vuid = cli_state_get_uid(cli);
3822 cli_state_set_uid(cli, new_vuid);
3824 if (test_cli_read(cli, fnum1, buf, 0, 13, NULL, 13)) {
3825 printf("read succeeded with different vuid! "
3826 "nasty security hole [%s]\n", buf);
3829 /* Try to open a file with different vuid, samba cnum. */
3830 if (NT_STATUS_IS_OK(cli_openx(cli, fname1, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum2))) {
3831 printf("create with different vuid, same cnum succeeded.\n");
3832 cli_close(cli, fnum2);
3833 cli_unlink(cli, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3835 printf("create with different vuid, same cnum failed.\n");
3836 printf("This will cause problems with service clients.\n");
3840 cli_state_set_uid(cli, saved_vuid);
3842 /* Try with same vuid, different cnum. */
3843 cli_state_set_tid(cli, new_cnum);
3845 if (test_cli_read(cli, fnum1, buf, 0, 13, NULL, 13)) {
3846 printf("read succeeded with different cnum![%s]\n", buf);
3850 cli_state_set_tid(cli, saved_cnum);
3851 cli_close(cli, fnum1);
3852 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3854 torture_close_connection(cli);
3856 printf("finished fdsesstest\n");
3861 This test checks that
3863 1) the server does not allow an unlink on a file that is open
3865 static bool run_unlinktest(int dummy)
3867 struct cli_state *cli;
3868 const char *fname = "\\unlink.tst";
3870 bool correct = True;
3873 if (!torture_open_connection(&cli, 0)) {
3877 smbXcli_conn_set_sockopt(cli->conn, sockops);
3879 printf("starting unlink test\n");
3881 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3885 status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
3886 if (!NT_STATUS_IS_OK(status)) {
3887 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
3891 status = cli_unlink(cli, fname,
3892 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3893 if (NT_STATUS_IS_OK(status)) {
3894 printf("error: server allowed unlink on an open file\n");
3897 correct = check_error(__LINE__, status, ERRDOS, ERRbadshare,
3898 NT_STATUS_SHARING_VIOLATION);
3901 cli_close(cli, fnum);
3902 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3904 if (!torture_close_connection(cli)) {
3908 printf("unlink test finished\n");
3915 test how many open files this server supports on the one socket
3917 static bool run_maxfidtest(int dummy)
3919 struct cli_state *cli;
3921 uint16_t fnums[0x11000];
3924 bool correct = True;
3930 printf("failed to connect\n");
3934 smbXcli_conn_set_sockopt(cli->conn, sockops);
3936 for (i=0; i<0x11000; i++) {
3937 slprintf(fname,sizeof(fname)-1,"\\maxfid.%d.%d", i,(int)getpid());
3938 status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_TRUNC, DENY_NONE,
3940 if (!NT_STATUS_IS_OK(status)) {
3941 printf("open of %s failed (%s)\n",
3942 fname, nt_errstr(status));
3943 printf("maximum fnum is %d\n", i);
3951 printf("cleaning up\n");
3953 slprintf(fname,sizeof(fname)-1,"\\maxfid.%d.%d", i,(int)getpid());
3954 cli_close(cli, fnums[i]);
3956 status = cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3957 if (!NT_STATUS_IS_OK(status)) {
3958 printf("unlink of %s failed (%s)\n",
3959 fname, nt_errstr(status));
3966 printf("maxfid test finished\n");
3967 if (!torture_close_connection(cli)) {
3973 /* generate a random buffer */
3974 static void rand_buf(char *buf, int len)
3977 *buf = (char)sys_random();
3982 /* send smb negprot commands, not reading the response */
3983 static bool run_negprot_nowait(int dummy)
3985 struct tevent_context *ev;
3987 struct cli_state *cli;
3988 bool correct = True;
3990 printf("starting negprot nowait test\n");
3992 ev = samba_tevent_context_init(talloc_tos());
3997 if (!(cli = open_nbt_connection())) {
4002 for (i=0;i<50000;i++) {
4003 struct tevent_req *req;
4005 req = smbXcli_negprot_send(
4018 if (!tevent_req_poll(req, ev)) {
4019 d_fprintf(stderr, "tevent_req_poll failed: %s\n",
4027 if (torture_close_connection(cli)) {
4031 printf("finished negprot nowait test\n");
4036 /* send smb negprot commands, not reading the response */
4037 static bool run_bad_nbt_session(int dummy)
4039 struct nmb_name called, calling;
4040 struct sockaddr_storage ss;
4045 printf("starting bad nbt session test\n");
4047 make_nmb_name(&calling, myname, 0x0);
4048 make_nmb_name(&called , host, 0x20);
4050 if (!resolve_name(host, &ss, 0x20, true)) {
4051 d_fprintf(stderr, "Could not resolve name %s\n", host);
4055 status = open_socket_out(&ss, NBT_SMB_PORT, 10000, &fd);
4056 if (!NT_STATUS_IS_OK(status)) {
4057 d_fprintf(stderr, "open_socket_out failed: %s\n",
4062 ret = cli_bad_session_request(fd, &calling, &called);
4065 d_fprintf(stderr, "open_socket_out failed: %s\n",
4070 printf("finished bad nbt session test\n");
4074 /* send random IPC commands */
4075 static bool run_randomipc(int dummy)
4077 char *rparam = NULL;
4079 unsigned int rdrcnt,rprcnt;
4081 int api, param_len, i;
4082 struct cli_state *cli;
4083 bool correct = True;
4086 printf("starting random ipc test\n");
4088 if (!torture_open_connection(&cli, 0)) {
4092 for (i=0;i<count;i++) {
4093 api = sys_random() % 500;
4094 param_len = (sys_random() % 64);
4096 rand_buf(param, param_len);
4101 param, param_len, 8,
4102 NULL, 0, CLI_BUFFER_SIZE,
4106 printf("%d/%d\r", i,count);
4109 printf("%d/%d\n", i, count);
4111 if (!torture_close_connection(cli)) {
4118 printf("finished random ipc test\n");
4125 static void browse_callback(const char *sname, uint32_t stype,
4126 const char *comment, void *state)
4128 printf("\t%20.20s %08x %s\n", sname, stype, comment);
4134 This test checks the browse list code
4137 static bool run_browsetest(int dummy)
4139 static struct cli_state *cli;
4140 bool correct = True;
4142 printf("starting browse test\n");
4144 if (!torture_open_connection(&cli, 0)) {
4148 printf("domain list:\n");
4149 cli_NetServerEnum(cli, cli->server_domain,
4150 SV_TYPE_DOMAIN_ENUM,
4151 browse_callback, NULL);
4153 printf("machine list:\n");
4154 cli_NetServerEnum(cli, cli->server_domain,
4156 browse_callback, NULL);
4158 if (!torture_close_connection(cli)) {
4162 printf("browse test finished\n");
4168 static bool check_attributes(struct cli_state *cli,
4170 uint32_t expected_attrs)
4173 NTSTATUS status = cli_getatr(cli,
4178 if (!NT_STATUS_IS_OK(status)) {
4179 printf("cli_getatr failed with %s\n",
4183 if (attrs != expected_attrs) {
4184 printf("Attributes incorrect 0x%x, should be 0x%x\n",
4185 (unsigned int)attrs,
4186 (unsigned int)expected_attrs);
4193 This checks how the getatr calls works
4195 static bool run_attrtest(int dummy)
4197 struct cli_state *cli;
4200 const char *fname = "\\attrib123456789.tst";
4201 bool correct = True;
4204 printf("starting attrib test\n");
4206 if (!torture_open_connection(&cli, 0)) {
4210 /* Ensure we can't unlink with out-of-range (unknown) attribute. */
4211 status = cli_unlink(cli, fname, 0x20000);
4212 if (!NT_STATUS_EQUAL(status, NT_STATUS_INVALID_PARAMETER)) {
4217 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4218 cli_openx(cli, fname,
4219 O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum);
4220 cli_close(cli, fnum);
4222 status = cli_getatr(cli, fname, NULL, NULL, &t);
4223 if (!NT_STATUS_IS_OK(status)) {
4224 printf("getatr failed (%s)\n", nt_errstr(status));
4228 if (labs(t - time(NULL)) > 60*60*24*10) {
4229 printf("ERROR: SMBgetatr bug. time is %s",
4235 t2 = t-60*60*24; /* 1 day ago */
4237 /* Ensure we can't set with out-of-range (unknown) attribute. */
4238 status = cli_setatr(cli, fname, 0x20000, t2);
4239 if (!NT_STATUS_EQUAL(status, NT_STATUS_INVALID_PARAMETER)) {
4244 status = cli_setatr(cli, fname, 0, t2);
4245 if (!NT_STATUS_IS_OK(status)) {
4246 printf("setatr failed (%s)\n", nt_errstr(status));
4250 status = cli_getatr(cli, fname, NULL, NULL, &t);
4251 if (!NT_STATUS_IS_OK(status)) {
4252 printf("getatr failed (%s)\n", nt_errstr(status));
4257 printf("ERROR: getatr/setatr bug. times are\n%s",
4259 printf("%s", ctime(&t2));
4263 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4265 /* Check cli_setpathinfo_ext() */
4266 /* Re-create the file. */
4267 status = cli_openx(cli, fname,
4268 O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum);
4269 if (!NT_STATUS_IS_OK(status)) {
4270 printf("Failed to recreate %s (%s)\n",
4271 fname, nt_errstr(status));
4274 cli_close(cli, fnum);
4276 status = cli_setpathinfo_ext(
4279 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* create */
4280 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* access */
4281 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* write */
4282 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* change */
4283 FILE_ATTRIBUTE_SYSTEM |
4284 FILE_ATTRIBUTE_HIDDEN |
4285 FILE_ATTRIBUTE_READONLY);
4286 if (!NT_STATUS_IS_OK(status)) {
4287 printf("cli_setpathinfo_ext failed with %s\n",
4292 /* Check attributes are correct. */
4293 correct = check_attributes(cli,
4295 FILE_ATTRIBUTE_SYSTEM |
4296 FILE_ATTRIBUTE_HIDDEN |
4297 FILE_ATTRIBUTE_READONLY);
4298 if (correct == false) {
4302 /* Setting to FILE_ATTRIBUTE_NORMAL should be ignored. */
4303 status = cli_setpathinfo_ext(
4306 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* create */
4307 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* access */
4308 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* write */
4309 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* change */
4310 FILE_ATTRIBUTE_NORMAL);
4311 if (!NT_STATUS_IS_OK(status)) {
4312 printf("cli_setpathinfo_ext failed with %s\n",
4317 /* Check attributes are correct. */
4318 correct = check_attributes(cli,
4320 FILE_ATTRIBUTE_SYSTEM |
4321 FILE_ATTRIBUTE_HIDDEN |
4322 FILE_ATTRIBUTE_READONLY);
4323 if (correct == false) {
4327 /* Setting to (uint16_t)-1 should also be ignored. */
4328 status = cli_setpathinfo_ext(
4331 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* create */
4332 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* access */
4333 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* write */
4334 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* change */
4336 if (!NT_STATUS_IS_OK(status)) {
4337 printf("cli_setpathinfo_ext failed with %s\n",
4342 /* Check attributes are correct. */
4343 correct = check_attributes(cli,
4345 FILE_ATTRIBUTE_SYSTEM |
4346 FILE_ATTRIBUTE_HIDDEN |
4347 FILE_ATTRIBUTE_READONLY);
4348 if (correct == false) {
4352 /* Setting to 0 should clear them all. */
4353 status = cli_setpathinfo_ext(
4356 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* create */
4357 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* access */
4358 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* write */
4359 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* change */
4361 if (!NT_STATUS_IS_OK(status)) {
4362 printf("cli_setpathinfo_ext failed with %s\n",
4367 /* Check attributes are correct. */
4368 correct = check_attributes(cli,
4370 FILE_ATTRIBUTE_NORMAL);
4371 if (correct == false) {
4379 FILE_ATTRIBUTE_SYSTEM |
4380 FILE_ATTRIBUTE_HIDDEN|
4381 FILE_ATTRIBUTE_READONLY);
4383 if (!torture_close_connection(cli)) {
4387 printf("attrib test finished\n");
4392 static NTSTATUS cli_qfilename(
4393 struct cli_state *cli,
4395 TALLOC_CTX *mem_ctx,
4398 uint16_t recv_flags2;
4405 status = cli_qfileinfo(talloc_tos(), cli, fnum,
4406 SMB_QUERY_FILE_NAME_INFO,
4407 4, CLI_BUFFER_SIZE, &recv_flags2,
4408 &rdata, &num_rdata);
4409 if (!NT_STATUS_IS_OK(status)) {
4413 namelen = IVAL(rdata, 0);
4414 if (namelen > (num_rdata - 4)) {
4416 return NT_STATUS_INVALID_NETWORK_RESPONSE;
4419 pull_string_talloc(mem_ctx,
4420 (const char *)rdata,
4427 status = map_nt_error_from_unix(errno);
4434 return NT_STATUS_OK;
4438 This checks a couple of trans2 calls
4440 static bool run_trans2test(int dummy)
4442 struct cli_state *cli;
4445 time_t c_time, a_time, m_time;
4446 struct timespec c_time_ts, a_time_ts, m_time_ts, w_time_ts, m_time2_ts;
4447 const char *fname = "\\trans2.tst";
4448 const char *dname = "\\trans2";
4449 const char *fname2 = "\\trans2\\trans2.tst";
4451 bool correct = True;
4456 printf("starting trans2 test\n");
4458 if (!torture_open_connection(&cli, 0)) {
4462 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
4463 /* Ensure ino is zero, SMB2 gets a real one. */
4466 /* Ensure ino is -1, SMB1 never gets a real one. */
4470 status = cli_get_fs_attr_info(cli, &fs_attr);
4471 if (!NT_STATUS_IS_OK(status)) {
4472 printf("ERROR: cli_get_fs_attr_info returned %s\n",
4477 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4478 cli_openx(cli, fname, O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum);
4479 status = cli_qfileinfo_basic(cli, fnum, NULL, &size, &c_time_ts,
4480 &a_time_ts, &w_time_ts, &m_time_ts, NULL);
4481 if (!NT_STATUS_IS_OK(status)) {
4482 printf("ERROR: qfileinfo failed (%s)\n", nt_errstr(status));
4486 status = cli_qfilename(cli, fnum, talloc_tos(), &pname);
4487 if (!NT_STATUS_IS_OK(status)) {
4488 printf("ERROR: qfilename failed (%s)\n", nt_errstr(status));
4491 else if (strcmp(pname, fname)) {
4492 printf("qfilename gave different name? [%s] [%s]\n",
4497 cli_close(cli, fnum);
4501 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4502 status = cli_openx(cli, fname, O_RDWR | O_CREAT | O_TRUNC, DENY_NONE,
4504 if (!NT_STATUS_IS_OK(status)) {
4505 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
4508 cli_close(cli, fnum);
4510 status = cli_qpathinfo1(cli, fname, &c_time, &a_time, &m_time, &size,
4512 if (!NT_STATUS_IS_OK(status)) {
4513 printf("ERROR: qpathinfo failed (%s)\n", nt_errstr(status));
4516 time_t t = time(NULL);
4518 if (c_time != m_time) {
4519 printf("create time=%s", ctime(&c_time));
4520 printf("modify time=%s", ctime(&m_time));
4521 printf("This system appears to have sticky create times\n");
4523 if ((labs(a_time - t) > 60) && (a_time % (60*60) == 0)) {
4524 printf("access time=%s", ctime(&a_time));
4525 printf("This system appears to set a midnight access time\n");
4529 if (labs(m_time - t) > 60*60*24*7) {
4530 printf("ERROR: totally incorrect times - maybe word reversed? mtime=%s", ctime(&m_time));
4536 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4537 cli_openx(cli, fname,
4538 O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum);
4539 cli_close(cli, fnum);
4540 status = cli_qpathinfo2(cli,
4550 if (!NT_STATUS_IS_OK(status)) {
4551 printf("ERROR: qpathinfo2 failed (%s)\n", nt_errstr(status));
4554 if (w_time_ts.tv_sec < 60*60*24*2) {
4555 printf("write time=%s", ctime(&w_time_ts.tv_sec));
4556 printf("This system appears to set a initial 0 write time\n");
4559 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
4560 /* SMB2 should always return an inode. */
4562 printf("SMB2 bad inode (0)\n");
4566 /* SMB1 must always return zero here. */
4568 printf("SMB1 bad inode (!0)\n");
4574 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4577 /* check if the server updates the directory modification time
4578 when creating a new file */
4579 status = cli_mkdir(cli, dname);
4580 if (!NT_STATUS_IS_OK(status)) {
4581 printf("ERROR: mkdir failed (%s)\n", nt_errstr(status));
4585 status = cli_qpathinfo2(cli,
4595 if (!NT_STATUS_IS_OK(status)) {
4596 printf("ERROR: qpathinfo2 failed (%s)\n", nt_errstr(status));
4600 cli_openx(cli, fname2,
4601 O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum);
4602 cli_writeall(cli, fnum, 0, (uint8_t *)&fnum, 0, sizeof(fnum), NULL);
4603 cli_close(cli, fnum);
4604 status = cli_qpathinfo2(cli,
4614 if (!NT_STATUS_IS_OK(status)) {
4615 printf("ERROR: qpathinfo2 failed (%s)\n", nt_errstr(status));
4618 if (memcmp(&m_time_ts, &m_time2_ts, sizeof(struct timespec))
4620 printf("This system does not update directory modification times\n");
4624 cli_unlink(cli, fname2, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4625 cli_rmdir(cli, dname);
4627 if (!torture_close_connection(cli)) {
4631 printf("trans2 test finished\n");
4637 This checks new W2K calls.
4640 static NTSTATUS new_trans(struct cli_state *pcli, int fnum, int level)
4642 uint8_t *buf = NULL;
4646 status = cli_qfileinfo(talloc_tos(), pcli, fnum, level, 0,
4647 CLI_BUFFER_SIZE, NULL, &buf, &len);
4648 if (!NT_STATUS_IS_OK(status)) {
4649 printf("ERROR: qfileinfo (%d) failed (%s)\n", level,
4652 printf("qfileinfo: level %d, len = %u\n", level, len);
4653 dump_data(0, (uint8_t *)buf, len);
4660 static bool run_w2ktest(int dummy)
4662 struct cli_state *cli;
4664 const char *fname = "\\w2ktest\\w2k.tst";
4666 bool correct = True;
4668 printf("starting w2k test\n");
4670 if (!torture_open_connection(&cli, 0)) {
4674 cli_openx(cli, fname,
4675 O_RDWR | O_CREAT , DENY_NONE, &fnum);
4677 for (level = 1004; level < 1040; level++) {
4678 new_trans(cli, fnum, level);
4681 cli_close(cli, fnum);
4683 if (!torture_close_connection(cli)) {
4687 printf("w2k test finished\n");
4694 this is a harness for some oplock tests
4696 static bool run_oplock1(int dummy)
4698 struct cli_state *cli1;
4699 const char *fname = "\\lockt1.lck";
4701 bool correct = True;
4704 printf("starting oplock test 1\n");
4706 if (!torture_open_connection(&cli1, 0)) {
4710 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4712 smbXcli_conn_set_sockopt(cli1->conn, sockops);
4714 cli1->use_oplocks = True;
4716 status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
4718 if (!NT_STATUS_IS_OK(status)) {
4719 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
4723 cli1->use_oplocks = False;
4725 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4726 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4728 status = cli_close(cli1, fnum1);
4729 if (!NT_STATUS_IS_OK(status)) {
4730 printf("close2 failed (%s)\n", nt_errstr(status));
4734 status = cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4735 if (!NT_STATUS_IS_OK(status)) {
4736 printf("unlink failed (%s)\n", nt_errstr(status));
4740 if (!torture_close_connection(cli1)) {
4744 printf("finished oplock test 1\n");
4749 static bool run_oplock2(int dummy)
4751 struct cli_state *cli1, *cli2;
4752 const char *fname = "\\lockt2.lck";
4753 uint16_t fnum1, fnum2;
4754 int saved_use_oplocks = use_oplocks;
4756 bool correct = True;
4757 volatile bool *shared_correct;
4761 shared_correct = (volatile bool *)anonymous_shared_allocate(sizeof(bool));
4762 *shared_correct = True;
4764 use_level_II_oplocks = True;
4767 printf("starting oplock test 2\n");
4769 if (!torture_open_connection(&cli1, 0)) {
4770 use_level_II_oplocks = False;
4771 use_oplocks = saved_use_oplocks;
4775 if (!torture_open_connection(&cli2, 1)) {
4776 use_level_II_oplocks = False;
4777 use_oplocks = saved_use_oplocks;
4781 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4783 smbXcli_conn_set_sockopt(cli1->conn, sockops);
4784 smbXcli_conn_set_sockopt(cli2->conn, sockops);
4786 status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
4788 if (!NT_STATUS_IS_OK(status)) {
4789 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
4793 /* Don't need the globals any more. */
4794 use_level_II_oplocks = False;
4795 use_oplocks = saved_use_oplocks;
4799 status = cli_openx(cli2, fname, O_RDWR, DENY_NONE, &fnum2);
4800 if (!NT_STATUS_IS_OK(status)) {
4801 printf("second open of %s failed (%s)\n", fname, nt_errstr(status));
4802 *shared_correct = False;
4808 status = cli_close(cli2, fnum2);
4809 if (!NT_STATUS_IS_OK(status)) {
4810 printf("close2 failed (%s)\n", nt_errstr(status));
4811 *shared_correct = False;
4819 /* Ensure cli1 processes the break. Empty file should always return 0
4821 status = cli_read(cli1, fnum1, buf, 0, 4, &nread);
4822 if (!NT_STATUS_IS_OK(status)) {
4823 printf("read on fnum1 failed (%s)\n", nt_errstr(status));
4825 } else if (nread != 0) {
4826 printf("read on empty fnum1 failed. recv %ld expected %d\n",
4827 (unsigned long)nread, 0);
4831 /* Should now be at level II. */
4832 /* Test if sending a write locks causes a break to none. */
4833 status = cli_lock32(cli1, fnum1, 0, 4, 0, READ_LOCK);
4834 if (!NT_STATUS_IS_OK(status)) {
4835 printf("lock failed (%s)\n", nt_errstr(status));
4839 cli_unlock(cli1, fnum1, 0, 4);
4843 status = cli_lock32(cli1, fnum1, 0, 4, 0, WRITE_LOCK);
4844 if (!NT_STATUS_IS_OK(status)) {
4845 printf("lock failed (%s)\n", nt_errstr(status));
4849 cli_unlock(cli1, fnum1, 0, 4);
4853 cli_read(cli1, fnum1, buf, 0, 4, NULL);
4855 status = cli_close(cli1, fnum1);
4856 if (!NT_STATUS_IS_OK(status)) {
4857 printf("close1 failed (%s)\n", nt_errstr(status));
4863 status = cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4864 if (!NT_STATUS_IS_OK(status)) {
4865 printf("unlink failed (%s)\n", nt_errstr(status));
4869 if (!torture_close_connection(cli1)) {
4873 if (!*shared_correct) {
4877 printf("finished oplock test 2\n");
4882 struct oplock4_state {
4883 struct tevent_context *ev;
4884 struct cli_state *cli;
4889 static void oplock4_got_break(struct tevent_req *req);
4890 static void oplock4_got_open(struct tevent_req *req);
4892 static bool run_oplock4(int dummy)
4894 struct tevent_context *ev;
4895 struct cli_state *cli1, *cli2;
4896 struct tevent_req *oplock_req, *open_req;
4897 const char *fname = "\\lockt4.lck";
4898 const char *fname_ln = "\\lockt4_ln.lck";
4899 uint16_t fnum1, fnum2;
4900 int saved_use_oplocks = use_oplocks;
4902 bool correct = true;
4906 struct oplock4_state *state;
4908 printf("starting oplock test 4\n");
4910 if (!torture_open_connection(&cli1, 0)) {
4911 use_level_II_oplocks = false;
4912 use_oplocks = saved_use_oplocks;
4916 if (!torture_open_connection(&cli2, 1)) {
4917 use_level_II_oplocks = false;
4918 use_oplocks = saved_use_oplocks;
4922 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4923 cli_unlink(cli1, fname_ln, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4925 smbXcli_conn_set_sockopt(cli1->conn, sockops);
4926 smbXcli_conn_set_sockopt(cli2->conn, sockops);
4928 /* Create the file. */
4929 status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
4931 if (!NT_STATUS_IS_OK(status)) {
4932 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
4936 status = cli_close(cli1, fnum1);
4937 if (!NT_STATUS_IS_OK(status)) {
4938 printf("close1 failed (%s)\n", nt_errstr(status));
4942 /* Now create a hardlink. */
4943 status = cli_hardlink(cli1, fname, fname_ln);
4944 if (!NT_STATUS_IS_OK(status)) {
4945 printf("nt hardlink failed (%s)\n", nt_errstr(status));
4949 /* Prove that opening hardlinks cause deny modes to conflict. */
4950 status = cli_openx(cli1, fname, O_RDWR, DENY_ALL, &fnum1);
4951 if (!NT_STATUS_IS_OK(status)) {
4952 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
4956 status = cli_openx(cli1, fname_ln, O_RDWR, DENY_NONE, &fnum2);
4957 if (NT_STATUS_IS_OK(status)) {
4958 printf("open of %s succeeded - should fail with sharing violation.\n",
4963 if (!NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
4964 printf("open of %s should fail with sharing violation. Got %s\n",
4965 fname_ln, nt_errstr(status));
4969 status = cli_close(cli1, fnum1);
4970 if (!NT_STATUS_IS_OK(status)) {
4971 printf("close1 failed (%s)\n", nt_errstr(status));
4975 cli1->use_oplocks = true;
4976 cli2->use_oplocks = true;
4978 status = cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
4979 if (!NT_STATUS_IS_OK(status)) {
4980 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
4984 ev = samba_tevent_context_init(talloc_tos());
4986 printf("tevent_context_init failed\n");
4990 state = talloc(ev, struct oplock4_state);
4991 if (state == NULL) {
4992 printf("talloc failed\n");
4997 state->got_break = &got_break;
4998 state->fnum2 = &fnum2;
5000 oplock_req = cli_smb_oplock_break_waiter_send(
5001 talloc_tos(), ev, cli1);
5002 if (oplock_req == NULL) {
5003 printf("cli_smb_oplock_break_waiter_send failed\n");
5006 tevent_req_set_callback(oplock_req, oplock4_got_break, state);
5008 open_req = cli_openx_send(
5009 talloc_tos(), ev, cli2, fname_ln, O_RDWR, DENY_NONE);
5010 if (open_req == NULL) {
5011 printf("cli_openx_send failed\n");
5014 tevent_req_set_callback(open_req, oplock4_got_open, state);
5019 while (!got_break || fnum2 == 0xffff) {
5021 ret = tevent_loop_once(ev);
5023 printf("tevent_loop_once failed: %s\n",
5029 status = cli_close(cli2, fnum2);
5030 if (!NT_STATUS_IS_OK(status)) {
5031 printf("close2 failed (%s)\n", nt_errstr(status));
5035 status = cli_close(cli1, fnum1);
5036 if (!NT_STATUS_IS_OK(status)) {
5037 printf("close1 failed (%s)\n", nt_errstr(status));
5041 status = cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5042 if (!NT_STATUS_IS_OK(status)) {
5043 printf("unlink failed (%s)\n", nt_errstr(status));
5047 status = cli_unlink(cli1, fname_ln, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5048 if (!NT_STATUS_IS_OK(status)) {
5049 printf("unlink failed (%s)\n", nt_errstr(status));
5053 if (!torture_close_connection(cli1)) {
5061 printf("finished oplock test 4\n");
5066 static void oplock4_got_break(struct tevent_req *req)
5068 struct oplock4_state *state = tevent_req_callback_data(
5069 req, struct oplock4_state);
5074 status = cli_smb_oplock_break_waiter_recv(req, &fnum, &level);
5076 if (!NT_STATUS_IS_OK(status)) {
5077 printf("cli_smb_oplock_break_waiter_recv returned %s\n",
5081 *state->got_break = true;
5083 req = cli_oplock_ack_send(state, state->ev, state->cli, fnum,
5086 printf("cli_oplock_ack_send failed\n");
5091 static void oplock4_got_open(struct tevent_req *req)
5093 struct oplock4_state *state = tevent_req_callback_data(
5094 req, struct oplock4_state);
5097 status = cli_openx_recv(req, state->fnum2);
5098 if (!NT_STATUS_IS_OK(status)) {
5099 printf("cli_openx_recv returned %s\n", nt_errstr(status));
5100 *state->fnum2 = 0xffff;
5104 #ifdef HAVE_KERNEL_OPLOCKS_LINUX
5106 struct oplock5_state {
5111 * Async open the file that has a kernel oplock, do an echo to get
5112 * that 100% across, close the file to signal to the child fd that the
5113 * oplock can be dropped, wait for the open reply.
5116 static void oplock5_opened(struct tevent_req *subreq);
5117 static void oplock5_pong(struct tevent_req *subreq);
5118 static void oplock5_timedout(struct tevent_req *subreq);
5120 static struct tevent_req *oplock5_send(
5121 TALLOC_CTX *mem_ctx,
5122 struct tevent_context *ev,
5123 struct cli_state *cli,
5127 struct tevent_req *req = NULL, *subreq = NULL;
5128 struct oplock5_state *state = NULL;
5129 static uint8_t data = 0;
5131 req = tevent_req_create(mem_ctx, &state, struct oplock5_state);
5135 state->pipe_down_fd = pipe_down_fd;
5137 subreq = cli_ntcreate_send(
5143 SEC_FILE_READ_DATA, /* DesiredAccess */
5144 FILE_ATTRIBUTE_NORMAL, /* FileAttributes */
5145 FILE_SHARE_WRITE|FILE_SHARE_READ, /* ShareAccess */
5146 FILE_OPEN, /* CreateDisposition */
5147 FILE_NON_DIRECTORY_FILE, /* CreateOptions */
5148 0, /* Impersonation */
5149 0); /* SecurityFlags */
5150 if (tevent_req_nomem(subreq, req)) {
5151 return tevent_req_post(req, ev);
5153 tevent_req_set_callback(subreq, oplock5_opened, req);
5155 subreq = cli_echo_send(
5160 (DATA_BLOB) { .data = &data, .length = sizeof(data) });
5161 if (tevent_req_nomem(subreq, req)) {
5162 return tevent_req_post(req, ev);
5164 tevent_req_set_callback(subreq, oplock5_pong, req);
5166 subreq = tevent_wakeup_send(state, ev, timeval_current_ofs(20, 0));
5167 if (tevent_req_nomem(subreq, req)) {
5168 return tevent_req_post(req, ev);
5170 tevent_req_set_callback(subreq, oplock5_timedout, req);
5175 static void oplock5_opened(struct tevent_req *subreq)
5177 struct tevent_req *req = tevent_req_callback_data(
5178 subreq, struct tevent_req);
5182 status = cli_ntcreate_recv(subreq, &fnum, NULL);
5183 TALLOC_FREE(subreq);
5184 if (tevent_req_nterror(req, status)) {
5187 tevent_req_done(req);
5190 static void oplock5_pong(struct tevent_req *subreq)
5192 struct tevent_req *req = tevent_req_callback_data(
5193 subreq, struct tevent_req);
5194 struct oplock5_state *state = tevent_req_data(
5195 req, struct oplock5_state);
5198 status = cli_echo_recv(subreq);
5199 TALLOC_FREE(subreq);
5200 if (tevent_req_nterror(req, status)) {
5204 close(state->pipe_down_fd);
5207 static void oplock5_timedout(struct tevent_req *subreq)
5209 struct tevent_req *req = tevent_req_callback_data(
5210 subreq, struct tevent_req);
5213 ok = tevent_wakeup_recv(subreq);
5214 TALLOC_FREE(subreq);
5216 tevent_req_oom(req);
5219 tevent_req_nterror(req, NT_STATUS_TIMEOUT);
5222 static NTSTATUS oplock5_recv(struct tevent_req *req)
5224 return tevent_req_simple_recv_ntstatus(req);
5227 static bool run_oplock5(int dummy)
5229 struct tevent_context *ev = NULL;
5230 struct tevent_req *req = NULL;
5231 struct cli_state *cli = NULL;
5232 const char *fname = "oplock5.txt";
5233 int pipe_down[2], pipe_up[2];
5240 printf("starting oplock5\n");
5242 if (local_path == NULL) {
5243 d_fprintf(stderr, "oplock5 must be given a local path via "
5244 "-l <localpath>\n");
5248 ret = pipe(pipe_down);
5250 d_fprintf(stderr, "pipe() failed: %s\n", strerror(errno));
5253 ret = pipe(pipe_up);
5255 d_fprintf(stderr, "pipe() failed: %s\n", strerror(errno));
5260 if (child_pid == -1) {
5261 d_fprintf(stderr, "fork() failed: %s\n", strerror(errno));
5265 if (child_pid == 0) {
5266 char *local_file = NULL;
5269 close(pipe_down[1]);
5272 local_file = talloc_asprintf(
5273 talloc_tos(), "%s/%s", local_path, fname);
5274 if (local_file == 0) {
5278 fd = open(local_file, O_RDWR|O_CREAT, 0644);
5281 "open(%s) in child failed: %s\n",
5288 signal(SIGIO, SIG_IGN);
5290 ret = fcntl(fd, F_SETLEASE, F_WRLCK);
5293 "SETLEASE in child failed: %s\n",
5300 ret = sys_write(pipe_up[1], &c, sizeof(c));
5303 "sys_write failed: %s\n",
5307 ret = sys_read(pipe_down[0], &c, sizeof(c));
5310 "sys_read failed: %s\n",
5318 close(pipe_down[0]);
5320 ret = sys_read(pipe_up[0], &c, sizeof(c));
5323 "sys_read failed: %s\n",
5328 d_fprintf(stderr, "got error code %"PRIu8"\n", c);
5332 ok = torture_open_connection(&cli, 0);
5334 d_fprintf(stderr, "torture_open_connection failed\n");
5338 ev = samba_tevent_context_init(talloc_tos());
5340 d_fprintf(stderr, "samba_tevent_context_init failed\n");
5344 req = oplock5_send(ev, ev, cli, fname, pipe_down[1]);
5346 d_fprintf(stderr, "oplock5_send failed\n");
5350 ok = tevent_req_poll_ntstatus(req, ev, &status);
5353 "tevent_req_poll_ntstatus failed: %s\n",
5358 status = oplock5_recv(req);
5360 if (!NT_STATUS_IS_OK(status)) {
5362 "oplock5 failed: %s\n",
5370 #endif /* HAVE_KERNEL_OPLOCKS_LINUX */
5373 Test delete on close semantics.
5375 static bool run_deletetest(int dummy)
5377 struct cli_state *cli1 = NULL;
5378 struct cli_state *cli2 = NULL;
5379 const char *fname = "\\delete.file";
5380 uint16_t fnum1 = (uint16_t)-1;
5381 uint16_t fnum2 = (uint16_t)-1;
5382 bool correct = false;
5385 printf("starting delete test\n");
5387 if (!torture_open_connection(&cli1, 0)) {
5391 smbXcli_conn_set_sockopt(cli1->conn, sockops);
5393 /* Test 1 - this should delete the file on close. */
5395 cli_setatr(cli1, fname, 0, 0);
5396 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5398 status = cli_ntcreate(cli1, fname, 0, GENERIC_ALL_ACCESS|DELETE_ACCESS,
5399 FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
5400 FILE_DELETE_ON_CLOSE, 0, &fnum1, NULL);
5401 if (!NT_STATUS_IS_OK(status)) {
5402 printf("[1] open of %s failed (%s)\n", fname, nt_errstr(status));
5406 status = cli_close(cli1, fnum1);
5407 if (!NT_STATUS_IS_OK(status)) {
5408 printf("[1] close failed (%s)\n", nt_errstr(status));
5412 status = cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
5413 if (NT_STATUS_IS_OK(status)) {
5414 printf("[1] open of %s succeeded (should fail)\n", fname);
5418 printf("first delete on close test succeeded.\n");
5420 /* Test 2 - this should delete the file on close. */
5422 cli_setatr(cli1, fname, 0, 0);
5423 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5425 status = cli_ntcreate(cli1, fname, 0, GENERIC_ALL_ACCESS,
5426 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
5427 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
5428 if (!NT_STATUS_IS_OK(status)) {
5429 printf("[2] open of %s failed (%s)\n", fname, nt_errstr(status));
5433 status = cli_nt_delete_on_close(cli1, fnum1, true);
5434 if (!NT_STATUS_IS_OK(status)) {
5435 printf("[2] setting delete_on_close failed (%s)\n", nt_errstr(status));
5439 status = cli_close(cli1, fnum1);
5440 if (!NT_STATUS_IS_OK(status)) {
5441 printf("[2] close failed (%s)\n", nt_errstr(status));
5445 status = cli_openx(cli1, fname, O_RDONLY, DENY_NONE, &fnum1);
5446 if (NT_STATUS_IS_OK(status)) {
5447 printf("[2] open of %s succeeded should have been deleted on close !\n", fname);
5448 status = cli_close(cli1, fnum1);
5449 if (!NT_STATUS_IS_OK(status)) {
5450 printf("[2] close failed (%s)\n", nt_errstr(status));
5452 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5456 printf("second delete on close test succeeded.\n");
5459 cli_setatr(cli1, fname, 0, 0);
5460 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5462 status = cli_ntcreate(cli1, fname, 0, GENERIC_ALL_ACCESS,
5463 FILE_ATTRIBUTE_NORMAL,
5464 FILE_SHARE_READ|FILE_SHARE_WRITE,
5465 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
5466 if (!NT_STATUS_IS_OK(status)) {
5467 printf("[3] open - 1 of %s failed (%s)\n", fname, nt_errstr(status));
5471 /* This should fail with a sharing violation - open for delete is only compatible
5472 with SHARE_DELETE. */
5474 status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
5475 FILE_ATTRIBUTE_NORMAL,
5476 FILE_SHARE_READ|FILE_SHARE_WRITE,
5477 FILE_OPEN, 0, 0, &fnum2, NULL);
5478 if (NT_STATUS_IS_OK(status)) {
5479 printf("[3] open - 2 of %s succeeded - should have failed.\n", fname);
5483 /* This should succeed. */
5484 status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
5485 FILE_ATTRIBUTE_NORMAL,
5486 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5487 FILE_OPEN, 0, 0, &fnum2, NULL);
5488 if (!NT_STATUS_IS_OK(status)) {
5489 printf("[3] open - 3 of %s failed (%s)\n", fname, nt_errstr(status));
5493 status = cli_nt_delete_on_close(cli1, fnum1, true);
5494 if (!NT_STATUS_IS_OK(status)) {
5495 printf("[3] setting delete_on_close failed (%s)\n", nt_errstr(status));
5499 status = cli_close(cli1, fnum1);
5500 if (!NT_STATUS_IS_OK(status)) {
5501 printf("[3] close 1 failed (%s)\n", nt_errstr(status));
5505 status = cli_close(cli1, fnum2);
5506 if (!NT_STATUS_IS_OK(status)) {
5507 printf("[3] close 2 failed (%s)\n", nt_errstr(status));
5511 /* This should fail - file should no longer be there. */
5513 status = cli_openx(cli1, fname, O_RDONLY, DENY_NONE, &fnum1);
5514 if (NT_STATUS_IS_OK(status)) {
5515 printf("[3] open of %s succeeded should have been deleted on close !\n", fname);
5516 status = cli_close(cli1, fnum1);
5517 if (!NT_STATUS_IS_OK(status)) {
5518 printf("[3] close failed (%s)\n", nt_errstr(status));
5520 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5524 printf("third delete on close test succeeded.\n");
5527 cli_setatr(cli1, fname, 0, 0);
5528 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5530 status = cli_ntcreate(cli1, fname, 0,
5531 FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
5532 FILE_ATTRIBUTE_NORMAL,
5533 FILE_SHARE_READ|FILE_SHARE_WRITE,
5534 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
5535 if (!NT_STATUS_IS_OK(status)) {
5536 printf("[4] open of %s failed (%s)\n", fname, nt_errstr(status));
5540 /* This should succeed. */
5541 status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
5542 FILE_ATTRIBUTE_NORMAL,
5543 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5544 FILE_OPEN, 0, 0, &fnum2, NULL);
5545 if (!NT_STATUS_IS_OK(status)) {
5546 printf("[4] open - 2 of %s failed (%s)\n", fname, nt_errstr(status));
5550 status = cli_close(cli1, fnum2);
5551 if (!NT_STATUS_IS_OK(status)) {
5552 printf("[4] close - 1 failed (%s)\n", nt_errstr(status));
5556 status = cli_nt_delete_on_close(cli1, fnum1, true);
5557 if (!NT_STATUS_IS_OK(status)) {
5558 printf("[4] setting delete_on_close failed (%s)\n", nt_errstr(status));
5562 /* This should fail - no more opens once delete on close set. */
5563 status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
5564 FILE_ATTRIBUTE_NORMAL,
5565 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5566 FILE_OPEN, 0, 0, &fnum2, NULL);
5567 if (NT_STATUS_IS_OK(status)) {
5568 printf("[4] open - 3 of %s succeeded ! Should have failed.\n", fname );
5572 status = cli_close(cli1, fnum1);
5573 if (!NT_STATUS_IS_OK(status)) {
5574 printf("[4] close - 2 failed (%s)\n", nt_errstr(status));
5578 printf("fourth delete on close test succeeded.\n");
5581 cli_setatr(cli1, fname, 0, 0);
5582 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5584 status = cli_openx(cli1, fname, O_RDWR|O_CREAT, DENY_NONE, &fnum1);
5585 if (!NT_STATUS_IS_OK(status)) {
5586 printf("[5] open of %s failed (%s)\n", fname, nt_errstr(status));
5590 /* This should fail - only allowed on NT opens with DELETE access. */
5592 status = cli_nt_delete_on_close(cli1, fnum1, true);
5593 if (NT_STATUS_IS_OK(status)) {
5594 printf("[5] setting delete_on_close on OpenX file succeeded - should fail !\n");
5598 status = cli_close(cli1, fnum1);
5599 if (!NT_STATUS_IS_OK(status)) {
5600 printf("[5] close failed (%s)\n", nt_errstr(status));
5604 printf("fifth delete on close test succeeded.\n");
5607 cli_setatr(cli1, fname, 0, 0);
5608 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5610 status = cli_ntcreate(cli1, fname, 0, FILE_READ_DATA|FILE_WRITE_DATA,
5611 FILE_ATTRIBUTE_NORMAL,
5612 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5613 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
5614 if (!NT_STATUS_IS_OK(status)) {
5615 printf("[6] open of %s failed (%s)\n", fname,
5620 /* This should fail - only allowed on NT opens with DELETE access. */
5622 status = cli_nt_delete_on_close(cli1, fnum1, true);
5623 if (NT_STATUS_IS_OK(status)) {
5624 printf("[6] setting delete_on_close on file with no delete access succeeded - should fail !\n");
5628 status = cli_close(cli1, fnum1);
5629 if (!NT_STATUS_IS_OK(status)) {
5630 printf("[6] close failed (%s)\n", nt_errstr(status));
5634 printf("sixth delete on close test succeeded.\n");
5637 cli_setatr(cli1, fname, 0, 0);
5638 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5640 status = cli_ntcreate(cli1, fname, 0,
5641 FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
5642 FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
5643 0, 0, &fnum1, NULL);
5644 if (!NT_STATUS_IS_OK(status)) {
5645 printf("[7] open of %s failed (%s)\n", fname, nt_errstr(status));
5649 status = cli_nt_delete_on_close(cli1, fnum1, true);
5650 if (!NT_STATUS_IS_OK(status)) {
5651 printf("[7] setting delete_on_close on file failed !\n");
5655 status = cli_nt_delete_on_close(cli1, fnum1, false);
5656 if (!NT_STATUS_IS_OK(status)) {
5657 printf("[7] unsetting delete_on_close on file failed !\n");
5661 status = cli_close(cli1, fnum1);
5662 if (!NT_STATUS_IS_OK(status)) {
5663 printf("[7] close - 1 failed (%s)\n", nt_errstr(status));
5667 /* This next open should succeed - we reset the flag. */
5668 status = cli_openx(cli1, fname, O_RDONLY, DENY_NONE, &fnum1);
5669 if (!NT_STATUS_IS_OK(status)) {
5670 printf("[7] open of %s failed (%s)\n", fname, nt_errstr(status));
5674 status = cli_close(cli1, fnum1);
5675 if (!NT_STATUS_IS_OK(status)) {
5676 printf("[7] close - 2 failed (%s)\n", nt_errstr(status));
5680 printf("seventh delete on close test succeeded.\n");
5683 cli_setatr(cli1, fname, 0, 0);
5684 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5686 if (!torture_open_connection(&cli2, 1)) {
5687 printf("[8] failed to open second connection.\n");
5691 smbXcli_conn_set_sockopt(cli1->conn, sockops);
5693 status = cli_ntcreate(cli1, fname, 0,
5694 FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
5695 FILE_ATTRIBUTE_NORMAL,
5696 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5697 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
5698 if (!NT_STATUS_IS_OK(status)) {
5699 printf("[8] open 1 of %s failed (%s)\n", fname, nt_errstr(status));
5703 status = cli_ntcreate(cli2, fname, 0,
5704 FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
5705 FILE_ATTRIBUTE_NORMAL,
5706 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5707 FILE_OPEN, 0, 0, &fnum2, NULL);
5708 if (!NT_STATUS_IS_OK(status)) {
5709 printf("[8] open 2 of %s failed (%s)\n", fname, nt_errstr(status));
5713 status = cli_nt_delete_on_close(cli1, fnum1, true);
5714 if (!NT_STATUS_IS_OK(status)) {
5715 printf("[8] setting delete_on_close on file failed !\n");
5719 status = cli_close(cli1, fnum1);
5720 if (!NT_STATUS_IS_OK(status)) {
5721 printf("[8] close - 1 failed (%s)\n", nt_errstr(status));
5725 status = cli_close(cli2, fnum2);
5726 if (!NT_STATUS_IS_OK(status)) {
5727 printf("[8] close - 2 failed (%s)\n", nt_errstr(status));
5731 /* This should fail.. */
5732 status = cli_openx(cli1, fname, O_RDONLY, DENY_NONE, &fnum1);
5733 if (NT_STATUS_IS_OK(status)) {
5734 printf("[8] open of %s succeeded should have been deleted on close !\n", fname);
5738 printf("eighth delete on close test succeeded.\n");
5742 /* This should fail - we need to set DELETE_ACCESS. */
5743 status = cli_ntcreate(cli1, fname, 0, FILE_READ_DATA|FILE_WRITE_DATA,
5744 FILE_ATTRIBUTE_NORMAL,
5747 FILE_DELETE_ON_CLOSE, 0, &fnum1, NULL);
5748 if (NT_STATUS_IS_OK(status)) {
5749 printf("[9] open of %s succeeded should have failed!\n", fname);
5753 printf("ninth delete on close test succeeded.\n");
5757 status = cli_ntcreate(cli1, fname, 0,
5758 FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
5759 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
5760 FILE_OVERWRITE_IF, FILE_DELETE_ON_CLOSE,
5762 if (!NT_STATUS_IS_OK(status)) {
5763 printf("[10] open of %s failed (%s)\n", fname, nt_errstr(status));
5767 /* This should delete the file. */
5768 status = cli_close(cli1, fnum1);
5769 if (!NT_STATUS_IS_OK(status)) {
5770 printf("[10] close failed (%s)\n", nt_errstr(status));
5774 /* This should fail.. */
5775 status = cli_openx(cli1, fname, O_RDONLY, DENY_NONE, &fnum1);
5776 if (NT_STATUS_IS_OK(status)) {
5777 printf("[10] open of %s succeeded should have been deleted on close !\n", fname);
5781 printf("tenth delete on close test succeeded.\n");
5785 cli_setatr(cli1, fname, 0, 0);
5786 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5788 /* Can we open a read-only file with delete access? */
5790 /* Create a readonly file. */
5791 status = cli_ntcreate(cli1, fname, 0, FILE_READ_DATA|FILE_WRITE_DATA,
5792 FILE_ATTRIBUTE_READONLY, FILE_SHARE_NONE,
5793 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
5794 if (!NT_STATUS_IS_OK(status)) {
5795 printf("[11] open of %s failed (%s)\n", fname, nt_errstr(status));
5799 status = cli_close(cli1, fnum1);
5800 if (!NT_STATUS_IS_OK(status)) {
5801 printf("[11] close failed (%s)\n", nt_errstr(status));
5805 /* Now try open for delete access. */
5806 status = cli_ntcreate(cli1, fname, 0,
5807 FILE_READ_ATTRIBUTES|DELETE_ACCESS,
5809 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5810 FILE_OPEN, 0, 0, &fnum1, NULL);
5811 if (!NT_STATUS_IS_OK(status)) {
5812 printf("[11] open of %s failed: %s\n", fname, nt_errstr(status));
5816 cli_close(cli1, fnum1);
5818 printf("eleventh delete on close test succeeded.\n");
5822 * like test 4 but with initial delete on close
5825 cli_setatr(cli1, fname, 0, 0);
5826 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5828 status = cli_ntcreate(cli1, fname, 0,
5829 FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
5830 FILE_ATTRIBUTE_NORMAL,
5831 FILE_SHARE_READ|FILE_SHARE_WRITE,
5833 FILE_DELETE_ON_CLOSE, 0, &fnum1, NULL);
5834 if (!NT_STATUS_IS_OK(status)) {
5835 printf("[12] open 1 of %s failed (%s)\n", fname, nt_errstr(status));
5839 status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
5840 FILE_ATTRIBUTE_NORMAL,
5841 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5842 FILE_OPEN, 0, 0, &fnum2, NULL);
5843 if (!NT_STATUS_IS_OK(status)) {
5844 printf("[12] open 2 of %s failed(%s).\n", fname, nt_errstr(status));
5848 status = cli_close(cli1, fnum2);
5849 if (!NT_STATUS_IS_OK(status)) {
5850 printf("[12] close 1 failed (%s)\n", nt_errstr(status));
5854 status = cli_nt_delete_on_close(cli1, fnum1, true);
5855 if (!NT_STATUS_IS_OK(status)) {
5856 printf("[12] setting delete_on_close failed (%s)\n", nt_errstr(status));
5860 /* This should fail - no more opens once delete on close set. */
5861 status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
5862 FILE_ATTRIBUTE_NORMAL,
5863 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5864 FILE_OPEN, 0, 0, &fnum2, NULL);
5865 if (NT_STATUS_IS_OK(status)) {
5866 printf("[12] open 3 of %s succeeded - should fail).\n", fname);
5870 status = cli_nt_delete_on_close(cli1, fnum1, false);
5871 if (!NT_STATUS_IS_OK(status)) {
5872 printf("[12] unsetting delete_on_close failed (%s)\n", nt_errstr(status));
5876 status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
5877 FILE_ATTRIBUTE_NORMAL,
5878 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5879 FILE_OPEN, 0, 0, &fnum2, NULL);
5880 if (!NT_STATUS_IS_OK(status)) {
5881 printf("[12] open 4 of %s failed (%s)\n", fname, nt_errstr(status));
5885 status = cli_close(cli1, fnum2);
5886 if (!NT_STATUS_IS_OK(status)) {
5887 printf("[12] close 2 failed (%s)\n", nt_errstr(status));
5891 status = cli_close(cli1, fnum1);
5892 if (!NT_STATUS_IS_OK(status)) {
5893 printf("[12] close 3 failed (%s)\n", nt_errstr(status));
5898 * setting delete on close on the handle does
5899 * not unset the initial delete on close...
5901 status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
5902 FILE_ATTRIBUTE_NORMAL,
5903 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5904 FILE_OPEN, 0, 0, &fnum2, NULL);
5905 if (NT_STATUS_IS_OK(status)) {
5906 printf("[12] open 5 of %s succeeded - should fail).\n", fname);
5908 } else if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
5909 printf("ntcreate returned %s, expected "
5910 "NT_STATUS_OBJECT_NAME_NOT_FOUND\n",
5915 printf("twelfth delete on close test succeeded.\n");
5918 printf("finished delete test\n");
5923 /* FIXME: This will crash if we aborted before cli2 got
5924 * initialized, because these functions don't handle
5925 * uninitialized connections. */
5927 if (fnum1 != (uint16_t)-1) cli_close(cli1, fnum1);
5928 if (fnum2 != (uint16_t)-1) cli_close(cli1, fnum2);
5929 cli_setatr(cli1, fname, 0, 0);
5930 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5932 if (cli1 && !torture_close_connection(cli1)) {
5935 if (cli2 && !torture_close_connection(cli2)) {
5941 struct delete_stream_state {
5945 static void delete_stream_unlinked(struct tevent_req *subreq);
5946 static void delete_stream_closed(struct tevent_req *subreq);
5948 static struct tevent_req *delete_stream_send(
5949 TALLOC_CTX *mem_ctx,
5950 struct tevent_context *ev,
5951 struct cli_state *cli,
5952 const char *base_fname,
5953 uint16_t stream_fnum)
5955 struct tevent_req *req = NULL, *subreq = NULL;
5956 struct delete_stream_state *state = NULL;
5958 req = tevent_req_create(
5959 mem_ctx, &state, struct delete_stream_state);
5964 subreq = cli_unlink_send(
5969 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5970 if (tevent_req_nomem(subreq, req)) {
5971 return tevent_req_post(req, ev);
5973 tevent_req_set_callback(subreq, delete_stream_unlinked, req);
5975 subreq = cli_close_send(state, ev, cli, stream_fnum, 0);
5976 if (tevent_req_nomem(subreq, req)) {
5977 return tevent_req_post(req, ev);
5979 tevent_req_set_callback(subreq, delete_stream_closed, req);
5984 static void delete_stream_unlinked(struct tevent_req *subreq)
5986 struct tevent_req *req = tevent_req_callback_data(
5987 subreq, struct tevent_req);
5988 struct delete_stream_state *state = tevent_req_data(
5989 req, struct delete_stream_state);
5992 status = cli_unlink_recv(subreq);
5993 TALLOC_FREE(subreq);
5994 if (!NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
5995 printf("cli_unlink returned %s\n",
5997 tevent_req_nterror(req, NT_STATUS_UNSUCCESSFUL);
6000 if (!state->closed) {
6001 /* close reply should have come in first */
6002 printf("Not closed\n");
6003 tevent_req_nterror(req, NT_STATUS_UNSUCCESSFUL);
6006 tevent_req_done(req);
6009 static void delete_stream_closed(struct tevent_req *subreq)
6011 struct tevent_req *req = tevent_req_callback_data(
6012 subreq, struct tevent_req);
6013 struct delete_stream_state *state = tevent_req_data(
6014 req, struct delete_stream_state);
6017 status = cli_close_recv(subreq);
6018 TALLOC_FREE(subreq);
6019 if (tevent_req_nterror(req, status)) {
6022 /* also waiting for the unlink to come back */
6023 state->closed = true;
6026 static NTSTATUS delete_stream_recv(struct tevent_req *req)
6028 return tevent_req_simple_recv_ntstatus(req);
6031 static bool run_delete_stream(int dummy)
6033 struct tevent_context *ev = NULL;
6034 struct tevent_req *req = NULL;
6035 struct cli_state *cli = NULL;
6036 const char fname[] = "delete_stream";
6037 const char fname_stream[] = "delete_stream:Zone.Identifier:$DATA";
6038 uint16_t fnum1, fnum2;
6042 printf("Starting stream delete test\n");
6044 ok = torture_open_connection(&cli, 0);
6049 cli_setatr(cli, fname, 0, 0);
6050 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6052 /* Create the file. */
6053 status = cli_ntcreate(
6057 READ_CONTROL_ACCESS,
6059 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6065 if (!NT_STATUS_IS_OK(status)) {
6067 "cli_ntcreate of %s failed (%s)\n",
6072 status = cli_close(cli, fnum1);
6073 if (!NT_STATUS_IS_OK(status)) {
6075 "cli_close of %s failed (%s)\n",
6081 /* Now create the stream. */
6082 status = cli_ntcreate(
6088 FILE_SHARE_READ|FILE_SHARE_WRITE,
6095 if (!NT_STATUS_IS_OK(status)) {
6097 "cli_ntcreate of %s failed (%s)\n",
6103 /* open it a second time */
6105 status = cli_ntcreate(
6111 FILE_SHARE_READ|FILE_SHARE_WRITE,
6118 if (!NT_STATUS_IS_OK(status)) {
6120 "2nd cli_ntcreate of %s failed (%s)\n",
6126 ev = samba_tevent_context_init(talloc_tos());
6128 d_fprintf(stderr, "samba_tevent_context_init failed\n");
6132 req = delete_stream_send(ev, ev, cli, fname, fnum1);
6134 d_fprintf(stderr, "delete_stream_send failed\n");
6138 ok = tevent_req_poll_ntstatus(req, ev, &status);
6141 "tevent_req_poll_ntstatus failed: %s\n",
6146 status = delete_stream_recv(req);
6148 if (!NT_STATUS_IS_OK(status)) {
6150 "delete_stream failed: %s\n",
6155 status = cli_close(cli, fnum2);
6156 if (!NT_STATUS_IS_OK(status)) {
6158 "close failed: %s\n",
6163 status = cli_unlink(
6164 cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6165 if (!NT_STATUS_IS_OK(status)) {
6167 "unlink failed: %s\n",
6176 Exercise delete on close semantics - use on the PRINT1 share in torture
6179 static bool run_delete_print_test(int dummy)
6181 struct cli_state *cli1 = NULL;
6182 const char *fname = "print_delete.file";
6183 uint16_t fnum1 = (uint16_t)-1;
6184 bool correct = false;
6185 const char *buf = "print file data\n";
6188 printf("starting print delete test\n");
6190 if (!torture_open_connection(&cli1, 0)) {
6194 smbXcli_conn_set_sockopt(cli1->conn, sockops);
6196 status = cli_ntcreate(cli1, fname, 0, GENERIC_ALL_ACCESS|DELETE_ACCESS,
6197 FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
6198 0, 0, &fnum1, NULL);
6199 if (!NT_STATUS_IS_OK(status)) {
6200 printf("open of %s failed (%s)\n",
6206 status = cli_writeall(cli1,
6209 (const uint8_t *)buf,
6211 strlen(buf), /* size */
6213 if (!NT_STATUS_IS_OK(status)) {
6214 printf("writing print file data failed (%s)\n",
6219 status = cli_nt_delete_on_close(cli1, fnum1, true);
6220 if (!NT_STATUS_IS_OK(status)) {
6221 printf("setting delete_on_close failed (%s)\n",
6226 status = cli_close(cli1, fnum1);
6227 if (!NT_STATUS_IS_OK(status)) {
6228 printf("close failed (%s)\n", nt_errstr(status));
6232 printf("finished print delete test\n");
6238 if (fnum1 != (uint16_t)-1) {
6239 cli_close(cli1, fnum1);
6242 if (cli1 && !torture_close_connection(cli1)) {
6248 static bool run_deletetest_ln(int dummy)
6250 struct cli_state *cli;
6251 const char *fname = "\\delete1";
6252 const char *fname_ln = "\\delete1_ln";
6256 bool correct = true;
6259 printf("starting deletetest-ln\n");
6261 if (!torture_open_connection(&cli, 0)) {
6265 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6266 cli_unlink(cli, fname_ln, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6268 smbXcli_conn_set_sockopt(cli->conn, sockops);
6270 /* Create the file. */
6271 status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
6272 if (!NT_STATUS_IS_OK(status)) {
6273 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
6277 status = cli_close(cli, fnum);
6278 if (!NT_STATUS_IS_OK(status)) {
6279 printf("close1 failed (%s)\n", nt_errstr(status));
6283 /* Now create a hardlink. */
6284 status = cli_hardlink(cli, fname, fname_ln);
6285 if (!NT_STATUS_IS_OK(status)) {
6286 printf("nt hardlink failed (%s)\n", nt_errstr(status));
6290 /* Open the original file. */
6291 status = cli_ntcreate(cli, fname, 0, FILE_READ_DATA,
6292 FILE_ATTRIBUTE_NORMAL,
6293 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6294 FILE_OPEN_IF, 0, 0, &fnum, NULL);
6295 if (!NT_STATUS_IS_OK(status)) {
6296 printf("ntcreate of %s failed (%s)\n", fname, nt_errstr(status));
6300 /* Unlink the hard link path. */
6301 status = cli_ntcreate(cli, fname_ln, 0, DELETE_ACCESS,
6302 FILE_ATTRIBUTE_NORMAL,
6303 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6304 FILE_OPEN_IF, 0, 0, &fnum1, NULL);
6305 if (!NT_STATUS_IS_OK(status)) {
6306 printf("ntcreate of %s failed (%s)\n", fname_ln, nt_errstr(status));
6309 status = cli_nt_delete_on_close(cli, fnum1, true);
6310 if (!NT_STATUS_IS_OK(status)) {
6311 d_printf("(%s) failed to set delete_on_close %s: %s\n",
6312 __location__, fname_ln, nt_errstr(status));
6316 status = cli_close(cli, fnum1);
6317 if (!NT_STATUS_IS_OK(status)) {
6318 printf("close %s failed (%s)\n",
6319 fname_ln, nt_errstr(status));
6323 status = cli_close(cli, fnum);
6324 if (!NT_STATUS_IS_OK(status)) {
6325 printf("close %s failed (%s)\n",
6326 fname, nt_errstr(status));
6330 /* Ensure the original file is still there. */
6331 status = cli_getatr(cli, fname, NULL, NULL, &t);
6332 if (!NT_STATUS_IS_OK(status)) {
6333 printf("%s getatr on file %s failed (%s)\n",
6340 /* Ensure the link path is gone. */
6341 status = cli_getatr(cli, fname_ln, NULL, NULL, &t);
6342 if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
6343 printf("%s, getatr for file %s returned wrong error code %s "
6344 "- should have been deleted\n",
6346 fname_ln, nt_errstr(status));
6350 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6351 cli_unlink(cli, fname_ln, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6353 if (!torture_close_connection(cli)) {
6357 printf("finished deletetest-ln\n");
6363 print out server properties
6365 static bool run_properties(int dummy)
6367 struct cli_state *cli;
6368 bool correct = True;
6370 printf("starting properties test\n");
6374 if (!torture_open_connection(&cli, 0)) {
6378 smbXcli_conn_set_sockopt(cli->conn, sockops);
6380 d_printf("Capabilities 0x%08x\n", smb1cli_conn_capabilities(cli->conn));
6382 if (!torture_close_connection(cli)) {
6391 /* FIRST_DESIRED_ACCESS 0xf019f */
6392 #define FIRST_DESIRED_ACCESS FILE_READ_DATA|FILE_WRITE_DATA|FILE_APPEND_DATA|\
6393 FILE_READ_EA| /* 0xf */ \
6394 FILE_WRITE_EA|FILE_READ_ATTRIBUTES| /* 0x90 */ \
6395 FILE_WRITE_ATTRIBUTES| /* 0x100 */ \
6396 DELETE_ACCESS|READ_CONTROL_ACCESS|\
6397 WRITE_DAC_ACCESS|WRITE_OWNER_ACCESS /* 0xf0000 */
6398 /* SECOND_DESIRED_ACCESS 0xe0080 */
6399 #define SECOND_DESIRED_ACCESS FILE_READ_ATTRIBUTES| /* 0x80 */ \
6400 READ_CONTROL_ACCESS|WRITE_DAC_ACCESS|\
6401 WRITE_OWNER_ACCESS /* 0xe0000 */
6404 #define THIRD_DESIRED_ACCESS FILE_READ_ATTRIBUTES| /* 0x80 */ \
6405 READ_CONTROL_ACCESS|WRITE_DAC_ACCESS|\
6407 WRITE_OWNER_ACCESS /* */
6411 Test ntcreate calls made by xcopy
6413 static bool run_xcopy(int dummy)
6415 static struct cli_state *cli1;
6416 const char *fname = "\\test.txt";
6417 bool correct = True;
6418 uint16_t fnum1, fnum2;
6421 printf("starting xcopy test\n");
6423 if (!torture_open_connection(&cli1, 0)) {
6427 status = cli_ntcreate(cli1, fname, 0, FIRST_DESIRED_ACCESS,
6428 FILE_ATTRIBUTE_ARCHIVE, FILE_SHARE_NONE,
6429 FILE_OVERWRITE_IF, 0x4044, 0, &fnum1, NULL);
6430 if (!NT_STATUS_IS_OK(status)) {
6431 printf("First open failed - %s\n", nt_errstr(status));
6435 status = cli_ntcreate(cli1, fname, 0, SECOND_DESIRED_ACCESS, 0,
6436 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6437 FILE_OPEN, 0x200000, 0, &fnum2, NULL);
6438 if (!NT_STATUS_IS_OK(status)) {
6439 printf("second open failed - %s\n", nt_errstr(status));
6443 if (!torture_close_connection(cli1)) {
6451 Test rename on files open with share delete and no share delete.
6453 static bool run_rename(int dummy)
6455 static struct cli_state *cli1;
6456 const char *fname = "\\test.txt";
6457 const char *fname1 = "\\test1.txt";
6458 bool correct = True;
6463 printf("starting rename test\n");
6465 if (!torture_open_connection(&cli1, 0)) {
6469 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6470 cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6472 status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
6473 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ,
6474 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
6475 if (!NT_STATUS_IS_OK(status)) {
6476 printf("First open failed - %s\n", nt_errstr(status));
6480 status = cli_rename(cli1, fname, fname1, false);
6481 if (!NT_STATUS_IS_OK(status)) {
6482 printf("First rename failed (SHARE_READ) (this is correct) - %s\n", nt_errstr(status));
6484 printf("First rename succeeded (SHARE_READ) - this should have failed !\n");
6488 status = cli_close(cli1, fnum1);
6489 if (!NT_STATUS_IS_OK(status)) {
6490 printf("close - 1 failed (%s)\n", nt_errstr(status));
6494 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6495 cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6496 status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS, FILE_ATTRIBUTE_NORMAL,
6498 FILE_SHARE_DELETE|FILE_SHARE_NONE,
6500 FILE_SHARE_DELETE|FILE_SHARE_READ,
6502 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
6503 if (!NT_STATUS_IS_OK(status)) {
6504 printf("Second open failed - %s\n", nt_errstr(status));
6508 status = cli_rename(cli1, fname, fname1, false);
6509 if (!NT_STATUS_IS_OK(status)) {
6510 printf("Second rename failed (SHARE_DELETE | SHARE_READ) - this should have succeeded - %s\n", nt_errstr(status));
6513 printf("Second rename succeeded (SHARE_DELETE | SHARE_READ)\n");
6516 status = cli_close(cli1, fnum1);
6517 if (!NT_STATUS_IS_OK(status)) {
6518 printf("close - 2 failed (%s)\n", nt_errstr(status));
6522 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6523 cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6525 status = cli_ntcreate(cli1, fname, 0, READ_CONTROL_ACCESS,
6526 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
6527 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
6528 if (!NT_STATUS_IS_OK(status)) {
6529 printf("Third open failed - %s\n", nt_errstr(status));
6534 status = cli_rename(cli1, fname, fname1, false);
6535 if (!NT_STATUS_IS_OK(status)) {
6536 printf("Third rename failed (SHARE_NONE) - this should have succeeded - %s\n", nt_errstr(status));
6539 printf("Third rename succeeded (SHARE_NONE)\n");
6542 status = cli_close(cli1, fnum1);
6543 if (!NT_STATUS_IS_OK(status)) {
6544 printf("close - 3 failed (%s)\n", nt_errstr(status));
6548 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6549 cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6553 status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
6554 FILE_ATTRIBUTE_NORMAL,
6555 FILE_SHARE_READ | FILE_SHARE_WRITE,
6556 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
6557 if (!NT_STATUS_IS_OK(status)) {
6558 printf("Fourth open failed - %s\n", nt_errstr(status));
6562 status = cli_rename(cli1, fname, fname1, false);
6563 if (!NT_STATUS_IS_OK(status)) {
6564 printf("Fourth rename failed (SHARE_READ | SHARE_WRITE) (this is correct) - %s\n", nt_errstr(status));
6566 printf("Fourth rename succeeded (SHARE_READ | SHARE_WRITE) - this should have failed !\n");
6570 status = cli_close(cli1, fnum1);
6571 if (!NT_STATUS_IS_OK(status)) {
6572 printf("close - 4 failed (%s)\n", nt_errstr(status));
6576 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6577 cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6581 status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
6582 FILE_ATTRIBUTE_NORMAL,
6583 FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
6584 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
6585 if (!NT_STATUS_IS_OK(status)) {
6586 printf("Fifth open failed - %s\n", nt_errstr(status));
6590 status = cli_rename(cli1, fname, fname1, false);
6591 if (!NT_STATUS_IS_OK(status)) {
6592 printf("Fifth rename failed (SHARE_READ | SHARE_WRITE | SHARE_DELETE) - this should have succeeded - %s ! \n", nt_errstr(status));
6595 printf("Fifth rename succeeded (SHARE_READ | SHARE_WRITE | SHARE_DELETE) (this is correct) - %s\n", nt_errstr(status));
6599 status = cli_close(cli1, fnum1);
6600 if (!NT_STATUS_IS_OK(status)) {
6601 printf("close - 5 failed (%s)\n", nt_errstr(status));
6605 /* Check that the renamed file has FILE_ATTRIBUTE_ARCHIVE. */
6606 status = cli_getatr(cli1, fname1, &attr, NULL, NULL);
6607 if (!NT_STATUS_IS_OK(status)) {
6608 printf("getatr on file %s failed - %s ! \n",
6609 fname1, nt_errstr(status));
6612 if (attr != FILE_ATTRIBUTE_ARCHIVE) {
6613 printf("Renamed file %s has wrong attr 0x%x "
6614 "(should be 0x%x)\n",
6617 (unsigned int)FILE_ATTRIBUTE_ARCHIVE);
6620 printf("Renamed file %s has archive bit set\n", fname1);
6624 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6625 cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6627 if (!torture_close_connection(cli1)) {
6635 Test rename into a directory with an ACL denying it.
6637 static bool run_rename_access(int dummy)
6639 static struct cli_state *cli = NULL;
6640 static struct cli_state *posix_cli = NULL;
6641 const char *src = "test.txt";
6642 const char *dname = "dir";
6643 const char *dst = "dir\\test.txt";
6644 const char *dsrc = "test.dir";
6645 const char *ddst = "dir\\test.dir";
6646 uint16_t fnum = (uint16_t)-1;
6647 struct security_descriptor *sd = NULL;
6648 struct security_descriptor *newsd = NULL;
6650 TALLOC_CTX *frame = NULL;
6652 frame = talloc_stackframe();
6653 printf("starting rename access test\n");
6655 /* Windows connection. */
6656 if (!torture_open_connection(&cli, 0)) {
6660 smbXcli_conn_set_sockopt(cli->conn, sockops);
6662 /* Posix connection. */
6663 if (!torture_open_connection(&posix_cli, 0)) {
6667 smbXcli_conn_set_sockopt(posix_cli->conn, sockops);
6669 status = torture_setup_unix_extensions(posix_cli);
6670 if (!NT_STATUS_IS_OK(status)) {
6674 /* Start with a clean slate. */
6675 cli_unlink(cli, src, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6676 cli_unlink(cli, dst, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6677 cli_rmdir(cli, dsrc);
6678 cli_rmdir(cli, ddst);
6679 cli_rmdir(cli, dname);
6682 * Setup the destination directory with a DENY ACE to
6683 * prevent new files within it.
6685 status = cli_ntcreate(cli,
6688 FILE_READ_ATTRIBUTES|READ_CONTROL_ACCESS|
6689 WRITE_DAC_ACCESS|FILE_READ_DATA|
6691 FILE_ATTRIBUTE_DIRECTORY,
6692 FILE_SHARE_READ|FILE_SHARE_WRITE,
6694 FILE_DIRECTORY_FILE,
6698 if (!NT_STATUS_IS_OK(status)) {
6699 printf("Create of %s - %s\n", dname, nt_errstr(status));
6703 status = cli_query_secdesc(cli,
6707 if (!NT_STATUS_IS_OK(status)) {
6708 printf("cli_query_secdesc failed for %s (%s)\n",
6709 dname, nt_errstr(status));
6713 newsd = security_descriptor_dacl_create(frame,
6718 SEC_ACE_TYPE_ACCESS_DENIED,
6719 SEC_DIR_ADD_FILE|SEC_DIR_ADD_SUBDIR,
6722 if (newsd == NULL) {
6725 sd->dacl = security_acl_concatenate(frame,
6728 if (sd->dacl == NULL) {
6731 status = cli_set_secdesc(cli, fnum, sd);
6732 if (!NT_STATUS_IS_OK(status)) {
6733 printf("cli_set_secdesc failed for %s (%s)\n",
6734 dname, nt_errstr(status));
6737 status = cli_close(cli, fnum);
6738 if (!NT_STATUS_IS_OK(status)) {
6739 printf("close failed for %s (%s)\n",
6740 dname, nt_errstr(status));
6743 /* Now go around the back and chmod to 777 via POSIX. */
6744 status = cli_posix_chmod(posix_cli, dname, 0777);
6745 if (!NT_STATUS_IS_OK(status)) {
6746 printf("cli_posix_chmod failed for %s (%s)\n",
6747 dname, nt_errstr(status));
6751 /* Check we can't create a file within dname via Windows. */
6752 status = cli_openx(cli, dst, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
6753 if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
6754 cli_close(posix_cli, fnum);
6755 printf("Create of %s should be ACCESS denied, was %s\n",
6756 dst, nt_errstr(status));
6760 /* Make the sample file/directory. */
6761 status = cli_openx(cli, src, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
6762 if (!NT_STATUS_IS_OK(status)) {
6763 printf("open of %s failed (%s)\n", src, nt_errstr(status));
6766 status = cli_close(cli, fnum);
6767 if (!NT_STATUS_IS_OK(status)) {
6768 printf("cli_close failed (%s)\n", nt_errstr(status));
6772 status = cli_mkdir(cli, dsrc);
6773 if (!NT_STATUS_IS_OK(status)) {
6774 printf("cli_mkdir of %s failed (%s)\n",
6775 dsrc, nt_errstr(status));
6780 * OK - renames of the new file and directory into the
6781 * dst directory should fail.
6784 status = cli_rename(cli, src, dst, false);
6785 if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
6786 printf("rename of %s -> %s should be ACCESS denied, was %s\n",
6787 src, dst, nt_errstr(status));
6790 status = cli_rename(cli, dsrc, ddst, false);
6791 if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
6792 printf("rename of %s -> %s should be ACCESS denied, was %s\n",
6793 src, dst, nt_errstr(status));
6803 torture_close_connection(posix_cli);
6807 if (fnum != (uint16_t)-1) {
6808 cli_close(cli, fnum);
6810 cli_unlink(cli, src,
6811 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6812 cli_unlink(cli, dst,
6813 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6814 cli_rmdir(cli, dsrc);
6815 cli_rmdir(cli, ddst);
6816 cli_rmdir(cli, dname);
6818 torture_close_connection(cli);
6826 Test owner rights ACE.
6828 static bool run_owner_rights(int dummy)
6830 static struct cli_state *cli = NULL;
6831 const char *fname = "owner_rights.txt";
6832 uint16_t fnum = (uint16_t)-1;
6833 struct security_descriptor *sd = NULL;
6834 struct security_descriptor *newsd = NULL;
6836 TALLOC_CTX *frame = NULL;
6838 frame = talloc_stackframe();
6839 printf("starting owner rights test\n");
6841 /* Windows connection. */
6842 if (!torture_open_connection(&cli, 0)) {
6846 smbXcli_conn_set_sockopt(cli->conn, sockops);
6848 /* Start with a clean slate. */
6849 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6851 /* Create the test file. */
6852 /* Now try and open for read and write-dac. */
6853 status = cli_ntcreate(cli,
6857 FILE_ATTRIBUTE_NORMAL,
6858 FILE_SHARE_READ|FILE_SHARE_WRITE|
6865 if (!NT_STATUS_IS_OK(status)) {
6866 printf("Create of %s - %s\n", fname, nt_errstr(status));
6870 /* Get the original SD. */
6871 status = cli_query_secdesc(cli,
6875 if (!NT_STATUS_IS_OK(status)) {
6876 printf("cli_query_secdesc failed for %s (%s)\n",
6877 fname, nt_errstr(status));
6882 * Add an "owner-rights" ACE denying WRITE_DATA,
6883 * and an "owner-rights" ACE allowing READ_DATA.
6886 newsd = security_descriptor_dacl_create(frame,
6891 SEC_ACE_TYPE_ACCESS_DENIED,
6895 SEC_ACE_TYPE_ACCESS_ALLOWED,
6899 if (newsd == NULL) {
6902 sd->dacl = security_acl_concatenate(frame,
6905 if (sd->dacl == NULL) {
6908 status = cli_set_secdesc(cli, fnum, sd);
6909 if (!NT_STATUS_IS_OK(status)) {
6910 printf("cli_set_secdesc failed for %s (%s)\n",
6911 fname, nt_errstr(status));
6914 status = cli_close(cli, fnum);
6915 if (!NT_STATUS_IS_OK(status)) {
6916 printf("close failed for %s (%s)\n",
6917 fname, nt_errstr(status));
6920 fnum = (uint16_t)-1;
6922 /* Try and open for FILE_WRITE_DATA */
6923 status = cli_ntcreate(cli,
6927 FILE_ATTRIBUTE_NORMAL,
6928 FILE_SHARE_READ|FILE_SHARE_WRITE|
6935 if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
6936 printf("Open of %s - %s\n", fname, nt_errstr(status));
6940 /* Now try and open for FILE_READ_DATA */
6941 status = cli_ntcreate(cli,
6945 FILE_ATTRIBUTE_NORMAL,
6946 FILE_SHARE_READ|FILE_SHARE_WRITE|
6953 if (!NT_STATUS_IS_OK(status)) {
6954 printf("Open of %s - %s\n", fname, nt_errstr(status));
6958 status = cli_close(cli, fnum);
6959 if (!NT_STATUS_IS_OK(status)) {
6960 printf("close failed for %s (%s)\n",
6961 fname, nt_errstr(status));
6965 /* Restore clean slate. */
6967 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6969 /* Create the test file. */
6970 status = cli_ntcreate(cli,
6974 FILE_ATTRIBUTE_NORMAL,
6975 FILE_SHARE_READ|FILE_SHARE_WRITE|
6982 if (!NT_STATUS_IS_OK(status)) {
6983 printf("Create of %s - %s\n", fname, nt_errstr(status));
6987 /* Get the original SD. */
6988 status = cli_query_secdesc(cli,
6992 if (!NT_STATUS_IS_OK(status)) {
6993 printf("cli_query_secdesc failed for %s (%s)\n",
6994 fname, nt_errstr(status));
6999 * Add an "owner-rights ACE denying WRITE_DATA,
7000 * and an "owner-rights ACE allowing READ_DATA|WRITE_DATA.
7003 newsd = security_descriptor_dacl_create(frame,
7008 SEC_ACE_TYPE_ACCESS_DENIED,
7012 SEC_ACE_TYPE_ACCESS_ALLOWED,
7013 FILE_READ_DATA|FILE_WRITE_DATA,
7016 if (newsd == NULL) {
7019 sd->dacl = security_acl_concatenate(frame,
7022 if (sd->dacl == NULL) {
7025 status = cli_set_secdesc(cli, fnum, sd);
7026 if (!NT_STATUS_IS_OK(status)) {
7027 printf("cli_set_secdesc failed for %s (%s)\n",
7028 fname, nt_errstr(status));
7031 status = cli_close(cli, fnum);
7032 if (!NT_STATUS_IS_OK(status)) {
7033 printf("close failed for %s (%s)\n",
7034 fname, nt_errstr(status));
7037 fnum = (uint16_t)-1;
7039 /* Try and open for FILE_WRITE_DATA */
7040 status = cli_ntcreate(cli,
7044 FILE_ATTRIBUTE_NORMAL,
7045 FILE_SHARE_READ|FILE_SHARE_WRITE|
7052 if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
7053 printf("Open of %s - %s\n", fname, nt_errstr(status));
7057 /* Now try and open for FILE_READ_DATA */
7058 status = cli_ntcreate(cli,
7062 FILE_ATTRIBUTE_NORMAL,
7063 FILE_SHARE_READ|FILE_SHARE_WRITE|
7070 if (!NT_STATUS_IS_OK(status)) {
7071 printf("Open of %s - %s\n", fname, nt_errstr(status));
7075 status = cli_close(cli, fnum);
7076 if (!NT_STATUS_IS_OK(status)) {
7077 printf("close failed for %s (%s)\n",
7078 fname, nt_errstr(status));
7082 /* Restore clean slate. */
7084 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7087 /* Create the test file. */
7088 status = cli_ntcreate(cli,
7092 FILE_ATTRIBUTE_NORMAL,
7093 FILE_SHARE_READ|FILE_SHARE_WRITE|
7100 if (!NT_STATUS_IS_OK(status)) {
7101 printf("Create of %s - %s\n", fname, nt_errstr(status));
7105 /* Get the original SD. */
7106 status = cli_query_secdesc(cli,
7110 if (!NT_STATUS_IS_OK(status)) {
7111 printf("cli_query_secdesc failed for %s (%s)\n",
7112 fname, nt_errstr(status));
7117 * Add an "authenticated users" ACE allowing READ_DATA,
7118 * add an "owner-rights" denying READ_DATA,
7119 * and an "authenticated users" ACE allowing WRITE_DATA.
7122 newsd = security_descriptor_dacl_create(frame,
7126 SID_NT_AUTHENTICATED_USERS,
7127 SEC_ACE_TYPE_ACCESS_ALLOWED,
7131 SEC_ACE_TYPE_ACCESS_DENIED,
7134 SID_NT_AUTHENTICATED_USERS,
7135 SEC_ACE_TYPE_ACCESS_ALLOWED,
7139 if (newsd == NULL) {
7140 printf("newsd == NULL\n");
7143 sd->dacl = security_acl_concatenate(frame,
7146 if (sd->dacl == NULL) {
7147 printf("sd->dacl == NULL\n");
7150 status = cli_set_secdesc(cli, fnum, sd);
7151 if (!NT_STATUS_IS_OK(status)) {
7152 printf("cli_set_secdesc failed for %s (%s)\n",
7153 fname, nt_errstr(status));
7156 status = cli_close(cli, fnum);
7157 if (!NT_STATUS_IS_OK(status)) {
7158 printf("close failed for %s (%s)\n",
7159 fname, nt_errstr(status));
7162 fnum = (uint16_t)-1;
7164 /* Now try and open for FILE_READ_DATA|FILE_WRITE_DATA */
7165 status = cli_ntcreate(cli,
7168 FILE_READ_DATA|FILE_WRITE_DATA,
7169 FILE_ATTRIBUTE_NORMAL,
7170 FILE_SHARE_READ|FILE_SHARE_WRITE|
7177 if (!NT_STATUS_IS_OK(status)) {
7178 printf("Open of %s - %s\n", fname, nt_errstr(status));
7182 status = cli_close(cli, fnum);
7183 if (!NT_STATUS_IS_OK(status)) {
7184 printf("close failed for %s (%s)\n",
7185 fname, nt_errstr(status));
7189 cli_unlink(cli, fname,
7190 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7198 if (fnum != (uint16_t)-1) {
7199 cli_close(cli, fnum);
7201 cli_unlink(cli, fname,
7202 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7203 torture_close_connection(cli);
7211 * Test SMB1-specific open with SEC_FLAG_SYSTEM_SECURITY.
7212 * Note this test only works with a user with SeSecurityPrivilege set.
7214 * NB. This is also tested in samba3.base.createx_access
7215 * but this makes it very explicit what we're looking for.
7217 static bool run_smb1_system_security(int dummy)
7219 static struct cli_state *cli = NULL;
7220 const char *fname = "system_security.txt";
7221 uint16_t fnum = (uint16_t)-1;
7223 TALLOC_CTX *frame = NULL;
7225 frame = talloc_stackframe();
7226 printf("starting smb1 system security test\n");
7228 /* SMB1 connection - torture_open_connection() forces this. */
7229 if (!torture_open_connection(&cli, 0)) {
7233 smbXcli_conn_set_sockopt(cli->conn, sockops);
7235 /* Start with a clean slate. */
7236 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7238 /* Create the test file. */
7239 status = cli_ntcreate(cli,
7243 FILE_ATTRIBUTE_NORMAL,
7244 FILE_SHARE_READ|FILE_SHARE_WRITE|
7251 if (!NT_STATUS_IS_OK(status)) {
7252 printf("Create of %s - %s\n", fname, nt_errstr(status));
7256 status = cli_close(cli, fnum);
7258 /* Open with SEC_FLAG_SYSTEM_SECURITY only. */
7260 * On SMB1 this succeeds - SMB2 it fails,
7261 * see the SMB2-SACL test.
7263 status = cli_ntcreate(cli,
7266 SEC_FLAG_SYSTEM_SECURITY,
7267 FILE_ATTRIBUTE_NORMAL,
7268 FILE_SHARE_READ|FILE_SHARE_WRITE|
7275 if (!NT_STATUS_IS_OK(status)) {
7276 printf("Open of %s - %s\n", fname, nt_errstr(status));
7280 status = cli_close(cli, fnum);
7282 cli_unlink(cli, fname,
7283 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7285 torture_close_connection(cli);
7292 if (fnum != (uint16_t)-1) {
7293 cli_close(cli, fnum);
7295 cli_unlink(cli, fname,
7296 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7297 torture_close_connection(cli);
7304 static bool run_pipe_number(int dummy)
7306 struct cli_state *cli1;
7307 const char *pipe_name = "\\SPOOLSS";
7312 printf("starting pipenumber test\n");
7313 if (!torture_open_connection(&cli1, 0)) {
7317 smbXcli_conn_set_sockopt(cli1->conn, sockops);
7319 status = cli_ntcreate(cli1, pipe_name, 0, FILE_READ_DATA,
7320 FILE_ATTRIBUTE_NORMAL,
7321 FILE_SHARE_READ|FILE_SHARE_WRITE,
7322 FILE_OPEN_IF, 0, 0, &fnum, NULL);
7323 if (!NT_STATUS_IS_OK(status)) {
7324 printf("Open of pipe %s failed with error (%s)\n", pipe_name, nt_errstr(status));
7328 printf("\r%6d", num_pipes);
7331 printf("pipe_number test - we can open %d %s pipes.\n", num_pipes, pipe_name );
7332 torture_close_connection(cli1);
7337 Test open mode returns on read-only files.
7339 static bool run_opentest(int dummy)
7341 static struct cli_state *cli1;
7342 static struct cli_state *cli2;
7343 const char *fname = "\\readonly.file";
7344 uint16_t fnum1, fnum2;
7347 bool correct = True;
7351 printf("starting open test\n");
7353 if (!torture_open_connection(&cli1, 0)) {
7357 cli_setatr(cli1, fname, 0, 0);
7358 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7360 smbXcli_conn_set_sockopt(cli1->conn, sockops);
7362 status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
7363 if (!NT_STATUS_IS_OK(status)) {
7364 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
7368 status = cli_close(cli1, fnum1);
7369 if (!NT_STATUS_IS_OK(status)) {
7370 printf("close2 failed (%s)\n", nt_errstr(status));
7374 status = cli_setatr(cli1, fname, FILE_ATTRIBUTE_READONLY, 0);
7375 if (!NT_STATUS_IS_OK(status)) {
7376 printf("cli_setatr failed (%s)\n", nt_errstr(status));
7380 status = cli_openx(cli1, fname, O_RDONLY, DENY_WRITE, &fnum1);
7381 if (!NT_STATUS_IS_OK(status)) {
7382 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
7386 /* This will fail - but the error should be ERRnoaccess, not ERRbadshare. */
7387 status = cli_openx(cli1, fname, O_RDWR, DENY_ALL, &fnum2);
7389 if (check_error(__LINE__, status, ERRDOS, ERRnoaccess,
7390 NT_STATUS_ACCESS_DENIED)) {
7391 printf("correct error code ERRDOS/ERRnoaccess returned\n");
7394 printf("finished open test 1\n");
7396 cli_close(cli1, fnum1);
7398 /* Now try not readonly and ensure ERRbadshare is returned. */
7400 cli_setatr(cli1, fname, 0, 0);
7402 status = cli_openx(cli1, fname, O_RDONLY, DENY_WRITE, &fnum1);
7403 if (!NT_STATUS_IS_OK(status)) {
7404 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
7408 /* This will fail - but the error should be ERRshare. */
7409 status = cli_openx(cli1, fname, O_RDWR, DENY_ALL, &fnum2);
7411 if (check_error(__LINE__, status, ERRDOS, ERRbadshare,
7412 NT_STATUS_SHARING_VIOLATION)) {
7413 printf("correct error code ERRDOS/ERRbadshare returned\n");
7416 status = cli_close(cli1, fnum1);
7417 if (!NT_STATUS_IS_OK(status)) {
7418 printf("close2 failed (%s)\n", nt_errstr(status));
7422 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7424 printf("finished open test 2\n");
7426 /* Test truncate open disposition on file opened for read. */
7427 status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
7428 if (!NT_STATUS_IS_OK(status)) {
7429 printf("(3) open (1) of %s failed (%s)\n", fname, nt_errstr(status));
7433 /* write 20 bytes. */
7435 memset(buf, '\0', 20);
7437 status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 0, 20, NULL);
7438 if (!NT_STATUS_IS_OK(status)) {
7439 printf("write failed (%s)\n", nt_errstr(status));
7443 status = cli_close(cli1, fnum1);
7444 if (!NT_STATUS_IS_OK(status)) {
7445 printf("(3) close1 failed (%s)\n", nt_errstr(status));
7449 /* Ensure size == 20. */
7450 status = cli_getatr(cli1, fname, NULL, &fsize, NULL);
7451 if (!NT_STATUS_IS_OK(status)) {
7452 printf("(3) getatr failed (%s)\n", nt_errstr(status));
7457 printf("(3) file size != 20\n");
7461 /* Now test if we can truncate a file opened for readonly. */
7462 status = cli_openx(cli1, fname, O_RDONLY|O_TRUNC, DENY_NONE, &fnum1);
7463 if (!NT_STATUS_IS_OK(status)) {
7464 printf("(3) open (2) of %s failed (%s)\n", fname, nt_errstr(status));
7468 status = cli_close(cli1, fnum1);
7469 if (!NT_STATUS_IS_OK(status)) {
7470 printf("close2 failed (%s)\n", nt_errstr(status));
7474 /* Ensure size == 0. */
7475 status = cli_getatr(cli1, fname, NULL, &fsize, NULL);
7476 if (!NT_STATUS_IS_OK(status)) {
7477 printf("(3) getatr failed (%s)\n", nt_errstr(status));
7482 printf("(3) file size != 0\n");
7485 printf("finished open test 3\n");
7487 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7489 printf("Do ctemp tests\n");
7490 status = cli_ctemp(cli1, talloc_tos(), "\\", &fnum1, &tmp_path);
7491 if (!NT_STATUS_IS_OK(status)) {
7492 printf("ctemp failed (%s)\n", nt_errstr(status));
7496 printf("ctemp gave path %s\n", tmp_path);
7497 status = cli_close(cli1, fnum1);
7498 if (!NT_STATUS_IS_OK(status)) {
7499 printf("close of temp failed (%s)\n", nt_errstr(status));
7502 status = cli_unlink(cli1, tmp_path, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7503 if (!NT_STATUS_IS_OK(status)) {
7504 printf("unlink of temp failed (%s)\n", nt_errstr(status));
7507 /* Test the non-io opens... */
7509 if (!torture_open_connection(&cli2, 1)) {
7513 cli_setatr(cli2, fname, 0, 0);
7514 cli_unlink(cli2, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7516 smbXcli_conn_set_sockopt(cli2->conn, sockops);
7518 printf("TEST #1 testing 2 non-io opens (no delete)\n");
7519 status = cli_ntcreate(cli1, fname, 0, FILE_READ_ATTRIBUTES,
7520 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7521 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
7522 if (!NT_STATUS_IS_OK(status)) {
7523 printf("TEST #1 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
7527 status = cli_ntcreate(cli2, fname, 0, FILE_READ_ATTRIBUTES,
7528 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7529 FILE_OPEN_IF, 0, 0, &fnum2, NULL);
7530 if (!NT_STATUS_IS_OK(status)) {
7531 printf("TEST #1 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
7535 status = cli_close(cli1, fnum1);
7536 if (!NT_STATUS_IS_OK(status)) {
7537 printf("TEST #1 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
7541 status = cli_close(cli2, fnum2);
7542 if (!NT_STATUS_IS_OK(status)) {
7543 printf("TEST #1 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
7547 printf("non-io open test #1 passed.\n");
7549 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7551 printf("TEST #2 testing 2 non-io opens (first with delete)\n");
7553 status = cli_ntcreate(cli1, fname, 0,
7554 DELETE_ACCESS|FILE_READ_ATTRIBUTES,
7555 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7556 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
7557 if (!NT_STATUS_IS_OK(status)) {
7558 printf("TEST #2 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
7562 status = cli_ntcreate(cli2, fname, 0, FILE_READ_ATTRIBUTES,
7563 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7564 FILE_OPEN_IF, 0, 0, &fnum2, NULL);
7565 if (!NT_STATUS_IS_OK(status)) {
7566 printf("TEST #2 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
7570 status = cli_close(cli1, fnum1);
7571 if (!NT_STATUS_IS_OK(status)) {
7572 printf("TEST #2 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
7576 status = cli_close(cli2, fnum2);
7577 if (!NT_STATUS_IS_OK(status)) {
7578 printf("TEST #2 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
7582 printf("non-io open test #2 passed.\n");
7584 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7586 printf("TEST #3 testing 2 non-io opens (second with delete)\n");
7588 status = cli_ntcreate(cli1, fname, 0, FILE_READ_ATTRIBUTES,
7589 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7590 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
7591 if (!NT_STATUS_IS_OK(status)) {
7592 printf("TEST #3 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
7596 status = cli_ntcreate(cli2, fname, 0,
7597 DELETE_ACCESS|FILE_READ_ATTRIBUTES,
7598 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7599 FILE_OPEN_IF, 0, 0, &fnum2, NULL);
7600 if (!NT_STATUS_IS_OK(status)) {
7601 printf("TEST #3 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
7605 status = cli_close(cli1, fnum1);
7606 if (!NT_STATUS_IS_OK(status)) {
7607 printf("TEST #3 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
7611 status = cli_close(cli2, fnum2);
7612 if (!NT_STATUS_IS_OK(status)) {
7613 printf("TEST #3 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
7617 printf("non-io open test #3 passed.\n");
7619 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7621 printf("TEST #4 testing 2 non-io opens (both with delete)\n");
7623 status = cli_ntcreate(cli1, fname, 0,
7624 DELETE_ACCESS|FILE_READ_ATTRIBUTES,
7625 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7626 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
7627 if (!NT_STATUS_IS_OK(status)) {
7628 printf("TEST #4 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
7632 status = cli_ntcreate(cli2, fname, 0,
7633 DELETE_ACCESS|FILE_READ_ATTRIBUTES,
7634 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7635 FILE_OPEN_IF, 0, 0, &fnum2, NULL);
7636 if (NT_STATUS_IS_OK(status)) {
7637 printf("TEST #4 open 2 of %s SUCCEEDED - should have failed (%s)\n", fname, nt_errstr(status));
7641 printf("TEST #4 open 2 of %s gave %s (correct error should be %s)\n", fname, nt_errstr(status), "sharing violation");
7643 status = cli_close(cli1, fnum1);
7644 if (!NT_STATUS_IS_OK(status)) {
7645 printf("TEST #4 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
7649 printf("non-io open test #4 passed.\n");
7651 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7653 printf("TEST #5 testing 2 non-io opens (both with delete - both with file share delete)\n");
7655 status = cli_ntcreate(cli1, fname, 0,
7656 DELETE_ACCESS|FILE_READ_ATTRIBUTES,
7657 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_DELETE,
7658 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
7659 if (!NT_STATUS_IS_OK(status)) {
7660 printf("TEST #5 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
7664 status = cli_ntcreate(cli2, fname, 0,
7665 DELETE_ACCESS|FILE_READ_ATTRIBUTES,
7666 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_DELETE,
7667 FILE_OPEN_IF, 0, 0, &fnum2, NULL);
7668 if (!NT_STATUS_IS_OK(status)) {
7669 printf("TEST #5 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
7673 status = cli_close(cli1, fnum1);
7674 if (!NT_STATUS_IS_OK(status)) {
7675 printf("TEST #5 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
7679 status = cli_close(cli2, fnum2);
7680 if (!NT_STATUS_IS_OK(status)) {
7681 printf("TEST #5 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
7685 printf("non-io open test #5 passed.\n");
7687 printf("TEST #6 testing 1 non-io open, one io open\n");
7689 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7691 status = cli_ntcreate(cli1, fname, 0, FILE_READ_DATA,
7692 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7693 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
7694 if (!NT_STATUS_IS_OK(status)) {
7695 printf("TEST #6 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
7699 status = cli_ntcreate(cli2, fname, 0, FILE_READ_ATTRIBUTES,
7700 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ,
7701 FILE_OPEN_IF, 0, 0, &fnum2, NULL);
7702 if (!NT_STATUS_IS_OK(status)) {
7703 printf("TEST #6 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
7707 status = cli_close(cli1, fnum1);
7708 if (!NT_STATUS_IS_OK(status)) {
7709 printf("TEST #6 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
7713 status = cli_close(cli2, fnum2);
7714 if (!NT_STATUS_IS_OK(status)) {
7715 printf("TEST #6 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
7719 printf("non-io open test #6 passed.\n");
7721 printf("TEST #7 testing 1 non-io open, one io open with delete\n");
7723 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7725 status = cli_ntcreate(cli1, fname, 0, FILE_READ_DATA,
7726 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7727 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
7728 if (!NT_STATUS_IS_OK(status)) {
7729 printf("TEST #7 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
7733 status = cli_ntcreate(cli2, fname, 0,
7734 DELETE_ACCESS|FILE_READ_ATTRIBUTES,
7735 FILE_ATTRIBUTE_NORMAL,
7736 FILE_SHARE_READ|FILE_SHARE_DELETE,
7737 FILE_OPEN_IF, 0, 0, &fnum2, NULL);
7738 if (NT_STATUS_IS_OK(status)) {
7739 printf("TEST #7 open 2 of %s SUCCEEDED - should have failed (%s)\n", fname, nt_errstr(status));
7743 printf("TEST #7 open 2 of %s gave %s (correct error should be %s)\n", fname, nt_errstr(status), "sharing violation");
7745 status = cli_close(cli1, fnum1);
7746 if (!NT_STATUS_IS_OK(status)) {
7747 printf("TEST #7 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
7751 printf("non-io open test #7 passed.\n");
7753 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7755 printf("TEST #8 testing open without WRITE_ATTRIBUTES, updating close write time.\n");
7756 status = cli_ntcreate(cli1, fname, 0, FILE_WRITE_DATA, FILE_ATTRIBUTE_NORMAL,
7757 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
7758 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
7759 if (!NT_STATUS_IS_OK(status)) {
7760 printf("TEST #8 open of %s failed (%s)\n", fname, nt_errstr(status));
7765 /* Write to ensure we have to update the file time. */
7766 status = cli_writeall(cli1, fnum1, 0, (const uint8_t *)"TEST DATA\n", 0, 10,
7768 if (!NT_STATUS_IS_OK(status)) {
7769 printf("TEST #8 cli_write failed: %s\n", nt_errstr(status));
7774 status = cli_close(cli1, fnum1);
7775 if (!NT_STATUS_IS_OK(status)) {
7776 printf("TEST #8 close of %s failed (%s)\n", fname, nt_errstr(status));
7782 if (!torture_close_connection(cli1)) {
7785 if (!torture_close_connection(cli2)) {
7792 NTSTATUS torture_setup_unix_extensions(struct cli_state *cli)
7794 uint16_t major, minor;
7795 uint32_t caplow, caphigh;
7798 if (!SERVER_HAS_UNIX_CIFS(cli)) {
7799 printf("Server doesn't support UNIX CIFS extensions.\n");
7800 return NT_STATUS_NOT_SUPPORTED;
7803 status = cli_unix_extensions_version(cli, &major, &minor, &caplow,
7805 if (!NT_STATUS_IS_OK(status)) {
7806 printf("Server didn't return UNIX CIFS extensions: %s\n",
7811 status = cli_set_unix_extensions_capabilities(cli, major, minor,
7813 if (!NT_STATUS_IS_OK(status)) {
7814 printf("Server doesn't support setting UNIX CIFS extensions: "
7815 "%s.\n", nt_errstr(status));
7819 return NT_STATUS_OK;
7823 Test POSIX open /mkdir calls.
7825 static bool run_simple_posix_open_test(int dummy)
7827 static struct cli_state *cli1;
7828 const char *fname = "posix:file";
7829 const char *hname = "posix:hlink";
7830 const char *sname = "posix:symlink";
7831 const char *dname = "posix:dir";
7833 char *target = NULL;
7834 uint16_t fnum1 = (uint16_t)-1;
7835 SMB_STRUCT_STAT sbuf;
7836 bool correct = false;
7839 const char *fname_windows = "windows_file";
7840 uint16_t fnum2 = (uint16_t)-1;
7843 printf("Starting simple POSIX open test\n");
7845 if (!torture_open_connection(&cli1, 0)) {
7849 smbXcli_conn_set_sockopt(cli1->conn, sockops);
7851 status = torture_setup_unix_extensions(cli1);
7852 if (!NT_STATUS_IS_OK(status)) {
7856 cli_setatr(cli1, fname, 0, 0);
7857 cli_posix_unlink(cli1, fname);
7858 cli_setatr(cli1, dname, 0, 0);
7859 cli_posix_rmdir(cli1, dname);
7860 cli_setatr(cli1, hname, 0, 0);
7861 cli_posix_unlink(cli1, hname);
7862 cli_setatr(cli1, sname, 0, 0);
7863 cli_posix_unlink(cli1, sname);
7864 cli_setatr(cli1, fname_windows, 0, 0);
7865 cli_posix_unlink(cli1, fname_windows);
7867 /* Create a directory. */
7868 status = cli_posix_mkdir(cli1, dname, 0777);
7869 if (!NT_STATUS_IS_OK(status)) {
7870 printf("POSIX mkdir of %s failed (%s)\n", dname, nt_errstr(status));
7874 status = cli_posix_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL,
7876 if (!NT_STATUS_IS_OK(status)) {
7877 printf("POSIX create of %s failed (%s)\n", fname, nt_errstr(status));
7881 /* Test ftruncate - set file size. */
7882 status = cli_ftruncate(cli1, fnum1, 1000);
7883 if (!NT_STATUS_IS_OK(status)) {
7884 printf("ftruncate failed (%s)\n", nt_errstr(status));
7888 /* Ensure st_size == 1000 */
7889 status = cli_posix_stat(cli1, fname, &sbuf);
7890 if (!NT_STATUS_IS_OK(status)) {
7891 printf("stat failed (%s)\n", nt_errstr(status));
7895 if (sbuf.st_ex_size != 1000) {
7896 printf("ftruncate - stat size (%u) != 1000\n", (unsigned int)sbuf.st_ex_size);
7900 /* Ensure st_mode == 0600 */
7901 if ((sbuf.st_ex_mode & 07777) != 0600) {
7902 printf("posix_open - bad permissions 0%o != 0600\n",
7903 (unsigned int)(sbuf.st_ex_mode & 07777));
7907 /* Test ftruncate - set file size back to zero. */
7908 status = cli_ftruncate(cli1, fnum1, 0);
7909 if (!NT_STATUS_IS_OK(status)) {
7910 printf("ftruncate failed (%s)\n", nt_errstr(status));
7914 status = cli_close(cli1, fnum1);
7915 if (!NT_STATUS_IS_OK(status)) {
7916 printf("close failed (%s)\n", nt_errstr(status));
7920 /* Now open the file again for read only. */
7921 status = cli_posix_open(cli1, fname, O_RDONLY, 0, &fnum1);
7922 if (!NT_STATUS_IS_OK(status)) {
7923 printf("POSIX open of %s failed (%s)\n", fname, nt_errstr(status));
7927 /* Now unlink while open. */
7928 status = cli_posix_unlink(cli1, fname);
7929 if (!NT_STATUS_IS_OK(status)) {
7930 printf("POSIX unlink of %s failed (%s)\n", fname, nt_errstr(status));
7934 status = cli_close(cli1, fnum1);
7935 if (!NT_STATUS_IS_OK(status)) {
7936 printf("close(2) failed (%s)\n", nt_errstr(status));
7940 /* Ensure the file has gone. */
7941 status = cli_posix_open(cli1, fname, O_RDONLY, 0, &fnum1);
7942 if (NT_STATUS_IS_OK(status)) {
7943 printf("POSIX open of %s succeeded, should have been deleted.\n", fname);
7947 /* Create again to test open with O_TRUNC. */
7948 status = cli_posix_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL, 0600, &fnum1);
7949 if (!NT_STATUS_IS_OK(status)) {
7950 printf("POSIX create of %s failed (%s)\n", fname, nt_errstr(status));
7954 /* Test ftruncate - set file size. */
7955 status = cli_ftruncate(cli1, fnum1, 1000);
7956 if (!NT_STATUS_IS_OK(status)) {
7957 printf("ftruncate failed (%s)\n", nt_errstr(status));
7961 /* Ensure st_size == 1000 */
7962 status = cli_posix_stat(cli1, fname, &sbuf);
7963 if (!NT_STATUS_IS_OK(status)) {
7964 printf("stat failed (%s)\n", nt_errstr(status));
7968 if (sbuf.st_ex_size != 1000) {
7969 printf("ftruncate - stat size (%u) != 1000\n", (unsigned int)sbuf.st_ex_size);
7973 status = cli_close(cli1, fnum1);
7974 if (!NT_STATUS_IS_OK(status)) {
7975 printf("close(2) failed (%s)\n", nt_errstr(status));
7979 /* Re-open with O_TRUNC. */
7980 status = cli_posix_open(cli1, fname, O_WRONLY|O_TRUNC, 0600, &fnum1);
7981 if (!NT_STATUS_IS_OK(status)) {
7982 printf("POSIX create of %s failed (%s)\n", fname, nt_errstr(status));
7986 /* Ensure st_size == 0 */
7987 status = cli_posix_stat(cli1, fname, &sbuf);
7988 if (!NT_STATUS_IS_OK(status)) {
7989 printf("stat failed (%s)\n", nt_errstr(status));
7993 if (sbuf.st_ex_size != 0) {
7994 printf("O_TRUNC - stat size (%u) != 0\n", (unsigned int)sbuf.st_ex_size);
7998 status = cli_close(cli1, fnum1);
7999 if (!NT_STATUS_IS_OK(status)) {
8000 printf("close failed (%s)\n", nt_errstr(status));
8004 status = cli_posix_unlink(cli1, fname);
8005 if (!NT_STATUS_IS_OK(status)) {
8006 printf("POSIX unlink of %s failed (%s)\n", fname, nt_errstr(status));
8010 status = cli_posix_open(cli1, dname, O_RDONLY, 0, &fnum1);
8011 if (!NT_STATUS_IS_OK(status)) {
8012 printf("POSIX open directory O_RDONLY of %s failed (%s)\n",
8013 dname, nt_errstr(status));
8017 cli_close(cli1, fnum1);
8019 /* What happens when we try and POSIX open a directory for write ? */
8020 status = cli_posix_open(cli1, dname, O_RDWR, 0, &fnum1);
8021 if (NT_STATUS_IS_OK(status)) {
8022 printf("POSIX open of directory %s succeeded, "
8023 "should have failed.\n",
8027 if (!check_both_error(__LINE__, status, ERRDOS, EISDIR,
8028 NT_STATUS_FILE_IS_A_DIRECTORY)) {
8033 /* Create the file. */
8034 status = cli_posix_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL,
8036 if (!NT_STATUS_IS_OK(status)) {
8037 printf("POSIX create of %s failed (%s)\n", fname, nt_errstr(status));
8041 /* Write some data into it. */
8042 status = cli_writeall(cli1, fnum1, 0, (const uint8_t *)"TEST DATA\n", 0, 10,
8044 if (!NT_STATUS_IS_OK(status)) {
8045 printf("cli_write failed: %s\n", nt_errstr(status));
8049 cli_close(cli1, fnum1);
8051 /* Now create a hardlink. */
8052 status = cli_posix_hardlink(cli1, fname, hname);
8053 if (!NT_STATUS_IS_OK(status)) {
8054 printf("POSIX hardlink of %s failed (%s)\n", hname, nt_errstr(status));
8058 /* Now create a symlink. */
8059 status = cli_posix_symlink(cli1, fname, sname);
8060 if (!NT_STATUS_IS_OK(status)) {
8061 printf("POSIX symlink of %s failed (%s)\n", sname, nt_errstr(status));
8065 /* Open the hardlink for read. */
8066 status = cli_posix_open(cli1, hname, O_RDONLY, 0, &fnum1);
8067 if (!NT_STATUS_IS_OK(status)) {
8068 printf("POSIX open of %s failed (%s)\n", hname, nt_errstr(status));
8072 status = cli_read(cli1, fnum1, buf, 0, 10, &nread);
8073 if (!NT_STATUS_IS_OK(status)) {
8074 printf("POSIX read of %s failed (%s)\n", hname,
8077 } else if (nread != 10) {
8078 printf("POSIX read of %s failed. Received %ld, expected %d\n",
8079 hname, (unsigned long)nread, 10);
8083 if (memcmp(buf, "TEST DATA\n", 10)) {
8084 printf("invalid data read from hardlink\n");
8088 /* Do a POSIX lock/unlock. */
8089 status = cli_posix_lock(cli1, fnum1, 0, 100, true, READ_LOCK);
8090 if (!NT_STATUS_IS_OK(status)) {
8091 printf("POSIX lock failed %s\n", nt_errstr(status));
8095 /* Punch a hole in the locked area. */
8096 status = cli_posix_unlock(cli1, fnum1, 10, 80);
8097 if (!NT_STATUS_IS_OK(status)) {
8098 printf("POSIX unlock failed %s\n", nt_errstr(status));
8102 cli_close(cli1, fnum1);
8104 /* Open the symlink for read - this should fail. A POSIX
8105 client should not be doing opens on a symlink. */
8106 status = cli_posix_open(cli1, sname, O_RDONLY, 0, &fnum1);
8107 if (NT_STATUS_IS_OK(status)) {
8108 printf("POSIX open of %s succeeded (should have failed)\n", sname);
8111 ok = check_both_error(
8112 __LINE__, status, ERRDOS, ERRbadpath,
8113 NT_STATUS_OBJECT_NAME_NOT_FOUND);
8115 printf("POSIX open of %s should have failed "
8116 "with NT_STATUS_OBJECT_NAME_NOT_FOUND, "
8117 "failed with %s instead.\n",
8118 sname, nt_errstr(status));
8122 status = cli_readlink(cli1, sname, talloc_tos(), &target, NULL, NULL);
8123 if (!NT_STATUS_IS_OK(status)) {
8124 printf("POSIX readlink on %s failed (%s)\n", sname, nt_errstr(status));
8128 if (strcmp(target, fname) != 0) {
8129 printf("POSIX readlink on %s failed to match name %s (read %s)\n",
8130 sname, fname, target);
8134 status = cli_posix_rmdir(cli1, dname);
8135 if (!NT_STATUS_IS_OK(status)) {
8136 printf("POSIX rmdir failed (%s)\n", nt_errstr(status));
8140 /* Check directory opens with a specific permission. */
8141 status = cli_posix_mkdir(cli1, dname, 0700);
8142 if (!NT_STATUS_IS_OK(status)) {
8143 printf("POSIX mkdir of %s failed (%s)\n", dname, nt_errstr(status));
8147 /* Ensure st_mode == 0700 */
8148 status = cli_posix_stat(cli1, dname, &sbuf);
8149 if (!NT_STATUS_IS_OK(status)) {
8150 printf("stat failed (%s)\n", nt_errstr(status));
8154 if ((sbuf.st_ex_mode & 07777) != 0700) {
8155 printf("posix_mkdir - bad permissions 0%o != 0700\n",
8156 (unsigned int)(sbuf.st_ex_mode & 07777));
8161 * Now create a Windows file, and attempt a POSIX unlink.
8162 * This should fail with a sharing violation but due to:
8164 * [Bug 9571] Unlink after open causes smbd to panic
8166 * ensure we've fixed the lock ordering violation.
8169 status = cli_ntcreate(cli1, fname_windows, 0,
8170 FILE_READ_DATA|FILE_WRITE_DATA, 0,
8171 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
8173 0x0, 0x0, &fnum2, NULL);
8174 if (!NT_STATUS_IS_OK(status)) {
8175 printf("Windows create of %s failed (%s)\n", fname_windows,
8180 /* Now try posix_unlink. */
8181 status = cli_posix_unlink(cli1, fname_windows);
8182 if (!NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
8183 printf("POSIX unlink of %s should fail "
8184 "with NT_STATUS_SHARING_VIOLATION "
8185 "got %s instead !\n",
8191 cli_close(cli1, fnum2);
8193 printf("Simple POSIX open test passed\n");
8198 if (fnum1 != (uint16_t)-1) {
8199 cli_close(cli1, fnum1);
8200 fnum1 = (uint16_t)-1;
8203 if (fnum2 != (uint16_t)-1) {
8204 cli_close(cli1, fnum2);
8205 fnum2 = (uint16_t)-1;
8208 cli_setatr(cli1, sname, 0, 0);
8209 cli_posix_unlink(cli1, sname);
8210 cli_setatr(cli1, hname, 0, 0);
8211 cli_posix_unlink(cli1, hname);
8212 cli_setatr(cli1, fname, 0, 0);
8213 cli_posix_unlink(cli1, fname);
8214 cli_setatr(cli1, dname, 0, 0);
8215 cli_posix_rmdir(cli1, dname);
8216 cli_setatr(cli1, fname_windows, 0, 0);
8217 cli_posix_unlink(cli1, fname_windows);
8219 if (!torture_close_connection(cli1)) {
8227 Test POSIX and Windows ACLs are rejected on symlinks.
8229 static bool run_acl_symlink_test(int dummy)
8231 static struct cli_state *cli;
8232 const char *fname = "posix_file";
8233 const char *sname = "posix_symlink";
8234 uint16_t fnum = (uint16_t)-1;
8235 bool correct = false;
8237 char *posix_acl = NULL;
8238 size_t posix_acl_len = 0;
8239 char *posix_acl_sym = NULL;
8240 size_t posix_acl_len_sym = 0;
8241 struct security_descriptor *sd = NULL;
8242 TALLOC_CTX *frame = NULL;
8244 frame = talloc_stackframe();
8246 printf("Starting acl symlink test\n");
8248 if (!torture_open_connection(&cli, 0)) {
8253 smbXcli_conn_set_sockopt(cli->conn, sockops);
8255 status = torture_setup_unix_extensions(cli);
8256 if (!NT_STATUS_IS_OK(status)) {
8261 cli_setatr(cli, fname, 0, 0);
8262 cli_posix_unlink(cli, fname);
8263 cli_setatr(cli, sname, 0, 0);
8264 cli_posix_unlink(cli, sname);
8266 status = cli_ntcreate(cli,
8269 READ_CONTROL_ACCESS,
8271 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
8278 if (!NT_STATUS_IS_OK(status)) {
8279 printf("cli_ntcreate of %s failed (%s)\n",
8285 /* Get the Windows ACL on the file. */
8286 status = cli_query_secdesc(cli,
8290 if (!NT_STATUS_IS_OK(status)) {
8291 printf("cli_query_secdesc failed (%s)\n",
8296 /* Get the POSIX ACL on the file. */
8297 status = cli_posix_getacl(cli,
8303 if (!NT_STATUS_IS_OK(status)) {
8304 printf("cli_posix_getacl failed (%s)\n",
8309 status = cli_close(cli, fnum);
8310 if (!NT_STATUS_IS_OK(status)) {
8311 printf("close failed (%s)\n", nt_errstr(status));
8314 fnum = (uint16_t)-1;
8316 /* Now create a symlink. */
8317 status = cli_posix_symlink(cli, fname, sname);
8318 if (!NT_STATUS_IS_OK(status)) {
8319 printf("cli_posix_symlink of %s -> %s failed (%s)\n",
8326 /* Open a handle on the symlink for SD set/get should fail. */
8327 status = cli_ntcreate(cli,
8330 READ_CONTROL_ACCESS|SEC_STD_WRITE_DAC,
8332 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
8339 if (NT_STATUS_IS_OK(status)) {
8340 printf("Symlink open for getsd/setsd of %s "
8341 "succeeded (should fail)\n",
8346 /* Try a stat-open on the symlink, should also fail. */
8347 status = cli_ntcreate(cli,
8350 FILE_READ_ATTRIBUTES|FILE_WRITE_ATTRIBUTES,
8352 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
8359 if (NT_STATUS_IS_OK(status)) {
8360 printf("Stat-open of symlink succeeded (should fail)\n");
8364 /* Get the POSIX ACL on the symlink pathname. Should fail. */
8365 status = cli_posix_getacl(cli,
8371 if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
8372 printf("cli_posix_getacl on a symlink gave %s. "
8373 "Should be NT_STATUS_ACCESS_DENIED.\n",
8378 /* Set the POSIX ACL on the symlink pathname. Should fail. */
8379 status = cli_posix_setacl(cli,
8384 if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
8385 printf("cli_posix_setacl on a symlink gave %s. "
8386 "Should be NT_STATUS_ACCESS_DENIED.\n",
8391 printf("ACL symlink test passed\n");
8396 if (fnum != (uint16_t)-1) {
8397 cli_close(cli, fnum);
8398 fnum = (uint16_t)-1;
8401 cli_setatr(cli, sname, 0, 0);
8402 cli_posix_unlink(cli, sname);
8403 cli_setatr(cli, fname, 0, 0);
8404 cli_posix_unlink(cli, fname);
8406 if (!torture_close_connection(cli)) {
8415 Test POSIX can delete a file containing streams.
8417 static bool run_posix_stream_delete(int dummy)
8419 struct cli_state *cli1 = NULL;
8420 struct cli_state *cli2 = NULL;
8421 const char *fname = "streamfile";
8422 const char *stream_fname = "streamfile:Zone.Identifier:$DATA";
8423 uint16_t fnum1 = (uint16_t)-1;
8424 bool correct = false;
8426 TALLOC_CTX *frame = NULL;
8428 frame = talloc_stackframe();
8430 printf("Starting POSIX stream delete test\n");
8432 if (!torture_open_connection(&cli1, 0) ||
8433 !torture_open_connection(&cli2, 1)) {
8438 smbXcli_conn_set_sockopt(cli1->conn, sockops);
8439 smbXcli_conn_set_sockopt(cli2->conn, sockops);
8441 status = torture_setup_unix_extensions(cli2);
8442 if (!NT_STATUS_IS_OK(status)) {
8446 cli_setatr(cli1, fname, 0, 0);
8447 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
8449 /* Create the file. */
8450 status = cli_ntcreate(cli1,
8453 READ_CONTROL_ACCESS,
8455 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
8462 if (!NT_STATUS_IS_OK(status)) {
8463 printf("cli_ntcreate of %s failed (%s)\n",
8469 status = cli_close(cli1, fnum1);
8470 if (!NT_STATUS_IS_OK(status)) {
8471 printf("cli_close of %s failed (%s)\n",
8476 fnum1 = (uint16_t)-1;
8478 /* Now create the stream. */
8479 status = cli_ntcreate(cli1,
8484 FILE_SHARE_READ|FILE_SHARE_WRITE,
8491 if (!NT_STATUS_IS_OK(status)) {
8492 printf("cli_ntcreate of %s failed (%s)\n",
8498 /* Leave the stream handle open... */
8500 /* POSIX unlink should fail. */
8501 status = cli_posix_unlink(cli2, fname);
8502 if (NT_STATUS_IS_OK(status)) {
8503 printf("cli_posix_unlink of %s succeeded, should have failed\n",
8508 if (!NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
8509 printf("cli_posix_unlink of %s failed with (%s) "
8510 "should have been NT_STATUS_SHARING_VIOLATION\n",
8516 /* Close the stream handle. */
8517 status = cli_close(cli1, fnum1);
8518 if (!NT_STATUS_IS_OK(status)) {
8519 printf("cli_close of %s failed (%s)\n",
8524 fnum1 = (uint16_t)-1;
8526 /* POSIX unlink after stream handle closed should succeed. */
8527 status = cli_posix_unlink(cli2, fname);
8528 if (!NT_STATUS_IS_OK(status)) {
8529 printf("cli_posix_unlink of %s failed (%s)\n",
8535 printf("POSIX stream delete test passed\n");
8540 if (fnum1 != (uint16_t)-1) {
8541 cli_close(cli1, fnum1);
8542 fnum1 = (uint16_t)-1;
8545 cli_setatr(cli1, fname, 0, 0);
8546 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
8548 if (!torture_close_connection(cli1)) {
8551 if (!torture_close_connection(cli2)) {
8560 Test setting EA's are rejected on symlinks.
8562 static bool run_ea_symlink_test(int dummy)
8564 static struct cli_state *cli;
8565 const char *fname = "posix_file_ea";
8566 const char *sname = "posix_symlink_ea";
8567 const char *ea_name = "testea_name";
8568 const char *ea_value = "testea_value";
8569 uint16_t fnum = (uint16_t)-1;
8570 bool correct = false;
8573 struct ea_struct *eas = NULL;
8574 TALLOC_CTX *frame = NULL;
8576 frame = talloc_stackframe();
8578 printf("Starting EA symlink test\n");
8580 if (!torture_open_connection(&cli, 0)) {
8585 smbXcli_conn_set_sockopt(cli->conn, sockops);
8587 status = torture_setup_unix_extensions(cli);
8588 if (!NT_STATUS_IS_OK(status)) {
8593 cli_setatr(cli, fname, 0, 0);
8594 cli_posix_unlink(cli, fname);
8595 cli_setatr(cli, sname, 0, 0);
8596 cli_posix_unlink(cli, sname);
8598 status = cli_ntcreate(cli,
8601 READ_CONTROL_ACCESS,
8603 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
8610 if (!NT_STATUS_IS_OK(status)) {
8611 printf("cli_ntcreate of %s failed (%s)\n",
8617 status = cli_close(cli, fnum);
8618 if (!NT_STATUS_IS_OK(status)) {
8619 printf("close failed (%s)\n",
8623 fnum = (uint16_t)-1;
8625 /* Set an EA on the path. */
8626 status = cli_set_ea_path(cli,
8630 strlen(ea_value)+1);
8632 if (!NT_STATUS_IS_OK(status)) {
8633 printf("cli_set_ea_path failed (%s)\n",
8638 /* Now create a symlink. */
8639 status = cli_posix_symlink(cli, fname, sname);
8640 if (!NT_STATUS_IS_OK(status)) {
8641 printf("cli_posix_symlink of %s -> %s failed (%s)\n",
8648 /* Get the EA list on the path. Should return value set. */
8649 status = cli_get_ea_list_path(cli,
8655 if (!NT_STATUS_IS_OK(status)) {
8656 printf("cli_get_ea_list_path failed (%s)\n",
8661 /* Ensure the EA we set is there. */
8662 for (i=0; i<num_eas; i++) {
8663 if (strcmp(eas[i].name, ea_name) == 0 &&
8664 eas[i].value.length == strlen(ea_value)+1 &&
8665 memcmp(eas[i].value.data,
8667 eas[i].value.length) == 0) {
8673 printf("Didn't find EA on pathname %s\n",
8681 /* Get the EA list on the symlink. Should return empty list. */
8682 status = cli_get_ea_list_path(cli,
8688 if (!NT_STATUS_IS_OK(status)) {
8689 printf("cli_get_ea_list_path failed (%s)\n",
8695 printf("cli_get_ea_list_path failed (%s)\n",
8700 /* Set an EA on the symlink. Should fail. */
8701 status = cli_set_ea_path(cli,
8705 strlen(ea_value)+1);
8707 if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
8708 printf("cli_set_ea_path on a symlink gave %s. "
8709 "Should be NT_STATUS_ACCESS_DENIED.\n",
8714 printf("EA symlink test passed\n");
8719 if (fnum != (uint16_t)-1) {
8720 cli_close(cli, fnum);
8721 fnum = (uint16_t)-1;
8724 cli_setatr(cli, sname, 0, 0);
8725 cli_posix_unlink(cli, sname);
8726 cli_setatr(cli, fname, 0, 0);
8727 cli_posix_unlink(cli, fname);
8729 if (!torture_close_connection(cli)) {
8738 Test POSIX locks are OFD-locks.
8740 static bool run_posix_ofd_lock_test(int dummy)
8742 static struct cli_state *cli;
8743 const char *fname = "posix_file";
8744 uint16_t fnum1 = (uint16_t)-1;
8745 uint16_t fnum2 = (uint16_t)-1;
8746 bool correct = false;
8748 TALLOC_CTX *frame = NULL;
8750 frame = talloc_stackframe();
8752 printf("Starting POSIX ofd-lock test\n");
8754 if (!torture_open_connection(&cli, 0)) {
8759 smbXcli_conn_set_sockopt(cli->conn, sockops);
8761 status = torture_setup_unix_extensions(cli);
8762 if (!NT_STATUS_IS_OK(status)) {
8767 cli_setatr(cli, fname, 0, 0);
8768 cli_posix_unlink(cli, fname);
8770 /* Open the file twice. */
8771 status = cli_posix_open(cli, fname, O_RDWR|O_CREAT|O_EXCL,
8773 if (!NT_STATUS_IS_OK(status)) {
8774 printf("First POSIX open of %s failed\n", fname);
8778 status = cli_posix_open(cli, fname, O_RDWR, 0, &fnum2);
8779 if (!NT_STATUS_IS_OK(status)) {
8780 printf("First POSIX open of %s failed\n", fname);
8784 /* Set a 0-50 lock on fnum1. */
8785 status = cli_posix_lock(cli, fnum1, 0, 50, false, WRITE_LOCK);
8786 if (!NT_STATUS_IS_OK(status)) {
8787 printf("POSIX lock (1) failed %s\n", nt_errstr(status));
8791 /* Set a 60-100 lock on fnum2. */
8792 status = cli_posix_lock(cli, fnum2, 60, 100, false, WRITE_LOCK);
8793 if (!NT_STATUS_IS_OK(status)) {
8794 printf("POSIX lock (2) failed %s\n", nt_errstr(status));
8798 /* close fnum1 - 0-50 lock should go away. */
8799 status = cli_close(cli, fnum1);
8800 if (!NT_STATUS_IS_OK(status)) {
8801 printf("close failed (%s)\n",
8805 fnum1 = (uint16_t)-1;
8807 /* Change the lock context. */
8808 cli_setpid(cli, cli_getpid(cli) + 1);
8810 /* Re-open fnum1. */
8811 status = cli_posix_open(cli, fname, O_RDWR, 0, &fnum1);
8812 if (!NT_STATUS_IS_OK(status)) {
8813 printf("Third POSIX open of %s failed\n", fname);
8817 /* 60-100 lock should still be there. */
8818 status = cli_posix_lock(cli, fnum1, 60, 100, false, WRITE_LOCK);
8819 if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
8820 printf("POSIX lock 60-100 not there %s\n", nt_errstr(status));
8824 /* 0-50 lock should be gone. */
8825 status = cli_posix_lock(cli, fnum1, 0, 50, false, WRITE_LOCK);
8826 if (!NT_STATUS_IS_OK(status)) {
8827 printf("POSIX lock 0-50 failed %s\n", nt_errstr(status));
8831 printf("POSIX OFD lock test passed\n");
8836 if (fnum1 != (uint16_t)-1) {
8837 cli_close(cli, fnum1);
8838 fnum1 = (uint16_t)-1;
8840 if (fnum2 != (uint16_t)-1) {
8841 cli_close(cli, fnum2);
8842 fnum2 = (uint16_t)-1;
8845 cli_setatr(cli, fname, 0, 0);
8846 cli_posix_unlink(cli, fname);
8848 if (!torture_close_connection(cli)) {
8856 struct posix_blocking_state {
8857 struct tevent_context *ev;
8858 struct cli_state *cli1;
8860 struct cli_state *cli2;
8866 static void posix_blocking_locked(struct tevent_req *subreq);
8867 static void posix_blocking_gotblocked(struct tevent_req *subreq);
8868 static void posix_blocking_gotecho(struct tevent_req *subreq);
8869 static void posix_blocking_unlocked(struct tevent_req *subreq);
8871 static struct tevent_req *posix_blocking_send(
8872 TALLOC_CTX *mem_ctx,
8873 struct tevent_context *ev,
8874 struct cli_state *cli1,
8876 struct cli_state *cli2,
8879 struct tevent_req *req = NULL, *subreq = NULL;
8880 struct posix_blocking_state *state = NULL;
8882 req = tevent_req_create(mem_ctx, &state, struct posix_blocking_state);
8888 state->fnum1 = fnum1;
8890 state->fnum2 = fnum2;
8892 subreq = cli_posix_lock_send(
8901 if (tevent_req_nomem(subreq, req)) {
8902 return tevent_req_post(req, ev);
8904 tevent_req_set_callback(subreq, posix_blocking_locked, req);
8908 static void posix_blocking_locked(struct tevent_req *subreq)
8910 struct tevent_req *req = tevent_req_callback_data(
8911 subreq, struct tevent_req);
8912 struct posix_blocking_state *state = tevent_req_data(
8913 req, struct posix_blocking_state);
8916 status = cli_posix_lock_recv(subreq);
8917 TALLOC_FREE(subreq);
8918 if (tevent_req_nterror(req, status)) {
8922 subreq = cli_posix_lock_send(
8931 if (tevent_req_nomem(subreq, req)) {
8934 tevent_req_set_callback(subreq, posix_blocking_gotblocked, req);
8936 /* Make sure the blocking request is delivered */
8937 subreq = cli_echo_send(
8942 (DATA_BLOB) { .data = (uint8_t *)state, .length = 1 });
8943 if (tevent_req_nomem(subreq, req)) {
8946 tevent_req_set_callback(subreq, posix_blocking_gotecho, req);
8949 static void posix_blocking_gotblocked(struct tevent_req *subreq)
8951 struct tevent_req *req = tevent_req_callback_data(
8952 subreq, struct tevent_req);
8953 struct posix_blocking_state *state = tevent_req_data(
8954 req, struct posix_blocking_state);
8957 status = cli_posix_lock_recv(subreq);
8958 TALLOC_FREE(subreq);
8959 if (tevent_req_nterror(req, status)) {
8962 if (!state->gotecho) {
8963 printf("blocked req got through before echo\n");
8964 tevent_req_nterror(req, NT_STATUS_INVALID_LOCK_SEQUENCE);
8967 tevent_req_done(req);
8970 static void posix_blocking_gotecho(struct tevent_req *subreq)
8972 struct tevent_req *req = tevent_req_callback_data(
8973 subreq, struct tevent_req);
8974 struct posix_blocking_state *state = tevent_req_data(
8975 req, struct posix_blocking_state);
8978 status = cli_echo_recv(subreq);
8979 TALLOC_FREE(subreq);
8980 if (tevent_req_nterror(req, status)) {
8983 if (state->gotblocked) {
8984 printf("blocked req got through before echo\n");
8985 tevent_req_nterror(req, NT_STATUS_INVALID_LOCK_SEQUENCE);
8988 state->gotecho = true;
8990 subreq = cli_posix_lock_send(
8999 if (tevent_req_nomem(subreq, req)) {
9002 tevent_req_set_callback(subreq, posix_blocking_unlocked, req);
9005 static void posix_blocking_unlocked(struct tevent_req *subreq)
9007 struct tevent_req *req = tevent_req_callback_data(
9008 subreq, struct tevent_req);
9011 status = cli_posix_lock_recv(subreq);
9012 TALLOC_FREE(subreq);
9013 if (tevent_req_nterror(req, status)) {
9016 /* tevent_req_done in posix_blocking_gotlocked */
9019 static NTSTATUS posix_blocking_recv(struct tevent_req *req)
9021 return tevent_req_simple_recv_ntstatus(req);
9024 static bool run_posix_blocking_lock(int dummy)
9026 struct tevent_context *ev = NULL;
9027 struct cli_state *cli1 = NULL, *cli2 = NULL;
9028 const char *fname = "posix_blocking";
9029 uint16_t fnum1 = UINT16_MAX, fnum2 = UINT16_MAX;
9030 struct tevent_req *req = NULL;
9035 printf("Starting posix blocking lock test\n");
9037 ev = samba_tevent_context_init(NULL);
9042 ok = torture_open_connection(&cli1, 0);
9046 ok = torture_open_connection(&cli2, 0);
9051 smbXcli_conn_set_sockopt(cli1->conn, sockops);
9053 status = torture_setup_unix_extensions(cli1);
9054 if (!NT_STATUS_IS_OK(status)) {
9058 status = torture_setup_unix_extensions(cli2);
9059 if (!NT_STATUS_IS_OK(status)) {
9063 cli_setatr(cli1, fname, 0, 0);
9064 cli_posix_unlink(cli1, fname);
9066 status = cli_posix_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL,
9068 if (!NT_STATUS_IS_OK(status)) {
9069 printf("First POSIX open of %s failed: %s\n",
9075 status = cli_posix_open(cli2, fname, O_RDWR, 0600, &fnum2);
9076 if (!NT_STATUS_IS_OK(status)) {
9077 printf("Second POSIX open of %s failed: %s\n",
9083 req = posix_blocking_send(ev, ev, cli1, fnum1, cli2, fnum2);
9085 printf("cli_posix_blocking failed\n");
9089 ok = tevent_req_poll_ntstatus(req, ev, &status);
9091 printf("tevent_req_poll_ntstatus failed: %s\n",
9095 status = posix_blocking_recv(req);
9097 if (!NT_STATUS_IS_OK(status)) {
9098 printf("posix_blocking_recv returned %s\n",
9106 if (fnum1 != UINT16_MAX) {
9107 cli_close(cli1, fnum1);
9110 if (fnum2 != UINT16_MAX) {
9111 cli_close(cli2, fnum2);
9116 cli_setatr(cli1, fname, 0, 0);
9117 cli_posix_unlink(cli1, fname);
9123 ok &= torture_close_connection(cli1);
9127 ok &= torture_close_connection(cli2);
9139 Test POSIX mkdir is case-sensitive.
9141 static bool run_posix_mkdir_test(int dummy)
9143 static struct cli_state *cli;
9144 const char *fname_foo = "POSIX_foo";
9145 const char *fname_foo_Foo = "POSIX_foo/Foo";
9146 const char *fname_foo_foo = "POSIX_foo/foo";
9147 const char *fname_Foo = "POSIX_Foo";
9148 const char *fname_Foo_Foo = "POSIX_Foo/Foo";
9149 const char *fname_Foo_foo = "POSIX_Foo/foo";
9150 bool correct = false;
9152 TALLOC_CTX *frame = NULL;
9153 uint16_t fnum = (uint16_t)-1;
9155 frame = talloc_stackframe();
9157 printf("Starting POSIX mkdir test\n");
9159 if (!torture_open_connection(&cli, 0)) {
9164 smbXcli_conn_set_sockopt(cli->conn, sockops);
9166 status = torture_setup_unix_extensions(cli);
9167 if (!NT_STATUS_IS_OK(status)) {
9172 cli_posix_rmdir(cli, fname_foo_foo);
9173 cli_posix_rmdir(cli, fname_foo_Foo);
9174 cli_posix_rmdir(cli, fname_foo);
9176 cli_posix_rmdir(cli, fname_Foo_foo);
9177 cli_posix_rmdir(cli, fname_Foo_Foo);
9178 cli_posix_rmdir(cli, fname_Foo);
9181 * Create a file POSIX_foo then try
9182 * and use it in a directory path by
9183 * doing mkdir POSIX_foo/bar.
9184 * The mkdir should fail with
9185 * NT_STATUS_OBJECT_PATH_NOT_FOUND
9188 status = cli_posix_open(cli,
9193 if (!NT_STATUS_IS_OK(status)) {
9194 printf("cli_posix_open of %s failed error %s\n",
9200 status = cli_posix_mkdir(cli, fname_foo_foo, 0777);
9201 if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_PATH_NOT_FOUND)) {
9202 printf("cli_posix_mkdir of %s should fail with "
9203 "NT_STATUS_OBJECT_PATH_NOT_FOUND got "
9210 status = cli_close(cli, fnum);
9211 if (!NT_STATUS_IS_OK(status)) {
9212 printf("cli_close failed %s\n", nt_errstr(status));
9215 fnum = (uint16_t)-1;
9217 status = cli_posix_unlink(cli, fname_foo);
9218 if (!NT_STATUS_IS_OK(status)) {
9219 printf("cli_posix_unlink of %s failed error %s\n",
9226 * Now we've deleted everything, posix_mkdir, posix_rmdir,
9227 * posix_open, posix_unlink, on
9228 * POSIX_foo/foo should return NT_STATUS_OBJECT_PATH_NOT_FOUND
9229 * not silently create POSIX_foo/foo.
9232 status = cli_posix_mkdir(cli, fname_foo_foo, 0777);
9233 if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_PATH_NOT_FOUND)) {
9234 printf("cli_posix_mkdir of %s should fail with "
9235 "NT_STATUS_OBJECT_PATH_NOT_FOUND got "
9242 status = cli_posix_rmdir(cli, fname_foo_foo);
9243 if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_PATH_NOT_FOUND)) {
9244 printf("cli_posix_rmdir of %s should fail with "
9245 "NT_STATUS_OBJECT_PATH_NOT_FOUND got "
9252 status = cli_posix_open(cli,
9257 if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_PATH_NOT_FOUND)) {
9258 printf("cli_posix_open of %s should fail with "
9259 "NT_STATUS_OBJECT_PATH_NOT_FOUND got "
9266 status = cli_posix_unlink(cli, fname_foo_foo);
9267 if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_PATH_NOT_FOUND)) {
9268 printf("cli_posix_unlink of %s should fail with "
9269 "NT_STATUS_OBJECT_PATH_NOT_FOUND got "
9276 status = cli_posix_mkdir(cli, fname_foo, 0777);
9277 if (!NT_STATUS_IS_OK(status)) {
9278 printf("cli_posix_mkdir of %s failed\n", fname_foo);
9282 status = cli_posix_mkdir(cli, fname_Foo, 0777);
9283 if (!NT_STATUS_IS_OK(status)) {
9284 printf("cli_posix_mkdir of %s failed\n", fname_Foo);
9288 status = cli_posix_mkdir(cli, fname_foo_foo, 0777);
9289 if (!NT_STATUS_IS_OK(status)) {
9290 printf("cli_posix_mkdir of %s failed\n", fname_foo_foo);
9294 status = cli_posix_mkdir(cli, fname_foo_Foo, 0777);
9295 if (!NT_STATUS_IS_OK(status)) {
9296 printf("cli_posix_mkdir of %s failed\n", fname_foo_Foo);
9300 status = cli_posix_mkdir(cli, fname_Foo_foo, 0777);
9301 if (!NT_STATUS_IS_OK(status)) {
9302 printf("cli_posix_mkdir of %s failed\n", fname_Foo_foo);
9306 status = cli_posix_mkdir(cli, fname_Foo_Foo, 0777);
9307 if (!NT_STATUS_IS_OK(status)) {
9308 printf("cli_posix_mkdir of %s failed\n", fname_Foo_Foo);
9312 printf("POSIX mkdir test passed\n");
9317 if (fnum != (uint16_t)-1) {
9318 cli_close(cli, fnum);
9319 fnum = (uint16_t)-1;
9322 cli_posix_rmdir(cli, fname_foo_foo);
9323 cli_posix_rmdir(cli, fname_foo_Foo);
9324 cli_posix_rmdir(cli, fname_foo);
9326 cli_posix_rmdir(cli, fname_Foo_foo);
9327 cli_posix_rmdir(cli, fname_Foo_Foo);
9328 cli_posix_rmdir(cli, fname_Foo);
9330 if (!torture_close_connection(cli)) {
9338 struct posix_acl_oplock_state {
9339 struct tevent_context *ev;
9340 struct cli_state *cli;
9346 static void posix_acl_oplock_got_break(struct tevent_req *req)
9348 struct posix_acl_oplock_state *state = tevent_req_callback_data(
9349 req, struct posix_acl_oplock_state);
9354 status = cli_smb_oplock_break_waiter_recv(req, &fnum, &level);
9356 if (!NT_STATUS_IS_OK(status)) {
9357 printf("cli_smb_oplock_break_waiter_recv returned %s\n",
9361 *state->got_break = true;
9363 req = cli_oplock_ack_send(state, state->ev, state->cli, fnum,
9366 printf("cli_oplock_ack_send failed\n");
9371 static void posix_acl_oplock_got_acl(struct tevent_req *req)
9373 struct posix_acl_oplock_state *state = tevent_req_callback_data(
9374 req, struct posix_acl_oplock_state);
9375 size_t ret_size = 0;
9376 char *ret_data = NULL;
9378 state->status = cli_posix_getacl_recv(req,
9383 if (!NT_STATUS_IS_OK(state->status)) {
9384 printf("cli_posix_getacl_recv returned %s\n",
9385 nt_errstr(state->status));
9387 *state->acl_ret = true;
9390 static bool run_posix_acl_oplock_test(int dummy)
9392 struct tevent_context *ev;
9393 struct cli_state *cli1, *cli2;
9394 struct tevent_req *oplock_req, *getacl_req;
9395 const char *fname = "posix_acl_oplock";
9397 int saved_use_oplocks = use_oplocks;
9399 bool correct = true;
9400 bool got_break = false;
9401 bool acl_ret = false;
9403 struct posix_acl_oplock_state *state;
9405 printf("starting posix_acl_oplock test\n");
9407 if (!torture_open_connection(&cli1, 0)) {
9408 use_level_II_oplocks = false;
9409 use_oplocks = saved_use_oplocks;
9413 if (!torture_open_connection(&cli2, 1)) {
9414 use_level_II_oplocks = false;
9415 use_oplocks = saved_use_oplocks;
9419 /* Setup posix on cli2 only. */
9420 status = torture_setup_unix_extensions(cli2);
9421 if (!NT_STATUS_IS_OK(status)) {
9425 smbXcli_conn_set_sockopt(cli1->conn, sockops);
9426 smbXcli_conn_set_sockopt(cli2->conn, sockops);
9428 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
9430 /* Create the file on the Windows connection. */
9431 status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
9433 if (!NT_STATUS_IS_OK(status)) {
9434 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
9438 status = cli_close(cli1, fnum);
9439 if (!NT_STATUS_IS_OK(status)) {
9440 printf("close1 failed (%s)\n", nt_errstr(status));
9444 cli1->use_oplocks = true;
9446 /* Open with oplock. */
9447 status = cli_ntcreate(cli1,
9451 FILE_ATTRIBUTE_NORMAL,
9452 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
9459 if (!NT_STATUS_IS_OK(status)) {
9460 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
9464 ev = samba_tevent_context_init(talloc_tos());
9466 printf("tevent_context_init failed\n");
9470 state = talloc_zero(ev, struct posix_acl_oplock_state);
9471 if (state == NULL) {
9472 printf("talloc failed\n");
9477 state->got_break = &got_break;
9478 state->acl_ret = &acl_ret;
9480 oplock_req = cli_smb_oplock_break_waiter_send(
9481 talloc_tos(), ev, cli1);
9482 if (oplock_req == NULL) {
9483 printf("cli_smb_oplock_break_waiter_send failed\n");
9486 tevent_req_set_callback(oplock_req, posix_acl_oplock_got_break, state);
9488 /* Get ACL on POSIX connection - should break oplock. */
9489 getacl_req = cli_posix_getacl_send(talloc_tos(),
9493 if (getacl_req == NULL) {
9494 printf("cli_posix_getacl_send failed\n");
9497 tevent_req_set_callback(getacl_req, posix_acl_oplock_got_acl, state);
9499 while (!got_break || !acl_ret) {
9501 ret = tevent_loop_once(ev);
9503 printf("tevent_loop_once failed: %s\n",
9509 if (!NT_STATUS_IS_OK(state->status)) {
9510 printf("getacl failed (%s)\n", nt_errstr(state->status));
9514 status = cli_close(cli1, fnum);
9515 if (!NT_STATUS_IS_OK(status)) {
9516 printf("close2 failed (%s)\n", nt_errstr(status));
9520 status = cli_unlink(cli1,
9522 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
9523 if (!NT_STATUS_IS_OK(status)) {
9524 printf("unlink failed (%s)\n", nt_errstr(status));
9528 if (!torture_close_connection(cli1)) {
9531 if (!torture_close_connection(cli2)) {
9539 printf("finished posix acl oplock test\n");
9544 static bool run_posix_acl_shareroot_test(int dummy)
9546 struct cli_state *cli;
9548 bool correct = false;
9549 char *posix_acl = NULL;
9550 size_t posix_acl_len = 0;
9551 uint16_t num_file_acls = 0;
9552 uint16_t num_dir_acls = 0;
9554 uint32_t expected_size = 0;
9555 bool got_user = false;
9556 bool got_group = false;
9557 bool got_other = false;
9558 TALLOC_CTX *frame = NULL;
9560 frame = talloc_stackframe();
9562 printf("starting posix_acl_shareroot test\n");
9564 if (!torture_open_connection(&cli, 0)) {
9569 smbXcli_conn_set_sockopt(cli->conn, sockops);
9571 status = torture_setup_unix_extensions(cli);
9572 if (!NT_STATUS_IS_OK(status)) {
9573 printf("Failed to setup unix extensions\n");
9577 /* Get the POSIX ACL on the root of the share. */
9578 status = cli_posix_getacl(cli,
9584 if (!NT_STATUS_IS_OK(status)) {
9585 printf("cli_posix_getacl of '.' failed (%s)\n",
9590 if (posix_acl_len < 6 ||
9591 SVAL(posix_acl,0) != SMB_POSIX_ACL_VERSION) {
9592 printf("getfacl ., unknown POSIX acl version %u.\n",
9593 (unsigned int)CVAL(posix_acl,0) );
9597 num_file_acls = SVAL(posix_acl,2);
9598 num_dir_acls = SVAL(posix_acl,4);
9599 expected_size = SMB_POSIX_ACL_HEADER_SIZE +
9600 SMB_POSIX_ACL_ENTRY_SIZE*
9601 (num_file_acls+num_dir_acls);
9603 if (posix_acl_len != expected_size) {
9604 printf("incorrect POSIX acl buffer size "
9605 "(should be %u, was %u).\n",
9606 (unsigned int)expected_size,
9607 (unsigned int)posix_acl_len);
9612 * We don't need to know what the ACL's are
9613 * we just need to know we have at least 3
9614 * file entries (u,g,o).
9617 for (i = 0; i < num_file_acls; i++) {
9618 unsigned char tagtype =
9620 SMB_POSIX_ACL_HEADER_SIZE+
9621 (i*SMB_POSIX_ACL_ENTRY_SIZE));
9624 case SMB_POSIX_ACL_USER_OBJ:
9627 case SMB_POSIX_ACL_GROUP_OBJ:
9630 case SMB_POSIX_ACL_OTHER:
9639 printf("Missing user entry\n");
9644 printf("Missing group entry\n");
9649 printf("Missing other entry\n");
9657 if (!torture_close_connection(cli)) {
9661 printf("finished posix acl shareroot test\n");
9667 static uint32_t open_attrs_table[] = {
9668 FILE_ATTRIBUTE_NORMAL,
9669 FILE_ATTRIBUTE_ARCHIVE,
9670 FILE_ATTRIBUTE_READONLY,
9671 FILE_ATTRIBUTE_HIDDEN,
9672 FILE_ATTRIBUTE_SYSTEM,
9674 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY,
9675 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN,
9676 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM,
9677 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN,
9678 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM,
9679 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM,
9681 FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN,
9682 FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM,
9683 FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM,
9684 FILE_ATTRIBUTE_HIDDEN,FILE_ATTRIBUTE_SYSTEM,
9687 struct trunc_open_results {
9690 uint32_t trunc_attr;
9691 uint32_t result_attr;
9694 static struct trunc_open_results attr_results[] = {
9695 { 0, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_ARCHIVE },
9696 { 1, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_ARCHIVE },
9697 { 2, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_READONLY, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY },
9698 { 16, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_ARCHIVE },
9699 { 17, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_ARCHIVE },
9700 { 18, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_READONLY, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY },
9701 { 51, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
9702 { 54, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
9703 { 56, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN },
9704 { 68, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
9705 { 71, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
9706 { 73, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM },
9707 { 99, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_HIDDEN,FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
9708 { 102, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
9709 { 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 },
9710 { 116, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
9711 { 119, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
9712 { 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 },
9713 { 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 },
9714 { 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 },
9715 { 227, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
9716 { 230, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
9717 { 232, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN },
9718 { 244, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
9719 { 247, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
9720 { 249, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM }
9723 static bool run_openattrtest(int dummy)
9725 static struct cli_state *cli1;
9726 const char *fname = "\\openattr.file";
9728 bool correct = True;
9730 unsigned int i, j, k, l;
9733 printf("starting open attr test\n");
9735 if (!torture_open_connection(&cli1, 0)) {
9739 smbXcli_conn_set_sockopt(cli1->conn, sockops);
9741 for (k = 0, i = 0; i < sizeof(open_attrs_table)/sizeof(uint32_t); i++) {
9742 cli_setatr(cli1, fname, 0, 0);
9743 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
9745 status = cli_ntcreate(cli1, fname, 0, FILE_WRITE_DATA,
9746 open_attrs_table[i], FILE_SHARE_NONE,
9747 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
9748 if (!NT_STATUS_IS_OK(status)) {
9749 printf("open %d (1) of %s failed (%s)\n", i, fname, nt_errstr(status));
9753 status = cli_close(cli1, fnum1);
9754 if (!NT_STATUS_IS_OK(status)) {
9755 printf("close %d (1) of %s failed (%s)\n", i, fname, nt_errstr(status));
9759 for (j = 0; j < sizeof(open_attrs_table)/sizeof(uint32_t); j++) {
9760 status = cli_ntcreate(cli1, fname, 0,
9761 FILE_READ_DATA|FILE_WRITE_DATA,
9762 open_attrs_table[j],
9763 FILE_SHARE_NONE, FILE_OVERWRITE,
9764 0, 0, &fnum1, NULL);
9765 if (!NT_STATUS_IS_OK(status)) {
9766 for (l = 0; l < sizeof(attr_results)/sizeof(struct trunc_open_results); l++) {
9767 if (attr_results[l].num == k) {
9768 printf("[%d] trunc open 0x%x -> 0x%x of %s failed - should have succeeded !(0x%x:%s)\n",
9769 k, open_attrs_table[i],
9770 open_attrs_table[j],
9771 fname, NT_STATUS_V(status), nt_errstr(status));
9776 if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
9777 printf("[%d] trunc open 0x%x -> 0x%x failed with wrong error code %s\n",
9778 k, open_attrs_table[i], open_attrs_table[j],
9783 printf("[%d] trunc open 0x%x -> 0x%x failed\n", k, open_attrs_table[i], open_attrs_table[j]);
9789 status = cli_close(cli1, fnum1);
9790 if (!NT_STATUS_IS_OK(status)) {
9791 printf("close %d (2) of %s failed (%s)\n", j, fname, nt_errstr(status));
9795 status = cli_getatr(cli1, fname, &attr, NULL, NULL);
9796 if (!NT_STATUS_IS_OK(status)) {
9797 printf("getatr(2) failed (%s)\n", nt_errstr(status));
9802 printf("[%d] getatr check [0x%x] trunc [0x%x] got attr 0x%x\n",
9803 k, open_attrs_table[i], open_attrs_table[j], attr );
9806 for (l = 0; l < sizeof(attr_results)/sizeof(struct trunc_open_results); l++) {
9807 if (attr_results[l].num == k) {
9808 if (attr != attr_results[l].result_attr ||
9809 open_attrs_table[i] != attr_results[l].init_attr ||
9810 open_attrs_table[j] != attr_results[l].trunc_attr) {
9811 printf("getatr check failed. [0x%x] trunc [0x%x] got attr 0x%x, should be 0x%x\n",
9812 open_attrs_table[i],
9813 open_attrs_table[j],
9815 attr_results[l].result_attr);
9825 cli_setatr(cli1, fname, 0, 0);
9826 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
9828 printf("open attr test %s.\n", correct ? "passed" : "failed");
9830 if (!torture_close_connection(cli1)) {
9836 static NTSTATUS list_fn(struct file_info *finfo,
9837 const char *name, void *state)
9839 int *matched = (int *)state;
9840 if (matched != NULL) {
9843 return NT_STATUS_OK;
9847 test directory listing speed
9849 static bool run_dirtest(int dummy)
9852 static struct cli_state *cli;
9854 struct timeval core_start;
9855 bool correct = True;
9858 printf("starting directory test\n");
9860 if (!torture_open_connection(&cli, 0)) {
9864 smbXcli_conn_set_sockopt(cli->conn, sockops);
9867 for (i=0;i<torture_numops;i++) {
9869 slprintf(fname, sizeof(fname), "\\%x", (int)random());
9870 if (!NT_STATUS_IS_OK(cli_openx(cli, fname, O_RDWR|O_CREAT, DENY_NONE, &fnum))) {
9871 fprintf(stderr,"Failed to open %s\n", fname);
9874 cli_close(cli, fnum);
9877 core_start = timeval_current();
9880 cli_list(cli, "a*.*", 0, list_fn, &matched);
9881 printf("Matched %d\n", matched);
9884 cli_list(cli, "b*.*", 0, list_fn, &matched);
9885 printf("Matched %d\n", matched);
9888 cli_list(cli, "xyzabc", 0, list_fn, &matched);
9889 printf("Matched %d\n", matched);
9891 printf("dirtest core %g seconds\n", timeval_elapsed(&core_start));
9894 for (i=0;i<torture_numops;i++) {
9896 slprintf(fname, sizeof(fname), "\\%x", (int)random());
9897 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
9900 if (!torture_close_connection(cli)) {
9904 printf("finished dirtest\n");
9909 static NTSTATUS del_fn(struct file_info *finfo, const char *mask,
9912 struct cli_state *pcli = (struct cli_state *)state;
9914 slprintf(fname, sizeof(fname), "\\LISTDIR\\%s", finfo->name);
9916 if (strcmp(finfo->name, ".") == 0 || strcmp(finfo->name, "..") == 0)
9917 return NT_STATUS_OK;
9919 if (finfo->attr & FILE_ATTRIBUTE_DIRECTORY) {
9920 if (!NT_STATUS_IS_OK(cli_rmdir(pcli, fname)))
9921 printf("del_fn: failed to rmdir %s\n,", fname );
9923 if (!NT_STATUS_IS_OK(cli_unlink(pcli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN)))
9924 printf("del_fn: failed to unlink %s\n,", fname );
9926 return NT_STATUS_OK;
9931 send a raw ioctl - used by the torture code
9933 static NTSTATUS cli_raw_ioctl(struct cli_state *cli,
9941 PUSH_LE_U16(vwv + 0, 0, fnum);
9942 PUSH_LE_U16(vwv + 1, 0, code >> 16);
9943 PUSH_LE_U16(vwv + 2, 0, (code & 0xFFFF));
9945 status = cli_smb(talloc_tos(),
9959 if (!NT_STATUS_IS_OK(status)) {
9962 *blob = data_blob_null;
9963 return NT_STATUS_OK;
9967 sees what IOCTLs are supported
9969 bool torture_ioctl_test(int dummy)
9971 static struct cli_state *cli;
9972 uint16_t device, function;
9974 const char *fname = "\\ioctl.dat";
9978 if (!torture_open_connection(&cli, 0)) {
9982 printf("starting ioctl test\n");
9984 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
9986 status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
9987 if (!NT_STATUS_IS_OK(status)) {
9988 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
9992 status = cli_raw_ioctl(cli, fnum, 0x2d0000 | (0x0420<<2), &blob);
9993 printf("ioctl device info: %s\n", nt_errstr(status));
9995 status = cli_raw_ioctl(cli, fnum, IOCTL_QUERY_JOB_INFO, &blob);
9996 printf("ioctl job info: %s\n", nt_errstr(status));
9998 for (device=0;device<0x100;device++) {
9999 printf("ioctl test with device = 0x%x\n", device);
10000 for (function=0;function<0x100;function++) {
10001 uint32_t code = (device<<16) | function;
10003 status = cli_raw_ioctl(cli, fnum, code, &blob);
10005 if (NT_STATUS_IS_OK(status)) {
10006 printf("ioctl 0x%x OK : %d bytes\n", (int)code,
10008 data_blob_free(&blob);
10013 if (!torture_close_connection(cli)) {
10022 tries variants of chkpath
10024 bool torture_chkpath_test(int dummy)
10026 static struct cli_state *cli;
10031 if (!torture_open_connection(&cli, 0)) {
10035 printf("starting chkpath test\n");
10037 /* cleanup from an old run */
10038 torture_deltree(cli, "\\chkpath.dir");
10040 status = cli_mkdir(cli, "\\chkpath.dir");
10041 if (!NT_STATUS_IS_OK(status)) {
10042 printf("mkdir1 failed : %s\n", nt_errstr(status));
10046 status = cli_mkdir(cli, "\\chkpath.dir\\dir2");
10047 if (!NT_STATUS_IS_OK(status)) {
10048 printf("mkdir2 failed : %s\n", nt_errstr(status));
10052 status = cli_openx(cli, "\\chkpath.dir\\foo.txt", O_RDWR|O_CREAT|O_EXCL,
10054 if (!NT_STATUS_IS_OK(status)) {
10055 printf("open1 failed (%s)\n", nt_errstr(status));
10058 cli_close(cli, fnum);
10060 status = cli_chkpath(cli, "\\chkpath.dir");
10061 if (!NT_STATUS_IS_OK(status)) {
10062 printf("chkpath1 failed: %s\n", nt_errstr(status));
10066 status = cli_chkpath(cli, "\\chkpath.dir\\dir2");
10067 if (!NT_STATUS_IS_OK(status)) {
10068 printf("chkpath2 failed: %s\n", nt_errstr(status));
10072 status = cli_chkpath(cli, "\\chkpath.dir\\foo.txt");
10073 if (!NT_STATUS_IS_OK(status)) {
10074 ret = check_error(__LINE__, status, ERRDOS, ERRbadpath,
10075 NT_STATUS_NOT_A_DIRECTORY);
10077 printf("* chkpath on a file should fail\n");
10081 status = cli_chkpath(cli, "\\chkpath.dir\\bar.txt");
10082 if (!NT_STATUS_IS_OK(status)) {
10083 ret = check_error(__LINE__, status, ERRDOS, ERRbadfile,
10084 NT_STATUS_OBJECT_NAME_NOT_FOUND);
10086 printf("* chkpath on a non existent file should fail\n");
10090 status = cli_chkpath(cli, "\\chkpath.dir\\dirxx\\bar.txt");
10091 if (!NT_STATUS_IS_OK(status)) {
10092 ret = check_error(__LINE__, status, ERRDOS, ERRbadpath,
10093 NT_STATUS_OBJECT_PATH_NOT_FOUND);
10095 printf("* chkpath on a non existent component should fail\n");
10099 torture_deltree(cli, "\\chkpath.dir");
10101 if (!torture_close_connection(cli)) {
10108 static bool run_eatest(int dummy)
10110 static struct cli_state *cli;
10111 const char *fname = "\\eatest.txt";
10112 bool correct = True;
10115 struct ea_struct *ea_list = NULL;
10116 TALLOC_CTX *mem_ctx = talloc_init("eatest");
10119 printf("starting eatest\n");
10121 if (!torture_open_connection(&cli, 0)) {
10122 talloc_destroy(mem_ctx);
10126 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
10128 status = cli_ntcreate(cli, fname, 0,
10129 FIRST_DESIRED_ACCESS, FILE_ATTRIBUTE_ARCHIVE,
10130 FILE_SHARE_NONE, FILE_OVERWRITE_IF,
10131 0x4044, 0, &fnum, NULL);
10132 if (!NT_STATUS_IS_OK(status)) {
10133 printf("open failed - %s\n", nt_errstr(status));
10134 talloc_destroy(mem_ctx);
10138 for (i = 0; i < 10; i++) {
10139 fstring ea_name, ea_val;
10141 slprintf(ea_name, sizeof(ea_name), "EA_%zu", i);
10142 memset(ea_val, (char)i+1, i+1);
10143 status = cli_set_ea_fnum(cli, fnum, ea_name, ea_val, i+1);
10144 if (!NT_STATUS_IS_OK(status)) {
10145 printf("ea_set of name %s failed - %s\n", ea_name,
10146 nt_errstr(status));
10147 talloc_destroy(mem_ctx);
10152 cli_close(cli, fnum);
10153 for (i = 0; i < 10; i++) {
10154 fstring ea_name, ea_val;
10156 slprintf(ea_name, sizeof(ea_name), "EA_%zu", i+10);
10157 memset(ea_val, (char)i+1, i+1);
10158 status = cli_set_ea_path(cli, fname, ea_name, ea_val, i+1);
10159 if (!NT_STATUS_IS_OK(status)) {
10160 printf("ea_set of name %s failed - %s\n", ea_name,
10161 nt_errstr(status));
10162 talloc_destroy(mem_ctx);
10167 status = cli_get_ea_list_path(cli, fname, mem_ctx, &num_eas, &ea_list);
10168 if (!NT_STATUS_IS_OK(status)) {
10169 printf("ea_get list failed - %s\n", nt_errstr(status));
10173 printf("num_eas = %d\n", (int)num_eas);
10175 if (num_eas != 20) {
10176 printf("Should be 20 EA's stored... failing.\n");
10180 for (i = 0; i < num_eas; i++) {
10181 printf("%zu: ea_name = %s. Val = ", i, ea_list[i].name);
10182 dump_data(0, ea_list[i].value.data,
10183 ea_list[i].value.length);
10186 /* Setting EA's to zero length deletes them. Test this */
10187 printf("Now deleting all EA's - case independent....\n");
10190 cli_set_ea_path(cli, fname, "", "", 0);
10192 for (i = 0; i < 20; i++) {
10194 slprintf(ea_name, sizeof(ea_name), "ea_%d", i);
10195 status = cli_set_ea_path(cli, fname, ea_name, "", 0);
10196 if (!NT_STATUS_IS_OK(status)) {
10197 printf("ea_set of name %s failed - %s\n", ea_name,
10198 nt_errstr(status));
10199 talloc_destroy(mem_ctx);
10205 status = cli_get_ea_list_path(cli, fname, mem_ctx, &num_eas, &ea_list);
10206 if (!NT_STATUS_IS_OK(status)) {
10207 printf("ea_get list failed - %s\n", nt_errstr(status));
10211 printf("num_eas = %d\n", (int)num_eas);
10212 for (i = 0; i < num_eas; i++) {
10213 printf("%zu: ea_name = %s. Val = ", i, ea_list[i].name);
10214 dump_data(0, ea_list[i].value.data,
10215 ea_list[i].value.length);
10218 if (num_eas != 0) {
10219 printf("deleting EA's failed.\n");
10223 /* Try and delete a non existent EA. */
10224 status = cli_set_ea_path(cli, fname, "foo", "", 0);
10225 if (!NT_STATUS_IS_OK(status)) {
10226 printf("deleting non-existent EA 'foo' should succeed. %s\n",
10227 nt_errstr(status));
10231 talloc_destroy(mem_ctx);
10232 if (!torture_close_connection(cli)) {
10239 static bool run_dirtest1(int dummy)
10242 static struct cli_state *cli;
10245 bool correct = True;
10247 printf("starting directory test\n");
10249 if (!torture_open_connection(&cli, 0)) {
10253 smbXcli_conn_set_sockopt(cli->conn, sockops);
10255 cli_list(cli, "\\LISTDIR\\*", 0, del_fn, cli);
10256 cli_list(cli, "\\LISTDIR\\*", FILE_ATTRIBUTE_DIRECTORY, del_fn, cli);
10257 cli_rmdir(cli, "\\LISTDIR");
10258 cli_mkdir(cli, "\\LISTDIR");
10260 /* Create 1000 files and 1000 directories. */
10261 for (i=0;i<1000;i++) {
10263 slprintf(fname, sizeof(fname), "\\LISTDIR\\f%d", i);
10264 if (!NT_STATUS_IS_OK(cli_ntcreate(cli, fname, 0, GENERIC_ALL_ACCESS, FILE_ATTRIBUTE_ARCHIVE,
10265 FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OVERWRITE_IF,
10266 0, 0, &fnum, NULL))) {
10267 fprintf(stderr,"Failed to open %s\n", fname);
10270 cli_close(cli, fnum);
10272 for (i=0;i<1000;i++) {
10274 slprintf(fname, sizeof(fname), "\\LISTDIR\\d%d", i);
10275 if (!NT_STATUS_IS_OK(cli_mkdir(cli, fname))) {
10276 fprintf(stderr,"Failed to open %s\n", fname);
10281 /* Now ensure that doing an old list sees both files and directories. */
10283 cli_list_old(cli, "\\LISTDIR\\*", FILE_ATTRIBUTE_DIRECTORY, list_fn, &num_seen);
10284 printf("num_seen = %d\n", num_seen );
10285 /* We should see 100 files + 1000 directories + . and .. */
10286 if (num_seen != 2002)
10289 /* Ensure if we have the "must have" bits we only see the
10290 * relevant entries.
10293 cli_list_old(cli, "\\LISTDIR\\*", (FILE_ATTRIBUTE_DIRECTORY<<8)|FILE_ATTRIBUTE_DIRECTORY, list_fn, &num_seen);
10294 printf("num_seen = %d\n", num_seen );
10295 if (num_seen != 1002)
10299 cli_list_old(cli, "\\LISTDIR\\*", (FILE_ATTRIBUTE_ARCHIVE<<8)|FILE_ATTRIBUTE_DIRECTORY, list_fn, &num_seen);
10300 printf("num_seen = %d\n", num_seen );
10301 if (num_seen != 1000)
10304 /* Delete everything. */
10305 cli_list(cli, "\\LISTDIR\\*", 0, del_fn, cli);
10306 cli_list(cli, "\\LISTDIR\\*", FILE_ATTRIBUTE_DIRECTORY, del_fn, cli);
10307 cli_rmdir(cli, "\\LISTDIR");
10310 printf("Matched %d\n", cli_list(cli, "a*.*", 0, list_fn, NULL));
10311 printf("Matched %d\n", cli_list(cli, "b*.*", 0, list_fn, NULL));
10312 printf("Matched %d\n", cli_list(cli, "xyzabc", 0, list_fn, NULL));
10315 if (!torture_close_connection(cli)) {
10319 printf("finished dirtest1\n");
10324 static bool run_error_map_extract(int dummy) {
10326 static struct cli_state *c_dos;
10327 static struct cli_state *c_nt;
10335 NTSTATUS nt_status;
10339 /* NT-Error connection */
10341 disable_spnego = true;
10342 if (!(c_nt = open_nbt_connection())) {
10343 disable_spnego = false;
10346 disable_spnego = false;
10348 status = smbXcli_negprot(c_nt->conn,
10356 if (!NT_STATUS_IS_OK(status)) {
10357 printf("%s rejected the NT-error negprot (%s)\n", host,
10358 nt_errstr(status));
10359 cli_shutdown(c_nt);
10363 status = cli_session_setup_anon(c_nt);
10364 if (!NT_STATUS_IS_OK(status)) {
10365 printf("%s rejected the NT-error initial session setup (%s)\n",host, nt_errstr(status));
10369 /* DOS-Error connection */
10371 disable_spnego = true;
10372 force_dos_errors = true;
10373 if (!(c_dos = open_nbt_connection())) {
10374 disable_spnego = false;
10375 force_dos_errors = false;
10378 disable_spnego = false;
10379 force_dos_errors = false;
10381 status = smbXcli_negprot(c_dos->conn,
10388 if (!NT_STATUS_IS_OK(status)) {
10389 printf("%s rejected the DOS-error negprot (%s)\n", host,
10390 nt_errstr(status));
10391 cli_shutdown(c_dos);
10395 status = cli_session_setup_anon(c_dos);
10396 if (!NT_STATUS_IS_OK(status)) {
10397 printf("%s rejected the DOS-error initial session setup (%s)\n",
10398 host, nt_errstr(status));
10402 c_nt->map_dos_errors = false;
10403 c_dos->map_dos_errors = false;
10405 for (error=(0xc0000000 | 0x1); error < (0xc0000000| 0xFFF); error++) {
10406 struct cli_credentials *user_creds = NULL;
10408 fstr_sprintf(user, "%X", error);
10410 user_creds = cli_session_creds_init(talloc_tos(),
10415 false, /* use_kerberos */
10416 false, /* fallback_after_kerberos */
10417 false, /* use_ccache */
10418 false); /* password_is_nt_hash */
10419 if (user_creds == NULL) {
10420 printf("cli_session_creds_init(%s) failed\n", user);
10424 status = cli_session_setup_creds(c_nt, user_creds);
10425 if (NT_STATUS_IS_OK(status)) {
10426 printf("/** Session setup succeeded. This shouldn't happen...*/\n");
10429 /* Case #1: 32-bit NT errors */
10430 if (!NT_STATUS_IS_DOS(status)) {
10431 nt_status = status;
10433 printf("/** Dos error on NT connection! (%s) */\n",
10434 nt_errstr(status));
10435 nt_status = NT_STATUS(0xc0000000);
10438 status = cli_session_setup_creds(c_dos, user_creds);
10439 if (NT_STATUS_IS_OK(status)) {
10440 printf("/** Session setup succeeded. This shouldn't happen...*/\n");
10443 /* Case #1: 32-bit NT errors */
10444 if (NT_STATUS_IS_DOS(status)) {
10445 printf("/** NT error on DOS connection! (%s) */\n",
10446 nt_errstr(status));
10447 errnum = errclass = 0;
10449 errclass = NT_STATUS_DOS_CLASS(status);
10450 errnum = NT_STATUS_DOS_CODE(status);
10453 if (NT_STATUS_V(nt_status) != error) {
10454 printf("/*\t{ This NT error code was 'sqashed'\n\t from %s to %s \n\t during the session setup }\n*/\n",
10455 get_nt_error_c_code(talloc_tos(), NT_STATUS(error)),
10456 get_nt_error_c_code(talloc_tos(), nt_status));
10459 printf("\t{%s,\t%s,\t%s},\n",
10460 smb_dos_err_class(errclass),
10461 smb_dos_err_name(errclass, errnum),
10462 get_nt_error_c_code(talloc_tos(), NT_STATUS(error)));
10464 TALLOC_FREE(user_creds);
10469 static bool run_sesssetup_bench(int dummy)
10471 static struct cli_state *c;
10472 const char *fname = "\\file.dat";
10477 if (!torture_open_connection(&c, 0)) {
10481 status = cli_ntcreate(c, fname, 0, GENERIC_ALL_ACCESS|DELETE_ACCESS,
10482 FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
10483 FILE_DELETE_ON_CLOSE, 0, &fnum, NULL);
10484 if (!NT_STATUS_IS_OK(status)) {
10485 d_printf("open %s failed: %s\n", fname, nt_errstr(status));
10489 for (i=0; i<torture_numops; i++) {
10490 status = cli_session_setup_creds(c, torture_creds);
10491 if (!NT_STATUS_IS_OK(status)) {
10492 d_printf("(%s) cli_session_setup_creds failed: %s\n",
10493 __location__, nt_errstr(status));
10497 d_printf("\r%d ", (int)cli_state_get_uid(c));
10499 status = cli_ulogoff(c);
10500 if (!NT_STATUS_IS_OK(status)) {
10501 d_printf("(%s) cli_ulogoff failed: %s\n",
10502 __location__, nt_errstr(status));
10510 static bool subst_test(const char *str, const char *user, const char *domain,
10511 uid_t uid, gid_t gid, const char *expected)
10514 bool result = true;
10516 subst = talloc_sub_specified(talloc_tos(), str, user, NULL, domain, uid, gid);
10518 if (strcmp(subst, expected) != 0) {
10519 printf("sub_specified(%s, %s, %s, %d, %d) returned [%s], expected "
10520 "[%s]\n", str, user, domain, (int)uid, (int)gid, subst,
10525 TALLOC_FREE(subst);
10529 static void chain1_open_completion(struct tevent_req *req)
10533 status = cli_openx_recv(req, &fnum);
10536 d_printf("cli_openx_recv returned %s: %d\n",
10538 NT_STATUS_IS_OK(status) ? fnum : -1);
10541 static void chain1_write_completion(struct tevent_req *req)
10545 status = cli_write_andx_recv(req, &written);
10548 d_printf("cli_write_andx_recv returned %s: %d\n",
10550 NT_STATUS_IS_OK(status) ? (int)written : -1);
10553 static void chain1_close_completion(struct tevent_req *req)
10556 bool *done = (bool *)tevent_req_callback_data_void(req);
10558 status = cli_close_recv(req);
10563 d_printf("cli_close returned %s\n", nt_errstr(status));
10566 static bool run_chain1(int dummy)
10568 struct cli_state *cli1;
10569 struct tevent_context *evt = samba_tevent_context_init(NULL);
10570 struct tevent_req *reqs[3], *smbreqs[3];
10572 const char *str = "foobar";
10573 const char *fname = "\\test_chain";
10576 printf("starting chain1 test\n");
10577 if (!torture_open_connection(&cli1, 0)) {
10581 smbXcli_conn_set_sockopt(cli1->conn, sockops);
10583 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
10585 reqs[0] = cli_openx_create(talloc_tos(), evt, cli1, fname,
10586 O_CREAT|O_RDWR, 0, &smbreqs[0]);
10587 if (reqs[0] == NULL) return false;
10588 tevent_req_set_callback(reqs[0], chain1_open_completion, NULL);
10591 reqs[1] = cli_write_andx_create(talloc_tos(), evt, cli1, 0, 0,
10592 (const uint8_t *)str, 0, strlen(str)+1,
10593 smbreqs, 1, &smbreqs[1]);
10594 if (reqs[1] == NULL) return false;
10595 tevent_req_set_callback(reqs[1], chain1_write_completion, NULL);
10597 reqs[2] = cli_smb1_close_create(talloc_tos(), evt, cli1, 0, &smbreqs[2]);
10598 if (reqs[2] == NULL) return false;
10599 tevent_req_set_callback(reqs[2], chain1_close_completion, &done);
10601 status = smb1cli_req_chain_submit(smbreqs, ARRAY_SIZE(smbreqs));
10602 if (!NT_STATUS_IS_OK(status)) {
10607 tevent_loop_once(evt);
10610 torture_close_connection(cli1);
10614 static void chain2_sesssetup_completion(struct tevent_req *req)
10617 status = cli_session_setup_guest_recv(req);
10618 d_printf("sesssetup returned %s\n", nt_errstr(status));
10621 static void chain2_tcon_completion(struct tevent_req *req)
10623 bool *done = (bool *)tevent_req_callback_data_void(req);
10625 status = cli_tcon_andx_recv(req);
10626 d_printf("tcon_and_x returned %s\n", nt_errstr(status));
10630 static bool run_chain2(int dummy)
10632 struct cli_state *cli1;
10633 struct tevent_context *evt = samba_tevent_context_init(NULL);
10634 struct tevent_req *reqs[2], *smbreqs[2];
10637 int flags = CLI_FULL_CONNECTION_FORCE_SMB1;
10639 printf("starting chain2 test\n");
10640 status = cli_start_connection(&cli1, lp_netbios_name(), host, NULL,
10641 port_to_use, SMB_SIGNING_DEFAULT, flags);
10642 if (!NT_STATUS_IS_OK(status)) {
10646 smbXcli_conn_set_sockopt(cli1->conn, sockops);
10648 reqs[0] = cli_session_setup_guest_create(talloc_tos(), evt, cli1,
10650 if (reqs[0] == NULL) return false;
10651 tevent_req_set_callback(reqs[0], chain2_sesssetup_completion, NULL);
10653 reqs[1] = cli_tcon_andx_create(talloc_tos(), evt, cli1, "IPC$",
10654 "?????", NULL, 0, &smbreqs[1]);
10655 if (reqs[1] == NULL) return false;
10656 tevent_req_set_callback(reqs[1], chain2_tcon_completion, &done);
10658 status = smb1cli_req_chain_submit(smbreqs, ARRAY_SIZE(smbreqs));
10659 if (!NT_STATUS_IS_OK(status)) {
10664 tevent_loop_once(evt);
10667 torture_close_connection(cli1);
10672 struct torture_createdel_state {
10673 struct tevent_context *ev;
10674 struct cli_state *cli;
10677 static void torture_createdel_created(struct tevent_req *subreq);
10678 static void torture_createdel_closed(struct tevent_req *subreq);
10680 static struct tevent_req *torture_createdel_send(TALLOC_CTX *mem_ctx,
10681 struct tevent_context *ev,
10682 struct cli_state *cli,
10685 struct tevent_req *req, *subreq;
10686 struct torture_createdel_state *state;
10688 req = tevent_req_create(mem_ctx, &state,
10689 struct torture_createdel_state);
10696 subreq = cli_ntcreate_send(
10697 state, ev, cli, name, 0,
10698 FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
10699 FILE_ATTRIBUTE_NORMAL,
10700 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
10701 FILE_OPEN_IF, FILE_DELETE_ON_CLOSE,
10702 SMB2_IMPERSONATION_IMPERSONATION, 0);
10704 if (tevent_req_nomem(subreq, req)) {
10705 return tevent_req_post(req, ev);
10707 tevent_req_set_callback(subreq, torture_createdel_created, req);
10711 static void torture_createdel_created(struct tevent_req *subreq)
10713 struct tevent_req *req = tevent_req_callback_data(
10714 subreq, struct tevent_req);
10715 struct torture_createdel_state *state = tevent_req_data(
10716 req, struct torture_createdel_state);
10720 status = cli_ntcreate_recv(subreq, &fnum, NULL);
10721 TALLOC_FREE(subreq);
10722 if (tevent_req_nterror(req, status)) {
10723 DEBUG(10, ("cli_ntcreate_recv returned %s\n",
10724 nt_errstr(status)));
10728 subreq = cli_close_send(state, state->ev, state->cli, fnum, 0);
10729 if (tevent_req_nomem(subreq, req)) {
10732 tevent_req_set_callback(subreq, torture_createdel_closed, req);
10735 static void torture_createdel_closed(struct tevent_req *subreq)
10737 struct tevent_req *req = tevent_req_callback_data(
10738 subreq, struct tevent_req);
10741 status = cli_close_recv(subreq);
10742 if (tevent_req_nterror(req, status)) {
10743 DEBUG(10, ("cli_close_recv returned %s\n", nt_errstr(status)));
10746 tevent_req_done(req);
10749 static NTSTATUS torture_createdel_recv(struct tevent_req *req)
10751 return tevent_req_simple_recv_ntstatus(req);
10754 struct torture_createdels_state {
10755 struct tevent_context *ev;
10756 struct cli_state *cli;
10757 const char *base_name;
10761 struct tevent_req **reqs;
10764 static void torture_createdels_done(struct tevent_req *subreq);
10766 static struct tevent_req *torture_createdels_send(TALLOC_CTX *mem_ctx,
10767 struct tevent_context *ev,
10768 struct cli_state *cli,
10769 const char *base_name,
10773 struct tevent_req *req;
10774 struct torture_createdels_state *state;
10777 req = tevent_req_create(mem_ctx, &state,
10778 struct torture_createdels_state);
10784 state->base_name = talloc_strdup(state, base_name);
10785 if (tevent_req_nomem(state->base_name, req)) {
10786 return tevent_req_post(req, ev);
10788 state->num_files = MAX(num_parallel, num_files);
10790 state->received = 0;
10792 state->reqs = talloc_array(state, struct tevent_req *, num_parallel);
10793 if (tevent_req_nomem(state->reqs, req)) {
10794 return tevent_req_post(req, ev);
10797 for (i=0; i<num_parallel; i++) {
10800 name = talloc_asprintf(state, "%s%8.8d", state->base_name,
10802 if (tevent_req_nomem(name, req)) {
10803 return tevent_req_post(req, ev);
10805 state->reqs[i] = torture_createdel_send(
10806 state->reqs, state->ev, state->cli, name);
10807 if (tevent_req_nomem(state->reqs[i], req)) {
10808 return tevent_req_post(req, ev);
10810 name = talloc_move(state->reqs[i], &name);
10811 tevent_req_set_callback(state->reqs[i],
10812 torture_createdels_done, req);
10818 static void torture_createdels_done(struct tevent_req *subreq)
10820 struct tevent_req *req = tevent_req_callback_data(
10821 subreq, struct tevent_req);
10822 struct torture_createdels_state *state = tevent_req_data(
10823 req, struct torture_createdels_state);
10824 size_t i, num_parallel = talloc_array_length(state->reqs);
10828 status = torture_createdel_recv(subreq);
10829 if (!NT_STATUS_IS_OK(status)){
10830 DEBUG(10, ("torture_createdel_recv returned %s\n",
10831 nt_errstr(status)));
10832 TALLOC_FREE(subreq);
10833 tevent_req_nterror(req, status);
10837 for (i=0; i<num_parallel; i++) {
10838 if (subreq == state->reqs[i]) {
10842 if (i == num_parallel) {
10843 DEBUG(10, ("received something we did not send\n"));
10844 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
10847 TALLOC_FREE(state->reqs[i]);
10849 if (state->sent >= state->num_files) {
10850 tevent_req_done(req);
10854 name = talloc_asprintf(state, "%s%8.8d", state->base_name,
10856 if (tevent_req_nomem(name, req)) {
10859 state->reqs[i] = torture_createdel_send(state->reqs, state->ev,
10861 if (tevent_req_nomem(state->reqs[i], req)) {
10864 name = talloc_move(state->reqs[i], &name);
10865 tevent_req_set_callback(state->reqs[i], torture_createdels_done, req);
10869 static NTSTATUS torture_createdels_recv(struct tevent_req *req)
10871 return tevent_req_simple_recv_ntstatus(req);
10874 struct swallow_notify_state {
10875 struct tevent_context *ev;
10876 struct cli_state *cli;
10878 uint32_t completion_filter;
10880 bool (*fn)(uint32_t action, const char *name, void *priv);
10884 static void swallow_notify_done(struct tevent_req *subreq);
10886 static struct tevent_req *swallow_notify_send(TALLOC_CTX *mem_ctx,
10887 struct tevent_context *ev,
10888 struct cli_state *cli,
10890 uint32_t completion_filter,
10892 bool (*fn)(uint32_t action,
10897 struct tevent_req *req, *subreq;
10898 struct swallow_notify_state *state;
10900 req = tevent_req_create(mem_ctx, &state,
10901 struct swallow_notify_state);
10907 state->fnum = fnum;
10908 state->completion_filter = completion_filter;
10909 state->recursive = recursive;
10911 state->priv = priv;
10913 subreq = cli_notify_send(state, state->ev, state->cli, state->fnum,
10914 0xffff, state->completion_filter,
10916 if (tevent_req_nomem(subreq, req)) {
10917 return tevent_req_post(req, ev);
10919 tevent_req_set_callback(subreq, swallow_notify_done, req);
10923 static void swallow_notify_done(struct tevent_req *subreq)
10925 struct tevent_req *req = tevent_req_callback_data(
10926 subreq, struct tevent_req);
10927 struct swallow_notify_state *state = tevent_req_data(
10928 req, struct swallow_notify_state);
10930 uint32_t i, num_changes;
10931 struct notify_change *changes;
10933 status = cli_notify_recv(subreq, state, &num_changes, &changes);
10934 TALLOC_FREE(subreq);
10935 if (!NT_STATUS_IS_OK(status)) {
10936 DEBUG(10, ("cli_notify_recv returned %s\n",
10937 nt_errstr(status)));
10938 tevent_req_nterror(req, status);
10942 for (i=0; i<num_changes; i++) {
10943 state->fn(changes[i].action, changes[i].name, state->priv);
10945 TALLOC_FREE(changes);
10947 subreq = cli_notify_send(state, state->ev, state->cli, state->fnum,
10948 0xffff, state->completion_filter,
10950 if (tevent_req_nomem(subreq, req)) {
10953 tevent_req_set_callback(subreq, swallow_notify_done, req);
10956 static bool print_notifies(uint32_t action, const char *name, void *priv)
10958 if (DEBUGLEVEL > 5) {
10959 d_printf("%d %s\n", (int)action, name);
10964 static void notify_bench_done(struct tevent_req *req)
10966 int *num_finished = (int *)tevent_req_callback_data_void(req);
10967 *num_finished += 1;
10970 static bool run_notify_bench(int dummy)
10972 const char *dname = "\\notify-bench";
10973 struct tevent_context *ev;
10976 struct tevent_req *req1;
10977 struct tevent_req *req2 = NULL;
10978 int i, num_unc_names;
10979 int num_finished = 0;
10981 printf("starting notify-bench test\n");
10983 if (use_multishare_conn) {
10985 unc_list = file_lines_load(multishare_conn_fname,
10986 &num_unc_names, 0, NULL);
10987 if (!unc_list || num_unc_names <= 0) {
10988 d_printf("Failed to load unc names list from '%s'\n",
10989 multishare_conn_fname);
10992 TALLOC_FREE(unc_list);
10997 ev = samba_tevent_context_init(talloc_tos());
10999 d_printf("tevent_context_init failed\n");
11003 for (i=0; i<num_unc_names; i++) {
11004 struct cli_state *cli;
11007 base_fname = talloc_asprintf(talloc_tos(), "%s\\file%3.3d.",
11009 if (base_fname == NULL) {
11013 if (!torture_open_connection(&cli, i)) {
11017 status = cli_ntcreate(cli, dname, 0,
11018 MAXIMUM_ALLOWED_ACCESS,
11019 0, FILE_SHARE_READ|FILE_SHARE_WRITE|
11021 FILE_OPEN_IF, FILE_DIRECTORY_FILE, 0,
11024 if (!NT_STATUS_IS_OK(status)) {
11025 d_printf("Could not create %s: %s\n", dname,
11026 nt_errstr(status));
11030 req1 = swallow_notify_send(talloc_tos(), ev, cli, dnum,
11031 FILE_NOTIFY_CHANGE_FILE_NAME |
11032 FILE_NOTIFY_CHANGE_DIR_NAME |
11033 FILE_NOTIFY_CHANGE_ATTRIBUTES |
11034 FILE_NOTIFY_CHANGE_LAST_WRITE,
11035 false, print_notifies, NULL);
11036 if (req1 == NULL) {
11037 d_printf("Could not create notify request\n");
11041 req2 = torture_createdels_send(talloc_tos(), ev, cli,
11042 base_fname, 10, torture_numops);
11043 if (req2 == NULL) {
11044 d_printf("Could not create createdels request\n");
11047 TALLOC_FREE(base_fname);
11049 tevent_req_set_callback(req2, notify_bench_done,
11053 while (num_finished < num_unc_names) {
11055 ret = tevent_loop_once(ev);
11057 d_printf("tevent_loop_once failed\n");
11062 if (!tevent_req_poll(req2, ev)) {
11063 d_printf("tevent_req_poll failed\n");
11066 status = torture_createdels_recv(req2);
11067 d_printf("torture_createdels_recv returned %s\n", nt_errstr(status));
11072 static bool run_mangle1(int dummy)
11074 struct cli_state *cli;
11075 const char *fname = "this_is_a_long_fname_to_be_mangled.txt";
11080 printf("starting mangle1 test\n");
11081 if (!torture_open_connection(&cli, 0)) {
11085 smbXcli_conn_set_sockopt(cli->conn, sockops);
11087 status = cli_ntcreate(cli, fname, 0, GENERIC_ALL_ACCESS|DELETE_ACCESS,
11088 FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
11089 0, 0, &fnum, NULL);
11090 if (!NT_STATUS_IS_OK(status)) {
11091 d_printf("open %s failed: %s\n", fname, nt_errstr(status));
11094 cli_close(cli, fnum);
11096 status = cli_qpathinfo_alt_name(cli, fname, alt_name);
11097 if (!NT_STATUS_IS_OK(status)) {
11098 d_printf("cli_qpathinfo_alt_name failed: %s\n",
11099 nt_errstr(status));
11102 d_printf("alt_name: %s\n", alt_name);
11104 status = cli_openx(cli, alt_name, O_RDONLY, DENY_NONE, &fnum);
11105 if (!NT_STATUS_IS_OK(status)) {
11106 d_printf("cli_openx(%s) failed: %s\n", alt_name,
11107 nt_errstr(status));
11110 cli_close(cli, fnum);
11112 status = cli_qpathinfo1(cli, alt_name, NULL, NULL, NULL, NULL, NULL);
11113 if (!NT_STATUS_IS_OK(status)) {
11114 d_printf("cli_qpathinfo1(%s) failed: %s\n", alt_name,
11115 nt_errstr(status));
11122 static NTSTATUS mangle_illegal_list_shortname_fn(struct file_info *f,
11126 if (f->short_name == NULL) {
11127 return NT_STATUS_OK;
11130 if (strlen(f->short_name) == 0) {
11131 return NT_STATUS_OK;
11134 printf("unexpected shortname: %s\n", f->short_name);
11136 return NT_STATUS_OBJECT_NAME_INVALID;
11139 static NTSTATUS mangle_illegal_list_name_fn(struct file_info *f,
11143 char *name = state;
11145 printf("name: %s\n", f->name);
11146 fstrcpy(name, f->name);
11147 return NT_STATUS_OK;
11150 static bool run_mangle_illegal(int dummy)
11152 struct cli_state *cli = NULL;
11153 struct cli_state *cli_posix = NULL;
11154 const char *fname = "\\MANGLE_ILLEGAL\\this_is_a_long_fname_to_be_mangled.txt";
11155 const char *illegal_fname = "MANGLE_ILLEGAL/foo:bar";
11156 char *mangled_path = NULL;
11162 printf("starting mangle-illegal test\n");
11164 if (!torture_open_connection(&cli, 0)) {
11168 smbXcli_conn_set_sockopt(cli->conn, sockops);
11170 if (!torture_open_connection(&cli_posix, 0)) {
11174 smbXcli_conn_set_sockopt(cli_posix->conn, sockops);
11176 status = torture_setup_unix_extensions(cli_posix);
11177 if (!NT_STATUS_IS_OK(status)) {
11181 cli_rmdir(cli, "\\MANGLE_ILLEGAL");
11182 status = cli_mkdir(cli, "\\MANGLE_ILLEGAL");
11183 if (!NT_STATUS_IS_OK(status)) {
11184 printf("mkdir1 failed : %s\n", nt_errstr(status));
11189 * Create a file with illegal NTFS characters and test that we
11190 * get a usable mangled name
11193 cli_setatr(cli_posix, illegal_fname, 0, 0);
11194 cli_posix_unlink(cli_posix, illegal_fname);
11196 status = cli_posix_open(cli_posix, illegal_fname, O_RDWR|O_CREAT|O_EXCL,
11198 if (!NT_STATUS_IS_OK(status)) {
11199 printf("POSIX create of %s failed (%s)\n",
11200 illegal_fname, nt_errstr(status));
11204 status = cli_close(cli_posix, fnum);
11205 if (!NT_STATUS_IS_OK(status)) {
11206 printf("close failed (%s)\n", nt_errstr(status));
11210 status = cli_list(cli, "\\MANGLE_ILLEGAL\\*", 0, mangle_illegal_list_name_fn, &name);
11211 if (!NT_STATUS_IS_OK(status)) {
11212 d_printf("cli_list failed: %s\n", nt_errstr(status));
11216 mangled_path = talloc_asprintf(talloc_tos(), "\\MANGLE_ILLEGAL\\%s", name);
11217 if (mangled_path == NULL) {
11221 status = cli_openx(cli, mangled_path, O_RDONLY, DENY_NONE, &fnum);
11222 if (!NT_STATUS_IS_OK(status)) {
11223 d_printf("cli_openx(%s) failed: %s\n", mangled_path, nt_errstr(status));
11224 TALLOC_FREE(mangled_path);
11227 TALLOC_FREE(mangled_path);
11228 cli_close(cli, fnum);
11230 cli_setatr(cli_posix, illegal_fname, 0, 0);
11231 cli_posix_unlink(cli_posix, illegal_fname);
11234 * Create a file with a long name and check that we got *no* short name.
11237 status = cli_ntcreate(cli, fname, 0, GENERIC_ALL_ACCESS|DELETE_ACCESS,
11238 FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
11239 0, 0, &fnum, NULL);
11240 if (!NT_STATUS_IS_OK(status)) {
11241 d_printf("open %s failed: %s\n", fname, nt_errstr(status));
11244 cli_close(cli, fnum);
11246 status = cli_list(cli, fname, 0, mangle_illegal_list_shortname_fn, &alt_name);
11247 if (!NT_STATUS_IS_OK(status)) {
11248 d_printf("cli_list failed\n");
11252 cli_unlink(cli, fname, 0);
11253 cli_rmdir(cli, "\\MANGLE_ILLEGAL");
11255 if (!torture_close_connection(cli_posix)) {
11259 if (!torture_close_connection(cli)) {
11266 static size_t null_source(uint8_t *buf, size_t n, void *priv)
11268 size_t *to_pull = (size_t *)priv;
11269 size_t thistime = *to_pull;
11271 thistime = MIN(thistime, n);
11272 if (thistime == 0) {
11276 memset(buf, 0, thistime);
11277 *to_pull -= thistime;
11281 static bool run_windows_write(int dummy)
11283 struct cli_state *cli1;
11287 const char *fname = "\\writetest.txt";
11288 struct timeval start_time;
11293 printf("starting windows_write test\n");
11294 if (!torture_open_connection(&cli1, 0)) {
11298 status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
11299 if (!NT_STATUS_IS_OK(status)) {
11300 printf("open failed (%s)\n", nt_errstr(status));
11304 smbXcli_conn_set_sockopt(cli1->conn, sockops);
11306 start_time = timeval_current();
11308 for (i=0; i<torture_numops; i++) {
11310 off_t start = i * torture_blocksize;
11311 size_t to_pull = torture_blocksize - 1;
11313 status = cli_writeall(cli1, fnum, 0, &c,
11314 start + torture_blocksize - 1, 1, NULL);
11315 if (!NT_STATUS_IS_OK(status)) {
11316 printf("cli_write failed: %s\n", nt_errstr(status));
11320 status = cli_push(cli1, fnum, 0, i * torture_blocksize, torture_blocksize,
11321 null_source, &to_pull);
11322 if (!NT_STATUS_IS_OK(status)) {
11323 printf("cli_push returned: %s\n", nt_errstr(status));
11328 seconds = timeval_elapsed(&start_time);
11329 kbytes = (double)torture_blocksize * torture_numops;
11332 printf("Wrote %d kbytes in %.2f seconds: %d kb/sec\n", (int)kbytes,
11333 (double)seconds, (int)(kbytes/seconds));
11337 cli_close(cli1, fnum);
11338 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
11339 torture_close_connection(cli1);
11343 static size_t calc_expected_return(struct cli_state *cli, size_t len_requested)
11345 size_t max_pdu = 0x1FFFF;
11347 if (cli->server_posix_capabilities & CIFS_UNIX_LARGE_READ_CAP) {
11348 max_pdu = 0xFFFFFF;
11351 if (smb1cli_conn_signing_is_active(cli->conn)) {
11355 if (smb1cli_conn_encryption_on(cli->conn)) {
11356 max_pdu = CLI_BUFFER_SIZE;
11359 if ((len_requested & 0xFFFF0000) == 0xFFFF0000) {
11360 len_requested &= 0xFFFF;
11363 return MIN(len_requested,
11364 max_pdu - (MIN_SMB_SIZE + VWV(12) + 1 /* padding byte */));
11367 static bool check_read_call(struct cli_state *cli,
11370 size_t len_requested)
11373 struct tevent_req *subreq = NULL;
11374 ssize_t len_read = 0;
11375 size_t len_expected = 0;
11376 struct tevent_context *ev = NULL;
11378 ev = samba_tevent_context_init(talloc_tos());
11383 subreq = cli_read_andx_send(talloc_tos(),
11390 if (!tevent_req_poll_ntstatus(subreq, ev, &status)) {
11394 status = cli_read_andx_recv(subreq, &len_read, &buf);
11395 if (!NT_STATUS_IS_OK(status)) {
11396 d_printf("cli_read_andx_recv failed: %s\n", nt_errstr(status));
11400 TALLOC_FREE(subreq);
11403 len_expected = calc_expected_return(cli, len_requested);
11405 if (len_expected > 0x10000 && len_read == 0x10000) {
11406 /* Windows servers only return a max of 0x10000,
11407 doesn't matter if you set CAP_LARGE_READX in
11408 the client sessionsetupX call or not. */
11409 d_printf("Windows server - returned 0x10000 on a read of 0x%x\n",
11410 (unsigned int)len_requested);
11411 } else if (len_read != len_expected) {
11412 d_printf("read of 0x%x failed: got 0x%x, expected 0x%x\n",
11413 (unsigned int)len_requested,
11414 (unsigned int)len_read,
11415 (unsigned int)len_expected);
11418 d_printf("Correct read reply.\n");
11424 /* Test large readX variants. */
11425 static bool large_readx_tests(struct cli_state *cli,
11429 /* A read of 0xFFFF0001 should *always* return 1 byte. */
11430 if (check_read_call(cli, fnum, buf, 0xFFFF0001) == false) {
11433 /* A read of 0x10000 should return 0x10000 bytes. */
11434 if (check_read_call(cli, fnum, buf, 0x10000) == false) {
11437 /* A read of 0x10000 should return 0x10001 bytes. */
11438 if (check_read_call(cli, fnum, buf, 0x10001) == false) {
11441 /* A read of 0x1FFFF - (MIN_SMB_SIZE + VWV(12) should return
11442 the requested number of bytes. */
11443 if (check_read_call(cli, fnum, buf, 0x1FFFF - (MIN_SMB_SIZE + VWV(12))) == false) {
11446 /* A read of 1MB should return 1MB bytes (on Samba). */
11447 if (check_read_call(cli, fnum, buf, 0x100000) == false) {
11451 if (check_read_call(cli, fnum, buf, 0x20001) == false) {
11454 if (check_read_call(cli, fnum, buf, 0x22000001) == false) {
11457 if (check_read_call(cli, fnum, buf, 0xFFFE0001) == false) {
11463 static bool run_large_readx(int dummy)
11465 uint8_t *buf = NULL;
11466 struct cli_state *cli1 = NULL;
11467 struct cli_state *cli2 = NULL;
11468 bool correct = false;
11469 const char *fname = "\\large_readx.dat";
11471 uint16_t fnum1 = UINT16_MAX;
11472 uint32_t normal_caps = 0;
11473 size_t file_size = 20*1024*1024;
11474 TALLOC_CTX *frame = talloc_stackframe();
11478 enum smb_signing_setting signing_setting;
11479 enum protocol_types protocol;
11483 .signing_setting = SMB_SIGNING_IF_REQUIRED,
11484 .protocol = PROTOCOL_NT1,
11486 .name = "NT1 - SIGNING_REQUIRED",
11487 .signing_setting = SMB_SIGNING_REQUIRED,
11488 .protocol = PROTOCOL_NT1,
11492 printf("starting large_readx test\n");
11494 if (!torture_open_connection(&cli1, 0)) {
11498 normal_caps = smb1cli_conn_capabilities(cli1->conn);
11500 if (!(normal_caps & CAP_LARGE_READX)) {
11501 d_printf("Server doesn't have CAP_LARGE_READX 0x%x\n",
11502 (unsigned int)normal_caps);
11506 /* Create a file of size 4MB. */
11507 status = cli_ntcreate(cli1, fname, 0, GENERIC_ALL_ACCESS,
11508 FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
11509 0, 0, &fnum1, NULL);
11511 if (!NT_STATUS_IS_OK(status)) {
11512 d_printf("open %s failed: %s\n", fname, nt_errstr(status));
11516 /* Write file_size bytes. */
11517 buf = talloc_zero_array(frame, uint8_t, file_size);
11522 status = cli_writeall(cli1,
11529 if (!NT_STATUS_IS_OK(status)) {
11530 d_printf("cli_writeall failed: %s\n", nt_errstr(status));
11534 status = cli_close(cli1, fnum1);
11535 if (!NT_STATUS_IS_OK(status)) {
11536 d_printf("cli_close failed: %s\n", nt_errstr(status));
11540 fnum1 = UINT16_MAX;
11542 for (i=0; i < ARRAY_SIZE(runs); i++) {
11543 enum smb_signing_setting saved_signing_setting = signing_state;
11544 uint16_t fnum2 = -1;
11547 (runs[i].signing_setting == SMB_SIGNING_REQUIRED))
11549 d_printf("skip[%u] - %s\n", (unsigned)i, runs[i].name);
11553 d_printf("run[%u] - %s\n", (unsigned)i, runs[i].name);
11555 signing_state = runs[i].signing_setting;
11556 cli2 = open_nbt_connection();
11557 signing_state = saved_signing_setting;
11558 if (cli2 == NULL) {
11562 status = smbXcli_negprot(cli2->conn,
11569 if (!NT_STATUS_IS_OK(status)) {
11573 status = cli_session_setup_creds(cli2, torture_creds);
11574 if (!NT_STATUS_IS_OK(status)) {
11578 status = cli_tree_connect(cli2,
11582 if (!NT_STATUS_IS_OK(status)) {
11586 cli_set_timeout(cli2, 120000); /* set a really long timeout (2 minutes) */
11588 normal_caps = smb1cli_conn_capabilities(cli2->conn);
11590 if (!(normal_caps & CAP_LARGE_READX)) {
11591 d_printf("Server doesn't have CAP_LARGE_READX 0x%x\n",
11592 (unsigned int)normal_caps);
11597 if (force_cli_encryption(cli2, share) == false) {
11600 } else if (SERVER_HAS_UNIX_CIFS(cli2)) {
11601 uint16_t major, minor;
11602 uint32_t caplow, caphigh;
11604 status = cli_unix_extensions_version(cli2,
11606 &caplow, &caphigh);
11607 if (!NT_STATUS_IS_OK(status)) {
11612 status = cli_ntcreate(cli2, fname, 0, FILE_READ_DATA,
11613 FILE_ATTRIBUTE_NORMAL, 0, FILE_OPEN,
11614 0, 0, &fnum2, NULL);
11615 if (!NT_STATUS_IS_OK(status)) {
11616 d_printf("Second open %s failed: %s\n", fname, nt_errstr(status));
11620 /* All reads must return less than file_size bytes. */
11621 if (!large_readx_tests(cli2, fnum2, buf)) {
11625 status = cli_close(cli2, fnum2);
11626 if (!NT_STATUS_IS_OK(status)) {
11627 d_printf("cli_close failed: %s\n", nt_errstr(status));
11632 if (!torture_close_connection(cli2)) {
11639 printf("Success on large_readx test\n");
11644 if (!torture_close_connection(cli2)) {
11650 if (fnum1 != UINT16_MAX) {
11651 status = cli_close(cli1, fnum1);
11652 if (!NT_STATUS_IS_OK(status)) {
11653 d_printf("cli_close failed: %s\n", nt_errstr(status));
11655 fnum1 = UINT16_MAX;
11658 status = cli_unlink(cli1, fname,
11659 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
11660 if (!NT_STATUS_IS_OK(status)) {
11661 printf("unlink failed (%s)\n", nt_errstr(status));
11664 if (!torture_close_connection(cli1)) {
11669 TALLOC_FREE(frame);
11671 printf("finished large_readx test\n");
11675 static NTSTATUS msdfs_attribute_list_fn(struct file_info *finfo,
11677 void *private_data)
11679 uint32_t *p_attr = (uint32_t *)private_data;
11681 if (strequal(finfo->name, test_filename)) {
11682 *p_attr = finfo->attr;
11685 return NT_STATUS_OK;
11688 static bool run_msdfs_attribute(int dummy)
11690 static struct cli_state *cli;
11691 bool correct = false;
11695 printf("Starting MSDFS-ATTRIBUTE test\n");
11697 if (test_filename == NULL || test_filename[0] == '\0') {
11698 printf("MSDFS-ATTRIBUTE test "
11699 "needs -f filename-of-msdfs-link\n");
11704 * NB. We use torture_open_connection_flags() not
11705 * torture_open_connection() as the latter forces
11708 if (!torture_open_connection_flags(&cli, 0, 0)) {
11712 smbXcli_conn_set_sockopt(cli->conn, sockops);
11714 status = cli_list(cli,
11716 FILE_ATTRIBUTE_DIRECTORY,
11717 msdfs_attribute_list_fn,
11720 if (!NT_STATUS_IS_OK(status)) {
11721 printf("cli_list failed with %s\n",
11722 nt_errstr(status));
11725 if ((attr & FILE_ATTRIBUTE_REPARSE_POINT) == 0) {
11726 printf("file %s should have "
11727 "FILE_ATTRIBUTE_REPARSE_POINT set. attr = 0x%x\n",
11729 (unsigned int)attr);
11733 if ((attr & FILE_ATTRIBUTE_DIRECTORY) == 0) {
11734 printf("file %s should have "
11735 "FILE_ATTRIBUTE_DIRECTORY set. attr = 0x%x\n",
11737 (unsigned int)attr);
11745 torture_close_connection(cli);
11749 static bool run_cli_echo(int dummy)
11751 struct cli_state *cli;
11754 printf("starting cli_echo test\n");
11755 if (!torture_open_connection(&cli, 0)) {
11758 smbXcli_conn_set_sockopt(cli->conn, sockops);
11760 status = cli_echo(cli, 5, data_blob_const("hello", 5));
11762 d_printf("cli_echo returned %s\n", nt_errstr(status));
11764 torture_close_connection(cli);
11765 return NT_STATUS_IS_OK(status);
11768 static int splice_status(off_t written, void *priv)
11773 static bool run_cli_splice(int dummy)
11775 uint8_t *buf = NULL;
11776 struct cli_state *cli1 = NULL;
11777 bool correct = false;
11778 const char *fname_src = "\\splice_src.dat";
11779 const char *fname_dst = "\\splice_dst.dat";
11781 uint16_t fnum1 = UINT16_MAX;
11782 uint16_t fnum2 = UINT16_MAX;
11783 size_t file_size = 2*1024*1024;
11784 size_t splice_size = 1*1024*1024 + 713;
11785 uint8_t digest1[16], digest2[16];
11788 TALLOC_CTX *frame = talloc_stackframe();
11790 printf("starting cli_splice test\n");
11792 if (!torture_open_connection(&cli1, 0)) {
11796 cli_unlink(cli1, fname_src,
11797 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
11798 cli_unlink(cli1, fname_dst,
11799 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
11801 /* Create a file */
11802 status = cli_ntcreate(cli1, fname_src, 0, GENERIC_ALL_ACCESS,
11803 FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
11804 0, 0, &fnum1, NULL);
11806 if (!NT_STATUS_IS_OK(status)) {
11807 d_printf("open %s failed: %s\n", fname_src, nt_errstr(status));
11811 /* Write file_size bytes - must be bigger than splice_size. */
11812 buf = talloc_zero_array(frame, uint8_t, file_size);
11814 d_printf("talloc_fail\n");
11818 /* Fill it with random numbers. */
11819 generate_random_buffer(buf, file_size);
11821 /* MD5 the first 1MB + 713 bytes. */
11822 gnutls_hash_fast(GNUTLS_DIG_MD5,
11827 status = cli_writeall(cli1,
11834 if (!NT_STATUS_IS_OK(status)) {
11835 d_printf("cli_writeall failed: %s\n", nt_errstr(status));
11839 status = cli_ntcreate(cli1, fname_dst, 0, GENERIC_ALL_ACCESS,
11840 FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
11841 0, 0, &fnum2, NULL);
11843 if (!NT_STATUS_IS_OK(status)) {
11844 d_printf("open %s failed: %s\n", fname_dst, nt_errstr(status));
11848 /* Now splice 1MB + 713 bytes. */
11849 status = cli_splice(cli1,
11860 if (!NT_STATUS_IS_OK(status)) {
11861 d_printf("cli_splice failed: %s\n", nt_errstr(status));
11865 /* Clear the old buffer. */
11866 memset(buf, '\0', file_size);
11868 /* Read the new file. */
11869 status = cli_read(cli1, fnum2, (char *)buf, 0, splice_size, &nread);
11870 if (!NT_STATUS_IS_OK(status)) {
11871 d_printf("cli_read failed: %s\n", nt_errstr(status));
11874 if (nread != splice_size) {
11875 d_printf("bad read of 0x%x, should be 0x%x\n",
11876 (unsigned int)nread,
11877 (unsigned int)splice_size);
11881 /* MD5 the first 1MB + 713 bytes. */
11882 gnutls_hash_fast(GNUTLS_DIG_MD5,
11887 /* Must be the same. */
11888 if (memcmp(digest1, digest2, 16) != 0) {
11889 d_printf("bad MD5 compare\n");
11894 printf("Success on cli_splice test\n");
11899 if (fnum1 != UINT16_MAX) {
11900 cli_close(cli1, fnum1);
11902 if (fnum2 != UINT16_MAX) {
11903 cli_close(cli1, fnum2);
11906 cli_unlink(cli1, fname_src,
11907 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
11908 cli_unlink(cli1, fname_dst,
11909 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
11911 if (!torture_close_connection(cli1)) {
11916 TALLOC_FREE(frame);
11920 static bool run_uid_regression_test(int dummy)
11922 static struct cli_state *cli;
11925 bool correct = True;
11926 struct smbXcli_tcon *tcon_copy = NULL;
11929 printf("starting uid regression test\n");
11931 if (!torture_open_connection(&cli, 0)) {
11935 smbXcli_conn_set_sockopt(cli->conn, sockops);
11937 /* Ok - now save then logoff our current user. */
11938 old_vuid = cli_state_get_uid(cli);
11940 status = cli_ulogoff(cli);
11941 if (!NT_STATUS_IS_OK(status)) {
11942 d_printf("(%s) cli_ulogoff failed: %s\n",
11943 __location__, nt_errstr(status));
11948 cli_state_set_uid(cli, old_vuid);
11950 /* Try an operation. */
11951 status = cli_mkdir(cli, "\\uid_reg_test");
11952 if (NT_STATUS_IS_OK(status)) {
11953 d_printf("(%s) cli_mkdir succeeded\n",
11958 /* Should be bad uid. */
11959 if (!check_error(__LINE__, status, ERRSRV, ERRbaduid,
11960 NT_STATUS_USER_SESSION_DELETED)) {
11966 old_cnum = cli_state_get_tid(cli);
11968 * This is an SMB1-only test.
11969 * Copy the tcon, not "save/restore".
11971 * In SMB1 the cli_tdis() below frees
11972 * cli->smb1.tcon so we need a copy
11973 * of the struct to put back for the
11974 * second tdis call with invalid vuid.
11976 * This is a test-only hack. Real client code
11977 * uses cli_state_save_tcon_share()/cli_state_restore_tcon_share().
11979 tcon_copy = smbXcli_tcon_copy(cli, cli->smb1.tcon);
11980 if (tcon_copy == NULL) {
11985 /* Now try a SMBtdis with the invalid vuid set to zero. */
11986 cli_state_set_uid(cli, 0);
11988 /* This should succeed. */
11989 status = cli_tdis(cli);
11991 if (NT_STATUS_IS_OK(status)) {
11992 d_printf("First tdis with invalid vuid should succeed.\n");
11994 d_printf("First tdis failed (%s)\n", nt_errstr(status));
11996 cli->smb1.tcon = tcon_copy;
12000 cli->smb1.tcon = tcon_copy;
12001 cli_state_set_uid(cli, old_vuid);
12002 cli_state_set_tid(cli, old_cnum);
12004 /* This should fail. */
12005 status = cli_tdis(cli);
12006 if (NT_STATUS_IS_OK(status)) {
12007 d_printf("Second tdis with invalid vuid should fail - succeeded instead !.\n");
12011 /* Should be bad tid. */
12012 if (!check_error(__LINE__, status, ERRSRV, ERRinvnid,
12013 NT_STATUS_NETWORK_NAME_DELETED)) {
12019 cli_rmdir(cli, "\\uid_reg_test");
12028 static const char *illegal_chars = "*\\/?<>|\":";
12029 static char force_shortname_chars[] = " +,.[];=\177";
12031 static NTSTATUS shortname_del_fn(struct file_info *finfo,
12032 const char *mask, void *state)
12034 struct cli_state *pcli = (struct cli_state *)state;
12036 NTSTATUS status = NT_STATUS_OK;
12038 slprintf(fname, sizeof(fname), "\\shortname\\%s", finfo->name);
12040 if (strcmp(finfo->name, ".") == 0 || strcmp(finfo->name, "..") == 0)
12041 return NT_STATUS_OK;
12043 if (finfo->attr & FILE_ATTRIBUTE_DIRECTORY) {
12044 status = cli_rmdir(pcli, fname);
12045 if (!NT_STATUS_IS_OK(status)) {
12046 printf("del_fn: failed to rmdir %s\n,", fname );
12049 status = cli_unlink(pcli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
12050 if (!NT_STATUS_IS_OK(status)) {
12051 printf("del_fn: failed to unlink %s\n,", fname );
12063 static NTSTATUS shortname_list_fn(struct file_info *finfo,
12064 const char *name, void *state)
12066 struct sn_state *s = (struct sn_state *)state;
12070 printf("shortname list: i = %d, name = |%s|, shortname = |%s|\n",
12071 i, finfo->name, finfo->short_name);
12074 if (strchr(force_shortname_chars, i)) {
12075 if (!finfo->short_name) {
12076 /* Shortname not created when it should be. */
12077 d_printf("(%s) ERROR: Shortname was not created for file %s containing %d\n",
12078 __location__, finfo->name, i);
12081 } else if (finfo->short_name){
12082 /* Shortname created when it should not be. */
12083 d_printf("(%s) ERROR: Shortname %s was created for file %s\n",
12084 __location__, finfo->short_name, finfo->name);
12088 return NT_STATUS_OK;
12091 static bool run_shortname_test(int dummy)
12093 static struct cli_state *cli;
12094 bool correct = True;
12100 printf("starting shortname test\n");
12102 if (!torture_open_connection(&cli, 0)) {
12106 smbXcli_conn_set_sockopt(cli->conn, sockops);
12108 cli_list(cli, "\\shortname\\*", 0, shortname_del_fn, cli);
12109 cli_list(cli, "\\shortname\\*", FILE_ATTRIBUTE_DIRECTORY, shortname_del_fn, cli);
12110 cli_rmdir(cli, "\\shortname");
12112 status = cli_mkdir(cli, "\\shortname");
12113 if (!NT_STATUS_IS_OK(status)) {
12114 d_printf("(%s) cli_mkdir of \\shortname failed: %s\n",
12115 __location__, nt_errstr(status));
12120 if (strlcpy(fname, "\\shortname\\", sizeof(fname)) >= sizeof(fname)) {
12124 if (strlcat(fname, "test .txt", sizeof(fname)) >= sizeof(fname)) {
12131 for (i = 32; i < 128; i++) {
12132 uint16_t fnum = (uint16_t)-1;
12136 if (strchr(illegal_chars, i)) {
12141 status = cli_ntcreate(cli, fname, 0, GENERIC_ALL_ACCESS, FILE_ATTRIBUTE_NORMAL,
12142 FILE_SHARE_READ|FILE_SHARE_WRITE,
12143 FILE_OVERWRITE_IF, 0, 0, &fnum, NULL);
12144 if (!NT_STATUS_IS_OK(status)) {
12145 d_printf("(%s) cli_nt_create of %s failed: %s\n",
12146 __location__, fname, nt_errstr(status));
12150 cli_close(cli, fnum);
12153 status = cli_list(cli, "\\shortname\\test*.*", 0,
12154 shortname_list_fn, &s);
12155 if (s.matched != 1) {
12156 d_printf("(%s) failed to list %s: %s\n",
12157 __location__, fname, nt_errstr(status));
12162 status = cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
12163 if (!NT_STATUS_IS_OK(status)) {
12164 d_printf("(%s) failed to delete %s: %s\n",
12165 __location__, fname, nt_errstr(status));
12178 cli_list(cli, "\\shortname\\*", 0, shortname_del_fn, cli);
12179 cli_list(cli, "\\shortname\\*", FILE_ATTRIBUTE_DIRECTORY, shortname_del_fn, cli);
12180 cli_rmdir(cli, "\\shortname");
12181 torture_close_connection(cli);
12185 TLDAPRC callback_code;
12187 static void pagedsearch_cb(struct tevent_req *req)
12190 struct tldap_message *msg;
12193 rc = tldap_search_paged_recv(req, talloc_tos(), &msg);
12194 if (!TLDAP_RC_IS_SUCCESS(rc)) {
12195 d_printf("tldap_search_paged_recv failed: %s\n",
12196 tldap_rc2string(rc));
12197 callback_code = rc;
12200 if (tldap_msg_type(msg) != TLDAP_RES_SEARCH_ENTRY) {
12204 if (!tldap_entry_dn(msg, &dn)) {
12205 d_printf("tldap_entry_dn failed\n");
12208 d_printf("%s\n", dn);
12212 enum tldap_extended_val {
12219 * Construct an extended dn control with either no value, 0 or 1
12221 * No value and 0 are equivalent (non-hyphenated GUID)
12222 * 1 has the hyphenated GUID
12224 static struct tldap_control *
12225 tldap_build_extended_control(enum tldap_extended_val val)
12227 struct tldap_control empty_control;
12228 struct asn1_data *data;
12230 ZERO_STRUCT(empty_control);
12232 if (val != EXTENDED_NONE) {
12233 data = asn1_init(talloc_tos(), ASN1_MAX_TREE_DEPTH);
12239 if (!asn1_push_tag(data, ASN1_SEQUENCE(0))) {
12243 if (!asn1_write_Integer(data, (int)val)) {
12247 if (!asn1_pop_tag(data)) {
12251 if (!asn1_blob(data, &empty_control.value)) {
12256 empty_control.oid = "1.2.840.113556.1.4.529";
12257 empty_control.critical = true;
12259 return tldap_add_control(talloc_tos(), NULL, 0, &empty_control);
12263 static bool tldap_test_dn_guid_format(struct tldap_context *ld, const char *basedn,
12264 enum tldap_extended_val control_val)
12266 struct tldap_control *control = tldap_build_extended_control(control_val);
12268 struct tldap_message **msg;
12271 rc = tldap_search(ld, basedn, TLDAP_SCOPE_BASE,
12272 "(objectClass=*)", NULL, 0, 0,
12274 0, 0, 0, 0, talloc_tos(), &msg);
12275 if (!TLDAP_RC_IS_SUCCESS(rc)) {
12276 d_printf("tldap_search for domain DN failed: %s\n",
12277 tldap_errstr(talloc_tos(), ld, rc));
12281 if (!tldap_entry_dn(msg[0], &dn)) {
12282 d_printf("tldap_search domain DN fetch failed: %s\n",
12283 tldap_errstr(talloc_tos(), ld, rc));
12287 d_printf("%s\n", dn);
12290 uint32_t time_mid, time_hi_and_version;
12291 uint32_t clock_seq[2];
12295 switch (control_val) {
12296 case EXTENDED_NONE:
12297 case EXTENDED_ZERO:
12299 * When reading GUIDs with hyphens, scanf will treat
12300 * hyphen as a hex character (and counts as part of the
12301 * width). This creates leftover GUID string which we
12302 * check will for with 'next' and closing '>'.
12304 if (12 == sscanf(dn, "<GUID=%08x%04x%04x%02x%02x%02x%02x%02x%02x%02x%02x>%c",
12305 &time_low, &time_mid,
12306 &time_hi_and_version, &clock_seq[0],
12307 &clock_seq[1], &node[0], &node[1],
12308 &node[2], &node[3], &node[4],
12309 &node[5], &next)) {
12310 /* This GUID is good */
12312 d_printf("GUID format in control (no hyphens) doesn't match output\n");
12318 if (12 == sscanf(dn,
12319 "<GUID=%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x>%c",
12320 &time_low, &time_mid,
12321 &time_hi_and_version, &clock_seq[0],
12322 &clock_seq[1], &node[0], &node[1],
12323 &node[2], &node[3], &node[4],
12324 &node[5], &next)) {
12325 /* This GUID is good */
12327 d_printf("GUID format in control (with hyphens) doesn't match output\n");
12340 static bool run_tldap(int dummy)
12342 struct tldap_context *ld;
12346 struct sockaddr_storage addr;
12347 struct tevent_context *ev;
12348 struct tevent_req *req;
12350 const char *filter;
12351 struct loadparm_context *lp_ctx = NULL;
12352 int tcp_port = 389;
12353 bool use_tls = false;
12354 bool use_starttls = false;
12355 int wrap_flags = -1;
12356 uint32_t gensec_features = 0;
12358 lp_ctx = loadparm_init_s3(talloc_tos(), loadparm_s3_helpers());
12360 wrap_flags = lpcfg_client_ldap_sasl_wrapping(lp_ctx);
12362 if (wrap_flags & ADS_AUTH_SASL_LDAPS) {
12365 } else if (wrap_flags & ADS_AUTH_SASL_STARTTLS) {
12367 use_starttls = true;
12369 if (wrap_flags & ADS_AUTH_SASL_SEAL) {
12370 gensec_features |= GENSEC_FEATURE_SEAL;
12372 if (wrap_flags & ADS_AUTH_SASL_SIGN) {
12373 gensec_features |= GENSEC_FEATURE_SIGN;
12376 if (gensec_features != 0) {
12377 gensec_features |= GENSEC_FEATURE_LDAP_STYLE;
12380 if (!resolve_name(host, &addr, 0, false)) {
12381 d_printf("could not find host %s\n", host);
12384 status = open_socket_out(&addr, tcp_port, 9999, &fd);
12385 if (!NT_STATUS_IS_OK(status)) {
12386 d_printf("open_socket_out failed: %s\n", nt_errstr(status));
12390 ld = tldap_context_create(talloc_tos(), fd);
12393 d_printf("tldap_context_create failed\n");
12397 if (use_tls && !tldap_has_tls_tstream(ld)) {
12398 tldap_set_starttls_needed(ld, use_starttls);
12400 rc = tldap_tls_connect(ld, lp_ctx, host);
12401 if (!TLDAP_RC_IS_SUCCESS(rc)) {
12402 DBG_ERR("tldap_tls_connect(%s) failed: %s\n",
12403 host, tldap_errstr(talloc_tos(), ld, rc));
12408 rc = tldap_fetch_rootdse(ld);
12409 if (!TLDAP_RC_IS_SUCCESS(rc)) {
12410 d_printf("tldap_fetch_rootdse failed: %s\n",
12411 tldap_errstr(talloc_tos(), ld, rc));
12415 basedn = tldap_talloc_single_attribute(
12416 tldap_rootdse(ld), "defaultNamingContext", talloc_tos());
12417 if (basedn == NULL) {
12418 d_printf("no defaultNamingContext\n");
12421 d_printf("defaultNamingContext: %s\n", basedn);
12423 ev = samba_tevent_context_init(talloc_tos());
12425 d_printf("tevent_context_init failed\n");
12429 rc = tldap_gensec_bind(ld, torture_creds, "ldap", host, NULL,
12430 lp_ctx, gensec_features);
12431 if (!TLDAP_RC_IS_SUCCESS(rc)) {
12432 d_printf("tldap_gensec_bind failed\n");
12436 callback_code = TLDAP_SUCCESS;
12438 req = tldap_search_paged_send(talloc_tos(), ev, ld, basedn,
12439 TLDAP_SCOPE_SUB, "(objectclass=*)",
12441 NULL, 0, NULL, 0, 0, 0, 0, 5);
12443 d_printf("tldap_search_paged_send failed\n");
12446 tevent_req_set_callback(req, pagedsearch_cb, NULL);
12448 tevent_req_poll(req, ev);
12452 rc = callback_code;
12454 if (!TLDAP_RC_IS_SUCCESS(rc)) {
12455 d_printf("tldap_search with paging failed: %s\n",
12456 tldap_errstr(talloc_tos(), ld, rc));
12460 /* test search filters against rootDSE */
12461 filter = "(&(|(name=samba)(nextRid<=10000000)(usnChanged>=10)(samba~=ambas)(!(name=s*m*a)))"
12462 "(|(name:=samba)(name:dn:2.5.13.5:=samba)(:dn:2.5.13.5:=samba)(!(name=*samba))))";
12464 rc = tldap_search(ld, "", TLDAP_SCOPE_BASE, filter,
12465 NULL, 0, 0, NULL, 0, NULL, 0, 0, 0, 0,
12466 talloc_tos(), NULL);
12467 if (!TLDAP_RC_IS_SUCCESS(rc)) {
12468 d_printf("tldap_search with complex filter failed: %s\n",
12469 tldap_errstr(talloc_tos(), ld, rc));
12474 * Tests to check for regression of:
12476 * https://bugzilla.samba.org/show_bug.cgi?id=14029
12478 * TLDAP used here to pick apart the original string DN (with GUID)
12480 if (!tldap_test_dn_guid_format(ld, basedn, EXTENDED_NONE)) {
12481 d_printf("tldap_search with extended dn (no val) failed: %s\n",
12482 tldap_errstr(talloc_tos(), ld, rc));
12485 if (!tldap_test_dn_guid_format(ld, basedn, EXTENDED_ZERO)) {
12486 d_printf("tldap_search with extended dn (0) failed: %s\n",
12487 tldap_errstr(talloc_tos(), ld, rc));
12490 if (!tldap_test_dn_guid_format(ld, basedn, EXTENDED_ONE)) {
12491 d_printf("tldap_search with extended dn (1) failed: %s\n",
12492 tldap_errstr(talloc_tos(), ld, rc));
12500 /* Torture test to ensure no regression of :
12501 https://bugzilla.samba.org/show_bug.cgi?id=7084
12504 static bool run_dir_createtime(int dummy)
12506 struct cli_state *cli;
12507 const char *dname = "\\testdir_createtime";
12508 const char *fname = "\\testdir_createtime\\testfile";
12510 struct timespec create_time;
12511 struct timespec create_time1;
12516 if (!torture_open_connection(&cli, 0)) {
12520 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
12521 /* Ensure ino is zero, SMB2 gets a real one. */
12524 /* Ensure ino is -1, SMB1 never gets a real one. */
12525 ino = (uint64_t)-1;
12528 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
12529 cli_rmdir(cli, dname);
12531 status = cli_mkdir(cli, dname);
12532 if (!NT_STATUS_IS_OK(status)) {
12533 printf("mkdir failed: %s\n", nt_errstr(status));
12537 status = cli_qpathinfo2(cli,
12547 if (!NT_STATUS_IS_OK(status)) {
12548 printf("cli_qpathinfo2 returned %s\n",
12549 nt_errstr(status));
12553 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
12554 /* SMB2 should always return an inode. */
12556 printf("SMB2 bad inode (0)\n");
12560 /* SMB1 must always return zero here. */
12562 printf("SMB1 bad inode (!0)\n");
12567 /* Sleep 3 seconds, then create a file. */
12570 status = cli_openx(cli, fname, O_RDWR | O_CREAT | O_EXCL,
12572 if (!NT_STATUS_IS_OK(status)) {
12573 printf("cli_openx failed: %s\n", nt_errstr(status));
12577 status = cli_qpathinfo2(cli,
12587 if (!NT_STATUS_IS_OK(status)) {
12588 printf("cli_qpathinfo2 (2) returned %s\n",
12589 nt_errstr(status));
12593 if (timespec_compare(&create_time1, &create_time)) {
12594 printf("run_dir_createtime: create time was updated (error)\n");
12596 printf("run_dir_createtime: create time was not updated (correct)\n");
12602 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
12603 cli_rmdir(cli, dname);
12604 if (!torture_close_connection(cli)) {
12611 static bool run_streamerror(int dummy)
12613 struct cli_state *cli;
12614 const char *dname = "\\testdir_streamerror";
12615 const char *streamname =
12616 "testdir_streamerror:{4c8cc155-6c1e-11d1-8e41-00c04fb9386d}:$DATA";
12618 time_t change_time, access_time, write_time;
12624 if (!torture_open_connection(&cli, 0)) {
12628 torture_deltree(cli, dname);
12630 status = cli_mkdir(cli, dname);
12631 if (!NT_STATUS_IS_OK(status)) {
12632 printf("mkdir failed: %s\n", nt_errstr(status));
12636 status = cli_qpathinfo1(cli, streamname, &change_time, &access_time,
12637 &write_time, &size, &attr);
12638 if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
12639 printf("pathinfo returned %s, expected "
12640 "NT_STATUS_OBJECT_NAME_NOT_FOUND\n",
12641 nt_errstr(status));
12645 status = cli_ntcreate(cli, streamname, 0x16,
12646 FILE_READ_DATA|FILE_READ_EA|
12647 FILE_READ_ATTRIBUTES|READ_CONTROL_ACCESS,
12648 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ,
12649 FILE_OPEN, 0, 0, &fnum, NULL);
12651 if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
12652 printf("ntcreate returned %s, expected "
12653 "NT_STATUS_OBJECT_NAME_NOT_FOUND\n",
12654 nt_errstr(status));
12659 cli_rmdir(cli, dname);
12663 struct pidtest_state {
12669 static void pid_echo_done(struct tevent_req *subreq);
12671 static struct tevent_req *pid_echo_send(TALLOC_CTX *mem_ctx,
12672 struct tevent_context *ev,
12673 struct cli_state *cli)
12675 struct tevent_req *req, *subreq;
12676 struct pidtest_state *state;
12678 req = tevent_req_create(mem_ctx, &state, struct pidtest_state);
12683 SSVAL(state->vwv, 0, 1);
12684 state->data = data_blob_const("hello", 5);
12686 subreq = smb1cli_req_send(state,
12690 0, 0, /* *_flags */
12691 0, 0, /* *_flags2 */
12693 0xDEADBEEF, /* pid */
12695 NULL, /* session */
12696 ARRAY_SIZE(state->vwv), state->vwv,
12697 state->data.length, state->data.data);
12699 if (tevent_req_nomem(subreq, req)) {
12700 return tevent_req_post(req, ev);
12702 tevent_req_set_callback(subreq, pid_echo_done, req);
12706 static void pid_echo_done(struct tevent_req *subreq)
12708 struct tevent_req *req = tevent_req_callback_data(
12709 subreq, struct tevent_req);
12710 struct pidtest_state *state = tevent_req_data(
12711 req, struct pidtest_state);
12713 uint32_t num_bytes;
12714 uint8_t *bytes = NULL;
12715 struct iovec *recv_iov = NULL;
12716 uint8_t *phdr = NULL;
12717 uint16_t pidlow = 0;
12718 uint16_t pidhigh = 0;
12719 struct smb1cli_req_expected_response expected[] = {
12721 .status = NT_STATUS_OK,
12726 status = smb1cli_req_recv(subreq, state,
12731 NULL, /* pvwv_offset */
12734 NULL, /* pbytes_offset */
12736 expected, ARRAY_SIZE(expected));
12738 TALLOC_FREE(subreq);
12740 if (!NT_STATUS_IS_OK(status)) {
12741 tevent_req_nterror(req, status);
12745 if (num_bytes != state->data.length) {
12746 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
12750 if (memcmp(bytes, state->data.data, num_bytes) != 0) {
12751 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
12755 /* Check pid low/high == DEADBEEF */
12756 pidlow = SVAL(phdr, HDR_PID);
12757 if (pidlow != 0xBEEF){
12758 printf("Incorrect pidlow 0x%x, should be 0xBEEF\n",
12759 (unsigned int)pidlow);
12760 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
12763 pidhigh = SVAL(phdr, HDR_PIDHIGH);
12764 if (pidhigh != 0xDEAD){
12765 printf("Incorrect pidhigh 0x%x, should be 0xDEAD\n",
12766 (unsigned int)pidhigh);
12767 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
12771 tevent_req_done(req);
12774 static NTSTATUS pid_echo_recv(struct tevent_req *req)
12776 return tevent_req_simple_recv_ntstatus(req);
12779 static bool run_pidhigh(int dummy)
12781 bool success = false;
12782 struct cli_state *cli = NULL;
12784 struct tevent_context *ev = NULL;
12785 struct tevent_req *req = NULL;
12786 TALLOC_CTX *frame = talloc_stackframe();
12788 printf("starting pid high test\n");
12789 if (!torture_open_connection(&cli, 0)) {
12792 smbXcli_conn_set_sockopt(cli->conn, sockops);
12794 ev = samba_tevent_context_init(frame);
12799 req = pid_echo_send(frame, ev, cli);
12804 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
12808 status = pid_echo_recv(req);
12809 if (NT_STATUS_IS_OK(status)) {
12810 printf("pid high test ok\n");
12816 TALLOC_FREE(frame);
12817 torture_close_connection(cli);
12822 Test Windows open on a bad POSIX symlink.
12824 static bool run_symlink_open_test(int dummy)
12826 static struct cli_state *cli;
12827 const char *fname = "non_existant_file";
12828 const char *sname = "dangling_symlink";
12829 uint16_t fnum = (uint16_t)-1;
12830 bool correct = false;
12832 TALLOC_CTX *frame = NULL;
12834 frame = talloc_stackframe();
12836 printf("Starting Windows bad symlink open test\n");
12838 if (!torture_open_connection(&cli, 0)) {
12839 TALLOC_FREE(frame);
12843 smbXcli_conn_set_sockopt(cli->conn, sockops);
12845 status = torture_setup_unix_extensions(cli);
12846 if (!NT_STATUS_IS_OK(status)) {
12847 TALLOC_FREE(frame);
12851 /* Ensure nothing exists. */
12852 cli_setatr(cli, fname, 0, 0);
12853 cli_posix_unlink(cli, fname);
12854 cli_setatr(cli, sname, 0, 0);
12855 cli_posix_unlink(cli, sname);
12857 /* Create a symlink pointing nowhere. */
12858 status = cli_posix_symlink(cli, fname, sname);
12859 if (!NT_STATUS_IS_OK(status)) {
12860 printf("cli_posix_symlink of %s -> %s failed (%s)\n",
12863 nt_errstr(status));
12867 /* Now ensure that a Windows open doesn't hang. */
12868 status = cli_ntcreate(cli,
12871 FILE_READ_DATA|FILE_WRITE_DATA,
12873 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
12881 * We get either NT_STATUS_OBJECT_NAME_NOT_FOUND or
12882 * NT_STATUS_OBJECT_PATH_NOT_FOUND depending on if
12883 * we use O_NOFOLLOW on the server or not.
12885 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND) ||
12886 NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_PATH_NOT_FOUND))
12890 printf("cli_ntcreate of %s returned %s - should return"
12891 " either (%s) or (%s)\n",
12894 nt_errstr(NT_STATUS_OBJECT_NAME_NOT_FOUND),
12895 nt_errstr(NT_STATUS_OBJECT_PATH_NOT_FOUND));
12903 if (fnum != (uint16_t)-1) {
12904 cli_close(cli, fnum);
12905 fnum = (uint16_t)-1;
12908 cli_setatr(cli, sname, 0, 0);
12909 cli_posix_unlink(cli, sname);
12910 cli_setatr(cli, fname, 0, 0);
12911 cli_posix_unlink(cli, fname);
12913 if (!torture_close_connection(cli)) {
12917 TALLOC_FREE(frame);
12921 static NTSTATUS smb1_wild_mangle_list_fn(struct file_info *finfo,
12925 char **mangled_name_return = (char **)state;
12926 bool is_mangled = strchr(finfo->name, '~');
12929 *mangled_name_return = talloc_strdup(NULL, finfo->name);
12930 if (*mangled_name_return == NULL) {
12931 return NT_STATUS_NO_MEMORY;
12934 return NT_STATUS_OK;
12937 static bool run_smb1_wild_mangle_unlink_test(int dummy)
12939 static struct cli_state *cli_posix = NULL;
12940 static struct cli_state *cli = NULL;
12941 uint16_t fnum = (uint16_t)-1;
12942 bool correct = false;
12943 const char *dname = "smb1_wild_mangle_unlink";
12944 const char *aname = "smb1_wild_mangle_unlink/a";
12945 const char *star_name = "smb1_wild_mangle_unlink/*";
12946 char *windows_unlink_name = NULL;
12947 char *mangled_name = NULL;
12950 printf("Starting SMB1 wild mangle unlink test\n");
12952 /* Open a Windows connection. */
12953 if (!torture_open_connection(&cli, 0)) {
12957 smbXcli_conn_set_sockopt(cli->conn, sockops);
12959 /* Open a POSIX connection. */
12960 if (!torture_open_connection(&cli_posix, 0)) {
12964 smbXcli_conn_set_sockopt(cli_posix->conn, sockops);
12966 status = torture_setup_unix_extensions(cli_posix);
12967 if (!NT_STATUS_IS_OK(status)) {
12968 printf("server doesn't support POSIX\n");
12973 torture_deltree(cli, dname);
12976 * Create two files - 'a' and '*'.
12977 * We need POSIX extensions for this as '*'
12978 * is not a valid Windows name.
12981 status = cli_mkdir(cli, dname);
12982 if (!NT_STATUS_IS_OK(status)) {
12983 printf("cli_mkdir of %s returned %s\n",
12985 nt_errstr(status));
12989 status = cli_posix_open(cli_posix,
12991 O_RDWR|O_CREAT|O_EXCL,
12994 if (!NT_STATUS_IS_OK(status)) {
12995 printf("cli_posix_open (create) of %s returned %s\n",
12997 nt_errstr(status));
13000 status = cli_close(cli_posix, fnum);
13001 if (!NT_STATUS_IS_OK(status)) {
13004 status = cli_posix_open(cli_posix,
13006 O_RDWR|O_CREAT|O_EXCL,
13009 if (!NT_STATUS_IS_OK(status)) {
13010 printf("cli_posix_open (create) of %s returned %s\n",
13012 nt_errstr(status));
13015 status = cli_close(cli_posix, fnum);
13016 if (!NT_STATUS_IS_OK(status)) {
13020 status = cli_list(cli,
13023 smb1_wild_mangle_list_fn,
13025 if (!NT_STATUS_IS_OK(status)) {
13026 printf("cli_list of %s returned %s\n",
13028 nt_errstr(status));
13032 if (mangled_name == NULL) {
13036 printf("mangled_name = %s\n",
13040 * Try a Windows unlink with the mangled name.
13041 * This should *NOT* unlink the 'a' name.
13044 windows_unlink_name = talloc_asprintf(cli_posix,
13049 status = cli_unlink(cli, windows_unlink_name, 0);
13050 if (!NT_STATUS_IS_OK(status)) {
13051 printf("cli_unlink of %s returned %s\n",
13052 windows_unlink_name,
13053 nt_errstr(status));
13057 /* Does 'a' still exist ? */
13058 status = cli_posix_open(cli_posix,
13063 if (!NT_STATUS_IS_OK(status)) {
13064 printf("cli_posix_open O_RNONLY of %s returned %s\n",
13066 nt_errstr(status));
13070 status = cli_close(cli_posix, fnum);
13071 if (!NT_STATUS_IS_OK(status)) {
13079 TALLOC_FREE(windows_unlink_name);
13080 TALLOC_FREE(mangled_name);
13083 torture_deltree(cli, dname);
13084 torture_close_connection(cli);
13087 if (cli_posix != NULL) {
13088 torture_close_connection(cli_posix);
13094 static bool run_smb1_wild_mangle_rename_test(int dummy)
13096 static struct cli_state *cli_posix = NULL;
13097 static struct cli_state *cli = NULL;
13098 uint16_t fnum = (uint16_t)-1;
13099 bool correct = false;
13100 const char *dname = "smb1_wild_mangle_rename";
13101 const char *fooname = "smb1_wild_mangle_rename/foo";
13102 const char *foostar_name = "smb1_wild_mangle_rename/fo*";
13103 const char *wild_name = "smb1_wild_mangle_rename/*";
13104 char *windows_rename_src = NULL;
13105 const char *windows_rename_dst = "smb1_wild_mangle_rename\\bar";
13106 char *mangled_name = NULL;
13109 printf("Starting SMB1 wild mangle rename test\n");
13111 if (!torture_open_connection(&cli_posix, 0)) {
13115 smbXcli_conn_set_sockopt(cli_posix->conn, sockops);
13117 status = torture_setup_unix_extensions(cli_posix);
13118 if (!NT_STATUS_IS_OK(status)) {
13119 printf("server doesn't support POSIX\n");
13123 /* Open a Windows connection. */
13124 if (!torture_open_connection(&cli, 0)) {
13128 smbXcli_conn_set_sockopt(cli->conn, sockops);
13130 /* Ensure we start from fresh. */
13131 torture_deltree(cli, dname);
13134 * Create two files - 'foo' and 'fo*'.
13135 * We need POSIX extensions for this as 'fo*'
13136 * is not a valid Windows name.
13139 status = cli_posix_mkdir(cli_posix, dname, 0770);
13140 if (!NT_STATUS_IS_OK(status)) {
13141 printf("cli_posix_mkdir of %s returned %s\n",
13143 nt_errstr(status));
13147 status = cli_posix_open(cli_posix,
13149 O_RDWR|O_CREAT|O_EXCL,
13152 if (!NT_STATUS_IS_OK(status)) {
13153 printf("cli_posix_open (create) of %s returned %s\n",
13155 nt_errstr(status));
13158 status = cli_close(cli_posix, fnum);
13159 if (!NT_STATUS_IS_OK(status)) {
13162 status = cli_posix_open(cli_posix,
13164 O_RDWR|O_CREAT|O_EXCL,
13167 if (!NT_STATUS_IS_OK(status)) {
13168 printf("cli_posix_open (create) of %s returned %s\n",
13170 nt_errstr(status));
13173 status = cli_close(cli_posix, fnum);
13174 if (!NT_STATUS_IS_OK(status)) {
13179 * Get the mangled name. We can re-use the
13180 * previous smb1_wild_mangle_list_fn for this.
13183 status = cli_list(cli,
13186 smb1_wild_mangle_list_fn,
13188 if (!NT_STATUS_IS_OK(status)) {
13189 printf("cli_list of %s returned %s\n",
13191 nt_errstr(status));
13195 if (mangled_name == NULL) {
13199 printf("mangled_name = %s\n",
13203 * Try a Windows rename with the mangled name.
13204 * This should *NOT* rename the 'foo' name.
13207 windows_rename_src = talloc_asprintf(cli_posix,
13212 status = cli_rename(cli,
13213 windows_rename_src,
13214 windows_rename_dst,
13216 if (!NT_STATUS_IS_OK(status)) {
13217 printf("cli_rename of %s -> %s returned %s\n",
13218 windows_rename_src,
13219 windows_rename_dst,
13220 nt_errstr(status));
13224 /* Does 'foo' still exist ? */
13225 status = cli_posix_open(cli_posix,
13230 if (!NT_STATUS_IS_OK(status)) {
13231 printf("cli_posix_open O_RNONLY of %s returned %s\n",
13233 nt_errstr(status));
13237 status = cli_close(cli_posix, fnum);
13238 if (!NT_STATUS_IS_OK(status)) {
13246 TALLOC_FREE(mangled_name);
13247 TALLOC_FREE(windows_rename_src);
13250 torture_deltree(cli, dname);
13251 torture_close_connection(cli);
13254 torture_close_connection(cli_posix);
13260 * Only testing minimal time strings, as the others
13261 * need (locale-dependent) guessing at what strftime does and
13262 * even may differ in builds.
13264 static bool timesubst_test(void)
13266 TALLOC_CTX *ctx = NULL;
13267 /* Sa 23. Dez 04:33:20 CET 2017 */
13268 const struct timeval tv = { 1514000000, 123 };
13269 const char* expect_minimal = "20171223_033320";
13270 const char* expect_minus = "20171223_033320_000123";
13272 char *env_tz, *orig_tz = NULL;
13273 bool result = true;
13275 ctx = talloc_new(NULL);
13277 env_tz = getenv("TZ");
13279 orig_tz = talloc_strdup(ctx, env_tz);
13281 setenv("TZ", "UTC", 1);
13283 s = minimal_timeval_string(ctx, &tv, false);
13285 if(!s || strcmp(s, expect_minimal)) {
13286 printf("minimal_timeval_string(ctx, tv, false) returned [%s], expected "
13287 "[%s]\n", s ? s : "<nil>", expect_minimal);
13291 s = minimal_timeval_string(ctx, &tv, true);
13292 if(!s || strcmp(s, expect_minus)) {
13293 printf("minimal_timeval_string(ctx, tv, true) returned [%s], expected "
13294 "[%s]\n", s ? s : "<nil>", expect_minus);
13300 setenv("TZ", orig_tz, 1);
13307 static bool run_local_substitute(int dummy)
13311 ok &= subst_test("%U", "bla", "", -1, -1, "bla");
13312 ok &= subst_test("%u%U", "bla", "", -1, -1, "blabla");
13313 ok &= subst_test("%g", "", "", -1, -1, "NO_GROUP");
13314 ok &= subst_test("%G", "", "", -1, -1, "NO_GROUP");
13315 ok &= subst_test("%g", "", "", -1, 0, gidtoname(0));
13316 ok &= subst_test("%G", "", "", -1, 0, gidtoname(0));
13317 ok &= subst_test("%D%u", "u", "dom", -1, 0, "domu");
13318 ok &= subst_test("%i %I", "", "", -1, -1, "0.0.0.0 0.0.0.0");
13319 ok &= subst_test("%j %J", "", "", -1, -1, "0_0_0_0 0_0_0_0");
13320 /* Substitution depends on current time, so better test the underlying
13321 formatting function. At least covers %t. */
13322 ok &= timesubst_test();
13324 /* Different captialization rules in sub_basic... */
13326 ok &= (strcmp(talloc_sub_basic(talloc_tos(), "BLA", "dom", "%U%D"),
13332 static bool run_local_base64(int dummy)
13337 for (i=1; i<2000; i++) {
13338 DATA_BLOB blob1, blob2;
13341 blob1.data = talloc_array(talloc_tos(), uint8_t, i);
13343 generate_random_buffer(blob1.data, blob1.length);
13345 b64 = base64_encode_data_blob(talloc_tos(), blob1);
13347 d_fprintf(stderr, "base64_encode_data_blob failed "
13348 "for %d bytes\n", i);
13351 blob2 = base64_decode_data_blob(b64);
13354 if (data_blob_cmp(&blob1, &blob2)) {
13355 d_fprintf(stderr, "data_blob_cmp failed for %d "
13359 TALLOC_FREE(blob1.data);
13360 data_blob_free(&blob2);
13365 static void parse_fn(const struct gencache_timeout *t,
13367 void *private_data)
13372 static bool run_local_gencache(int dummy)
13378 struct memcache *mem;
13381 mem = memcache_init(NULL, 0);
13383 d_printf("%s: memcache_init failed\n", __location__);
13386 memcache_set_global(mem);
13388 if (!gencache_set("foo", "bar", time(NULL) + 1000)) {
13389 d_printf("%s: gencache_set() failed\n", __location__);
13393 if (!gencache_get("foo", NULL, NULL, NULL)) {
13394 d_printf("%s: gencache_get() failed\n", __location__);
13398 for (i=0; i<1000000; i++) {
13399 gencache_parse("foo", parse_fn, NULL);
13402 if (!gencache_get("foo", talloc_tos(), &val, &tm)) {
13403 d_printf("%s: gencache_get() failed\n", __location__);
13408 if (!gencache_get("foo", talloc_tos(), &val, &tm)) {
13409 d_printf("%s: gencache_get() failed\n", __location__);
13413 if (strcmp(val, "bar") != 0) {
13414 d_printf("%s: gencache_get() returned %s, expected %s\n",
13415 __location__, val, "bar");
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("foo", talloc_tos(), &val, &tm)) {
13433 d_printf("%s: gencache_get() on deleted entry "
13434 "succeeded\n", __location__);
13438 blob = data_blob_string_const_null("bar");
13439 tm = time(NULL) + 60;
13441 if (!gencache_set_data_blob("foo", blob, tm)) {
13442 d_printf("%s: gencache_set_data_blob() failed\n", __location__);
13446 if (!gencache_get_data_blob("foo", talloc_tos(), &blob, NULL, NULL)) {
13447 d_printf("%s: gencache_get_data_blob() failed\n", __location__);
13451 if (strcmp((const char *)blob.data, "bar") != 0) {
13452 d_printf("%s: gencache_get_data_blob() returned %s, expected %s\n",
13453 __location__, (const char *)blob.data, "bar");
13454 data_blob_free(&blob);
13458 data_blob_free(&blob);
13460 if (!gencache_del("foo")) {
13461 d_printf("%s: gencache_del() failed\n", __location__);
13464 if (gencache_del("foo")) {
13465 d_printf("%s: second gencache_del() succeeded\n",
13470 if (gencache_get_data_blob("foo", talloc_tos(), &blob, NULL, NULL)) {
13471 d_printf("%s: gencache_get_data_blob() on deleted entry "
13472 "succeeded\n", __location__);
13477 blob.data = (uint8_t *)&v;
13478 blob.length = sizeof(v);
13480 if (!gencache_set_data_blob("blob", blob, tm)) {
13481 d_printf("%s: gencache_set_data_blob() failed\n",
13485 if (gencache_get("blob", talloc_tos(), &val, &tm)) {
13486 d_printf("%s: gencache_get succeeded\n", __location__);
13493 static bool rbt_testflags(struct db_context *db, const char *key,
13498 struct db_record *rec;
13500 rec = dbwrap_fetch_locked(db, db, string_tdb_data(key));
13502 d_fprintf(stderr, "fetch_locked failed\n");
13506 status = dbwrap_record_store(rec, string_tdb_data(value), TDB_MODIFY);
13507 if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
13508 d_fprintf(stderr, "store TDB_MODIFY unexpected status: %s\n",
13509 nt_errstr(status));
13513 status = dbwrap_record_store(rec, string_tdb_data("overwriteme"),
13515 if (!NT_STATUS_IS_OK(status)) {
13516 d_fprintf(stderr, "store TDB_INSERT failed: %s\n",
13517 nt_errstr(status));
13521 status = dbwrap_record_store(rec, string_tdb_data(value), TDB_INSERT);
13522 if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_COLLISION)) {
13523 d_fprintf(stderr, "store TDB_INSERT unexpected status: %s\n",
13524 nt_errstr(status));
13528 status = dbwrap_record_store(rec, string_tdb_data(value), TDB_MODIFY);
13529 if (!NT_STATUS_IS_OK(status)) {
13530 d_fprintf(stderr, "store TDB_MODIFY failed: %s\n",
13531 nt_errstr(status));
13541 static bool rbt_testval(struct db_context *db, const char *key,
13544 struct db_record *rec;
13545 TDB_DATA data = string_tdb_data(value);
13550 rec = dbwrap_fetch_locked(db, db, string_tdb_data(key));
13552 d_fprintf(stderr, "fetch_locked failed\n");
13555 status = dbwrap_record_store(rec, data, 0);
13556 if (!NT_STATUS_IS_OK(status)) {
13557 d_fprintf(stderr, "store failed: %s\n", nt_errstr(status));
13562 rec = dbwrap_fetch_locked(db, db, string_tdb_data(key));
13564 d_fprintf(stderr, "second fetch_locked failed\n");
13568 dbvalue = dbwrap_record_get_value(rec);
13569 if ((dbvalue.dsize != data.dsize)
13570 || (memcmp(dbvalue.dptr, data.dptr, data.dsize) != 0)) {
13571 d_fprintf(stderr, "Got wrong data back\n");
13581 static int local_rbtree_traverse_read(struct db_record *rec, void *private_data)
13583 int *count2 = (int *)private_data;
13588 static int local_rbtree_traverse_delete(struct db_record *rec, void *private_data)
13590 int *count2 = (int *)private_data;
13592 dbwrap_record_delete(rec);
13596 static bool run_local_rbtree(int dummy)
13598 struct db_context *db;
13605 db = db_open_rbt(NULL);
13608 d_fprintf(stderr, "db_open_rbt failed\n");
13612 if (!rbt_testflags(db, "firstkey", "firstval")) {
13616 for (i = 0; i < 999; i++) {
13617 char key[sizeof("key-9223372036854775807")];
13618 char value[sizeof("value-9223372036854775807")];
13620 snprintf(key, sizeof(key), "key%ld", random());
13621 snprintf(value, sizeof(value) ,"value%ld", random());
13623 if (!rbt_testval(db, key, value)) {
13627 snprintf(value, sizeof(value) ,"value%ld", random());
13629 if (!rbt_testval(db, key, value)) {
13635 count = 0; count2 = 0;
13636 status = dbwrap_traverse_read(db, local_rbtree_traverse_read,
13638 printf("%s: read1: %d %d, %s\n", __func__, count, count2, nt_errstr(status));
13639 if ((count != count2) || (count != 1000)) {
13642 count = 0; count2 = 0;
13643 status = dbwrap_traverse(db, local_rbtree_traverse_delete,
13645 printf("%s: delete: %d %d, %s\n", __func__, count, count2, nt_errstr(status));
13646 if ((count != count2) || (count != 1000)) {
13649 count = 0; count2 = 0;
13650 status = dbwrap_traverse_read(db, local_rbtree_traverse_read,
13652 printf("%s: read2: %d %d, %s\n", __func__, count, count2, nt_errstr(status));
13653 if ((count != count2) || (count != 0)) {
13664 local test for character set functions
13666 This is a very simple test for the functionality in convert_string_error()
13668 static bool run_local_convert_string(int dummy)
13670 TALLOC_CTX *tmp_ctx = talloc_new(NULL);
13671 const char *test_strings[2] = { "March", "M\303\244rz" };
13675 for (i=0; i<2; i++) {
13676 const char *str = test_strings[i];
13677 int len = strlen(str);
13678 size_t converted_size;
13681 memset(dst, 'X', sizeof(dst));
13683 /* first try with real source length */
13684 ret = convert_string_error(CH_UNIX, CH_UTF8,
13689 d_fprintf(stderr, "Failed to convert '%s' to CH_DISPLAY\n", str);
13693 if (converted_size != len) {
13694 d_fprintf(stderr, "Converted size of '%s' should be %d - got %d\n",
13695 str, len, (int)converted_size);
13699 if (strncmp(str, dst, converted_size) != 0) {
13700 d_fprintf(stderr, "Expected '%s' to match '%s'\n", str, dst);
13704 if (strlen(str) != converted_size) {
13705 d_fprintf(stderr, "Expected '%s' length %d - got %d\n", str,
13706 (int)strlen(str), (int)converted_size);
13710 if (dst[converted_size] != 'X') {
13711 d_fprintf(stderr, "Expected no termination of '%s'\n", dst);
13715 /* now with srclen==-1, this causes the nul to be
13717 ret = convert_string_error(CH_UNIX, CH_UTF8,
13722 d_fprintf(stderr, "Failed to convert '%s' to CH_DISPLAY\n", str);
13726 if (converted_size != len+1) {
13727 d_fprintf(stderr, "Converted size of '%s' should be %d - got %d\n",
13728 str, len, (int)converted_size);
13732 if (strncmp(str, dst, converted_size) != 0) {
13733 d_fprintf(stderr, "Expected '%s' to match '%s'\n", str, dst);
13737 if (len+1 != converted_size) {
13738 d_fprintf(stderr, "Expected '%s' length %d - got %d\n", str,
13739 len+1, (int)converted_size);
13743 if (dst[converted_size] != 'X') {
13744 d_fprintf(stderr, "Expected no termination of '%s'\n", dst);
13751 TALLOC_FREE(tmp_ctx);
13754 TALLOC_FREE(tmp_ctx);
13758 static bool run_local_string_to_sid(int dummy) {
13759 struct dom_sid sid;
13761 if (string_to_sid(&sid, "S--1-5-32-545")) {
13762 printf("allowing S--1-5-32-545\n");
13765 if (string_to_sid(&sid, "S-1-5-32-+545")) {
13766 printf("allowing S-1-5-32-+545\n");
13769 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")) {
13770 printf("allowing S-1-2-3-4-5-6-7-8-9-0-1-2-3-4-5-6-7-8-9-0\n");
13773 if (string_to_sid(&sid, "S-1-5-32-545-abc")) {
13774 printf("allowing S-1-5-32-545-abc\n");
13777 if (string_to_sid(&sid, "S-300-5-32-545")) {
13778 printf("allowing S-300-5-32-545\n");
13781 if (string_to_sid(&sid, "S-1-0xfffffffffffffe-32-545")) {
13782 printf("allowing S-1-0xfffffffffffffe-32-545\n");
13785 if (string_to_sid(&sid, "S-1-0xffffffffffff-5294967297-545")) {
13786 printf("allowing S-1-0xffffffffffff-5294967297-545\n");
13789 if (!string_to_sid(&sid, "S-1-0xfffffffffffe-32-545")) {
13790 printf("could not parse S-1-0xfffffffffffe-32-545\n");
13793 if (!string_to_sid(&sid, "S-1-5-32-545")) {
13794 printf("could not parse S-1-5-32-545\n");
13797 if (!dom_sid_equal(&sid, &global_sid_Builtin_Users)) {
13798 struct dom_sid_buf buf;
13799 printf("mis-parsed S-1-5-32-545 as %s\n",
13800 dom_sid_str_buf(&sid, &buf));
13806 static bool sid_to_string_test(const char *expected) {
13809 struct dom_sid sid;
13811 if (!string_to_sid(&sid, expected)) {
13812 printf("could not parse %s\n", expected);
13816 str = dom_sid_string(NULL, &sid);
13817 if (strcmp(str, expected)) {
13818 printf("Comparison failed (%s != %s)\n", str, expected);
13825 static bool run_local_sid_to_string(int dummy) {
13826 if (!sid_to_string_test("S-1-0xffffffffffff-1-1-1-1-1-1-1-1-1-1-1-1"))
13828 if (!sid_to_string_test("S-1-545"))
13830 if (!sid_to_string_test("S-255-3840-1-1-1-1"))
13835 static bool run_local_binary_to_sid(int dummy) {
13837 struct dom_sid *sid = talloc(NULL, struct dom_sid);
13838 static const uint8_t good_binary_sid[] = {
13839 0x1, /* revision number */
13840 15, /* num auths */
13841 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, /* id_auth */
13842 0x1, 0x1, 0x1, 0x1, /* auth[0] */
13843 0x1, 0x1, 0x1, 0x1, /* auth[1] */
13844 0x1, 0x1, 0x1, 0x1, /* auth[2] */
13845 0x1, 0x1, 0x1, 0x1, /* auth[3] */
13846 0x1, 0x1, 0x1, 0x1, /* auth[4] */
13847 0x1, 0x1, 0x1, 0x1, /* auth[5] */
13848 0x1, 0x1, 0x1, 0x1, /* auth[6] */
13849 0x1, 0x1, 0x1, 0x1, /* auth[7] */
13850 0x1, 0x1, 0x1, 0x1, /* auth[8] */
13851 0x1, 0x1, 0x1, 0x1, /* auth[9] */
13852 0x1, 0x1, 0x1, 0x1, /* auth[10] */
13853 0x1, 0x1, 0x1, 0x1, /* auth[11] */
13854 0x1, 0x1, 0x1, 0x1, /* auth[12] */
13855 0x1, 0x1, 0x1, 0x1, /* auth[13] */
13856 0x1, 0x1, 0x1, 0x1, /* auth[14] */
13859 static const uint8_t long_binary_sid[] = {
13860 0x1, /* revision number */
13861 15, /* num auths */
13862 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, /* id_auth */
13863 0x1, 0x1, 0x1, 0x1, /* auth[0] */
13864 0x1, 0x1, 0x1, 0x1, /* auth[1] */
13865 0x1, 0x1, 0x1, 0x1, /* auth[2] */
13866 0x1, 0x1, 0x1, 0x1, /* auth[3] */
13867 0x1, 0x1, 0x1, 0x1, /* auth[4] */
13868 0x1, 0x1, 0x1, 0x1, /* auth[5] */
13869 0x1, 0x1, 0x1, 0x1, /* auth[6] */
13870 0x1, 0x1, 0x1, 0x1, /* auth[7] */
13871 0x1, 0x1, 0x1, 0x1, /* auth[8] */
13872 0x1, 0x1, 0x1, 0x1, /* auth[9] */
13873 0x1, 0x1, 0x1, 0x1, /* auth[10] */
13874 0x1, 0x1, 0x1, 0x1, /* auth[11] */
13875 0x1, 0x1, 0x1, 0x1, /* auth[12] */
13876 0x1, 0x1, 0x1, 0x1, /* auth[13] */
13877 0x1, 0x1, 0x1, 0x1, /* auth[14] */
13878 0x1, 0x1, 0x1, 0x1, /* auth[15] */
13879 0x1, 0x1, 0x1, 0x1, /* auth[16] */
13880 0x1, 0x1, 0x1, 0x1, /* auth[17] */
13883 static const uint8_t long_binary_sid2[] = {
13884 0x1, /* revision number */
13885 32, /* num auths */
13886 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, /* id_auth */
13887 0x1, 0x1, 0x1, 0x1, /* auth[0] */
13888 0x1, 0x1, 0x1, 0x1, /* auth[1] */
13889 0x1, 0x1, 0x1, 0x1, /* auth[2] */
13890 0x1, 0x1, 0x1, 0x1, /* auth[3] */
13891 0x1, 0x1, 0x1, 0x1, /* auth[4] */
13892 0x1, 0x1, 0x1, 0x1, /* auth[5] */
13893 0x1, 0x1, 0x1, 0x1, /* auth[6] */
13894 0x1, 0x1, 0x1, 0x1, /* auth[7] */
13895 0x1, 0x1, 0x1, 0x1, /* auth[8] */
13896 0x1, 0x1, 0x1, 0x1, /* auth[9] */
13897 0x1, 0x1, 0x1, 0x1, /* auth[10] */
13898 0x1, 0x1, 0x1, 0x1, /* auth[11] */
13899 0x1, 0x1, 0x1, 0x1, /* auth[12] */
13900 0x1, 0x1, 0x1, 0x1, /* auth[13] */
13901 0x1, 0x1, 0x1, 0x1, /* auth[14] */
13902 0x1, 0x1, 0x1, 0x1, /* auth[15] */
13903 0x1, 0x1, 0x1, 0x1, /* auth[16] */
13904 0x1, 0x1, 0x1, 0x1, /* auth[17] */
13905 0x1, 0x1, 0x1, 0x1, /* auth[18] */
13906 0x1, 0x1, 0x1, 0x1, /* auth[19] */
13907 0x1, 0x1, 0x1, 0x1, /* auth[20] */
13908 0x1, 0x1, 0x1, 0x1, /* auth[21] */
13909 0x1, 0x1, 0x1, 0x1, /* auth[22] */
13910 0x1, 0x1, 0x1, 0x1, /* auth[23] */
13911 0x1, 0x1, 0x1, 0x1, /* auth[24] */
13912 0x1, 0x1, 0x1, 0x1, /* auth[25] */
13913 0x1, 0x1, 0x1, 0x1, /* auth[26] */
13914 0x1, 0x1, 0x1, 0x1, /* auth[27] */
13915 0x1, 0x1, 0x1, 0x1, /* auth[28] */
13916 0x1, 0x1, 0x1, 0x1, /* auth[29] */
13917 0x1, 0x1, 0x1, 0x1, /* auth[30] */
13918 0x1, 0x1, 0x1, 0x1, /* auth[31] */
13921 ret = sid_parse(good_binary_sid, sizeof(good_binary_sid), sid);
13925 ret = sid_parse(long_binary_sid2, sizeof(long_binary_sid2), sid);
13929 ret = sid_parse(long_binary_sid, sizeof(long_binary_sid), sid);
13936 /* Split a path name into filename and stream name components. Canonicalise
13937 * such that an implicit $DATA token is always explicit.
13939 * The "specification" of this function can be found in the
13940 * run_local_stream_name() function in torture.c, I've tried those
13941 * combinations against a W2k3 server.
13944 static NTSTATUS split_ntfs_stream_name(TALLOC_CTX *mem_ctx, const char *fname,
13945 char **pbase, char **pstream)
13948 char *stream = NULL;
13949 char *sname; /* stream name */
13950 const char *stype; /* stream type */
13952 DEBUG(10, ("split_ntfs_stream_name called for [%s]\n", fname));
13954 sname = strchr_m(fname, ':');
13956 if (sname == NULL) {
13957 if (pbase != NULL) {
13958 base = talloc_strdup(mem_ctx, fname);
13959 NT_STATUS_HAVE_NO_MEMORY(base);
13964 if (pbase != NULL) {
13965 base = talloc_strndup(mem_ctx, fname, PTR_DIFF(sname, fname));
13966 NT_STATUS_HAVE_NO_MEMORY(base);
13971 stype = strchr_m(sname, ':');
13973 if (stype == NULL) {
13974 sname = talloc_strdup(mem_ctx, sname);
13978 if (strcasecmp_m(stype, ":$DATA") != 0) {
13980 * If there is an explicit stream type, so far we only
13981 * allow $DATA. Is there anything else allowed? -- vl
13983 DEBUG(10, ("[%s] is an invalid stream type\n", stype));
13985 return NT_STATUS_OBJECT_NAME_INVALID;
13987 sname = talloc_strndup(mem_ctx, sname, PTR_DIFF(stype, sname));
13991 if (sname == NULL) {
13993 return NT_STATUS_NO_MEMORY;
13996 if (sname[0] == '\0') {
13998 * no stream name, so no stream
14003 if (pstream != NULL) {
14004 stream = talloc_asprintf(mem_ctx, "%s:%s", sname, stype);
14005 if (stream == NULL) {
14006 TALLOC_FREE(sname);
14008 return NT_STATUS_NO_MEMORY;
14011 * upper-case the type field
14013 (void)strupper_m(strchr_m(stream, ':')+1);
14017 if (pbase != NULL) {
14020 if (pstream != NULL) {
14023 return NT_STATUS_OK;
14026 static bool test_stream_name(const char *fname, const char *expected_base,
14027 const char *expected_stream,
14028 NTSTATUS expected_status)
14032 char *stream = NULL;
14034 status = split_ntfs_stream_name(talloc_tos(), fname, &base, &stream);
14035 if (!NT_STATUS_EQUAL(status, expected_status)) {
14039 if (!NT_STATUS_IS_OK(status)) {
14043 if (base == NULL) goto error;
14045 if (strcmp(expected_base, base) != 0) goto error;
14047 if ((expected_stream != NULL) && (stream == NULL)) goto error;
14048 if ((expected_stream == NULL) && (stream != NULL)) goto error;
14050 if ((stream != NULL) && (strcmp(expected_stream, stream) != 0))
14054 TALLOC_FREE(stream);
14058 d_fprintf(stderr, "Do test_stream(%s, %s, %s, %s)\n",
14059 fname, expected_base ? expected_base : "<NULL>",
14060 expected_stream ? expected_stream : "<NULL>",
14061 nt_errstr(expected_status));
14062 d_fprintf(stderr, "-> base=%s, stream=%s, status=%s\n",
14063 base ? base : "<NULL>", stream ? stream : "<NULL>",
14064 nt_errstr(status));
14066 TALLOC_FREE(stream);
14070 static bool run_local_stream_name(int dummy)
14074 ret &= test_stream_name(
14075 "bla", "bla", NULL, NT_STATUS_OK);
14076 ret &= test_stream_name(
14077 "bla::$DATA", "bla", NULL, NT_STATUS_OK);
14078 ret &= test_stream_name(
14079 "bla:blub:", "bla", NULL, NT_STATUS_OBJECT_NAME_INVALID);
14080 ret &= test_stream_name(
14081 "bla::", NULL, NULL, NT_STATUS_OBJECT_NAME_INVALID);
14082 ret &= test_stream_name(
14083 "bla::123", "bla", NULL, NT_STATUS_OBJECT_NAME_INVALID);
14084 ret &= test_stream_name(
14085 "bla:$DATA", "bla", "$DATA:$DATA", NT_STATUS_OK);
14086 ret &= test_stream_name(
14087 "bla:x:$DATA", "bla", "x:$DATA", NT_STATUS_OK);
14088 ret &= test_stream_name(
14089 "bla:x", "bla", "x:$DATA", NT_STATUS_OK);
14094 static bool data_blob_equal(DATA_BLOB a, DATA_BLOB b)
14096 if (a.length != b.length) {
14097 printf("a.length=%d != b.length=%d\n",
14098 (int)a.length, (int)b.length);
14101 if (memcmp(a.data, b.data, a.length) != 0) {
14102 printf("a.data and b.data differ\n");
14108 static bool run_local_memcache(int dummy)
14110 struct memcache *cache;
14111 DATA_BLOB k1, k2, k3, k4, k5;
14115 TALLOC_CTX *mem_ctx;
14121 size_t size1, size2;
14124 mem_ctx = talloc_init("foo");
14125 if (mem_ctx == NULL) {
14129 /* STAT_CACHE TESTS */
14131 cache = memcache_init(NULL, sizeof(void *) == 8 ? 200 : 100);
14133 if (cache == NULL) {
14134 printf("memcache_init failed\n");
14138 d1 = data_blob_const("d1", 2);
14139 d3 = data_blob_const("d3", 2);
14141 k1 = data_blob_const("d1", 2);
14142 k2 = data_blob_const("d2", 2);
14143 k3 = data_blob_const("d3", 2);
14144 k4 = data_blob_const("d4", 2);
14145 k5 = data_blob_const("d5", 2);
14147 memcache_add(cache, STAT_CACHE, k1, d1);
14149 if (!memcache_lookup(cache, STAT_CACHE, k1, &v1)) {
14150 printf("could not find k1\n");
14153 if (!data_blob_equal(d1, v1)) {
14157 memcache_add(cache, STAT_CACHE, k1, d3);
14159 if (!memcache_lookup(cache, STAT_CACHE, k1, &v3)) {
14160 printf("could not find replaced k1\n");
14163 if (!data_blob_equal(d3, v3)) {
14167 TALLOC_FREE(cache);
14169 /* GETWD_CACHE TESTS */
14170 str1 = talloc_strdup(mem_ctx, "string1");
14171 if (str1 == NULL) {
14174 ptr2 = str1; /* Keep an alias for comparison. */
14176 str2 = talloc_strdup(mem_ctx, "string2");
14177 if (str2 == NULL) {
14181 cache = memcache_init(NULL, sizeof(void *) == 8 ? 200 : 100);
14182 if (cache == NULL) {
14183 printf("memcache_init failed\n");
14187 memcache_add_talloc(cache, GETWD_CACHE, k2, &str1);
14188 /* str1 == NULL now. */
14189 ptr1 = memcache_lookup_talloc(cache, GETWD_CACHE, k2);
14190 if (ptr1 == NULL) {
14191 printf("could not find k2\n");
14194 if (ptr1 != ptr2) {
14195 printf("fetch of k2 got wrong string\n");
14199 /* Add a blob to ensure k2 gets purged. */
14200 d3 = data_blob_talloc_zero(mem_ctx, 180);
14201 memcache_add(cache, STAT_CACHE, k3, d3);
14203 ptr2 = memcache_lookup_talloc(cache, GETWD_CACHE, k2);
14204 if (ptr2 != NULL) {
14205 printf("Did find k2, should have been purged\n");
14210 * Test that talloc size also is accounted in memcache and
14211 * causes purge of other object.
14214 str1 = talloc_zero_size(mem_ctx, 100);
14215 str2 = talloc_zero_size(mem_ctx, 100);
14217 memcache_add_talloc(cache, GETWD_CACHE, k4, &str1);
14218 memcache_add_talloc(cache, GETWD_CACHE, k5, &str1);
14220 ptr3 = memcache_lookup_talloc(cache, GETWD_CACHE, k4);
14221 if (ptr3 != NULL) {
14222 printf("Did find k4, should have been purged\n");
14227 * Test that adding a duplicate non-talloced
14228 * key/value on top of a talloced key/value takes account
14229 * of the talloc_freed value size.
14231 TALLOC_FREE(cache);
14232 TALLOC_FREE(mem_ctx);
14234 mem_ctx = talloc_init("key_replace");
14235 if (mem_ctx == NULL) {
14239 cache = memcache_init(NULL, sizeof(void *) == 8 ? 200 : 100);
14240 if (cache == NULL) {
14245 * Add a 100 byte talloced string. This will
14246 * store a (4 or 8 byte) pointer and record the
14247 * total talloced size.
14249 str1 = talloc_zero_size(mem_ctx, 100);
14250 memcache_add_talloc(cache, GETWD_CACHE, k4, &str1);
14252 * Now overwrite with a small talloced
14253 * value. This should fit in the existing size
14254 * and the total talloced size should be removed
14255 * from the cache size.
14257 str1 = talloc_zero_size(mem_ctx, 2);
14258 memcache_add_talloc(cache, GETWD_CACHE, k4, &str1);
14260 * Now store a 20 byte string. If the
14261 * total talloced size wasn't accounted for
14262 * and removed in the overwrite, then this
14265 str2 = talloc_zero_size(mem_ctx, 20);
14266 memcache_add_talloc(cache, GETWD_CACHE, k5, &str2);
14268 ptr3 = memcache_lookup_talloc(cache, GETWD_CACHE, k4);
14269 if (ptr3 == NULL) {
14270 printf("Did not find k4, should not have been purged\n");
14274 TALLOC_FREE(cache);
14275 TALLOC_FREE(mem_ctx);
14277 mem_ctx = talloc_init("foo");
14278 if (mem_ctx == NULL) {
14282 cache = memcache_init(NULL, 0);
14283 if (cache == NULL) {
14287 str1 = talloc_strdup(mem_ctx, "string1");
14288 if (str1 == NULL) {
14291 str2 = talloc_strdup(mem_ctx, "string2");
14292 if (str2 == NULL) {
14295 memcache_add_talloc(cache, SINGLETON_CACHE_TALLOC,
14296 data_blob_string_const("torture"), &str1);
14297 size1 = talloc_total_size(cache);
14299 memcache_add_talloc(cache, SINGLETON_CACHE_TALLOC,
14300 data_blob_string_const("torture"), &str2);
14301 size2 = talloc_total_size(cache);
14303 printf("size1=%d, size2=%d\n", (int)size1, (int)size2);
14305 if (size2 > size1) {
14306 printf("memcache leaks memory!\n");
14312 TALLOC_FREE(cache);
14316 static void wbclient_done(struct tevent_req *req)
14319 struct winbindd_response *wb_resp;
14320 int *i = (int *)tevent_req_callback_data_void(req);
14322 wbc_err = wb_trans_recv(req, req, &wb_resp);
14325 d_printf("wb_trans_recv %d returned %s\n", *i, wbcErrorString(wbc_err));
14328 static bool run_wbclient_multi_ping(int dummy)
14330 struct tevent_context *ev;
14331 struct wb_context **wb_ctx;
14332 struct winbindd_request wb_req;
14333 bool result = false;
14336 BlockSignals(True, SIGPIPE);
14338 ev = tevent_context_init(talloc_tos());
14343 wb_ctx = talloc_array(ev, struct wb_context *, torture_nprocs);
14344 if (wb_ctx == NULL) {
14348 ZERO_STRUCT(wb_req);
14349 wb_req.cmd = WINBINDD_PING;
14351 d_printf("torture_nprocs=%d, numops=%d\n", (int)torture_nprocs, (int)torture_numops);
14353 for (i=0; i<torture_nprocs; i++) {
14354 wb_ctx[i] = wb_context_init(ev, NULL);
14355 if (wb_ctx[i] == NULL) {
14358 for (j=0; j<torture_numops; j++) {
14359 struct tevent_req *req;
14360 req = wb_trans_send(ev, ev, wb_ctx[i],
14361 (j % 2) == 0, &wb_req);
14365 tevent_req_set_callback(req, wbclient_done, &i);
14371 while (i < torture_nprocs * torture_numops) {
14372 tevent_loop_once(ev);
14381 static bool dbtrans_inc(struct db_context *db)
14383 struct db_record *rec;
14389 rec = dbwrap_fetch_locked(db, db, string_term_tdb_data("transtest"));
14391 printf(__location__ "fetch_lock failed\n");
14395 value = dbwrap_record_get_value(rec);
14397 if (value.dsize != sizeof(uint32_t)) {
14398 printf(__location__ "value.dsize = %d\n",
14403 memcpy(&val, value.dptr, sizeof(val));
14406 status = dbwrap_record_store(
14407 rec, make_tdb_data((uint8_t *)&val, sizeof(val)), 0);
14408 if (!NT_STATUS_IS_OK(status)) {
14409 printf(__location__ "store failed: %s\n",
14410 nt_errstr(status));
14420 static bool run_local_dbtrans(int dummy)
14422 struct db_context *db;
14423 struct db_record *rec;
14429 db = db_open(talloc_tos(), "transtest.tdb", 0, TDB_DEFAULT,
14430 O_RDWR|O_CREAT, 0600, DBWRAP_LOCK_ORDER_1,
14433 printf("Could not open transtest.db\n");
14437 res = dbwrap_transaction_start(db);
14439 printf(__location__ "transaction_start failed\n");
14443 rec = dbwrap_fetch_locked(db, db, string_term_tdb_data("transtest"));
14445 printf(__location__ "fetch_lock failed\n");
14449 value = dbwrap_record_get_value(rec);
14451 if (value.dptr == NULL) {
14453 status = dbwrap_record_store(
14454 rec, make_tdb_data((uint8_t *)&initial,
14457 if (!NT_STATUS_IS_OK(status)) {
14458 printf(__location__ "store returned %s\n",
14459 nt_errstr(status));
14466 res = dbwrap_transaction_commit(db);
14468 printf(__location__ "transaction_commit failed\n");
14473 uint32_t val, val2;
14476 res = dbwrap_transaction_start(db);
14478 printf(__location__ "transaction_start failed\n");
14482 status = dbwrap_fetch_uint32_bystring(db, "transtest", &val);
14483 if (!NT_STATUS_IS_OK(status)) {
14484 printf(__location__ "dbwrap_fetch_uint32 failed: %s\n",
14485 nt_errstr(status));
14489 for (i=0; i<10; i++) {
14490 if (!dbtrans_inc(db)) {
14495 status = dbwrap_fetch_uint32_bystring(db, "transtest", &val2);
14496 if (!NT_STATUS_IS_OK(status)) {
14497 printf(__location__ "dbwrap_fetch_uint32 failed: %s\n",
14498 nt_errstr(status));
14502 if (val2 != val + 10) {
14503 printf(__location__ "val=%d, val2=%d\n",
14504 (int)val, (int)val2);
14508 printf("val2=%d\r", val2);
14510 res = dbwrap_transaction_commit(db);
14512 printf(__location__ "transaction_commit failed\n");
14522 * Just a dummy test to be run under a debugger. There's no real way
14523 * to inspect the tevent_poll specific function from outside of
14527 static bool run_local_tevent_poll(int dummy)
14529 struct tevent_context *ev;
14530 struct tevent_fd *fd1, *fd2;
14531 bool result = false;
14533 ev = tevent_context_init_byname(NULL, "poll");
14535 d_fprintf(stderr, "tevent_context_init_byname failed\n");
14539 fd1 = tevent_add_fd(ev, ev, 2, 0, NULL, NULL);
14541 d_fprintf(stderr, "tevent_add_fd failed\n");
14544 fd2 = tevent_add_fd(ev, ev, 3, 0, NULL, NULL);
14546 d_fprintf(stderr, "tevent_add_fd failed\n");
14551 fd2 = tevent_add_fd(ev, ev, 1, 0, NULL, NULL);
14553 d_fprintf(stderr, "tevent_add_fd failed\n");
14563 static bool run_local_hex_encode_buf(int dummy)
14569 for (i=0; i<sizeof(src); i++) {
14572 hex_encode_buf(buf, src, sizeof(src));
14573 if (strcmp(buf, "0001020304050607") != 0) {
14576 hex_encode_buf(buf, NULL, 0);
14577 if (buf[0] != '\0') {
14583 static const char *remove_duplicate_addrs2_test_strings_vector[] = {
14605 "1001:1111:1111:1000:0:1111:1111:1111",
14614 static const char *remove_duplicate_addrs2_test_strings_result[] = {
14628 "1001:1111:1111:1000:0:1111:1111:1111"
14631 static bool run_local_remove_duplicate_addrs2(int dummy)
14633 struct samba_sockaddr test_vector[28];
14636 /* Construct the sockaddr_storage test vector. */
14637 for (i = 0; i < 28; i++) {
14638 struct addrinfo hints;
14639 struct addrinfo *res = NULL;
14642 memset(&hints, '\0', sizeof(hints));
14643 hints.ai_flags = AI_NUMERICHOST;
14644 ret = getaddrinfo(remove_duplicate_addrs2_test_strings_vector[i],
14649 fprintf(stderr, "getaddrinfo failed on [%s]\n",
14650 remove_duplicate_addrs2_test_strings_vector[i]);
14653 memset(&test_vector[i], '\0', sizeof(test_vector[i]));
14654 memcpy(&test_vector[i].u.ss,
14660 count = remove_duplicate_addrs2(test_vector, i);
14663 fprintf(stderr, "count wrong (%zu) should be 14\n",
14668 for (i = 0; i < count; i++) {
14669 char addr[INET6_ADDRSTRLEN];
14671 print_sockaddr(addr, sizeof(addr), &test_vector[i].u.ss);
14673 if (strcmp(addr, remove_duplicate_addrs2_test_strings_result[i]) != 0) {
14674 fprintf(stderr, "mismatch on [%zu] [%s] [%s]\n",
14677 remove_duplicate_addrs2_test_strings_result[i]);
14682 printf("run_local_remove_duplicate_addrs2: success\n");
14686 static bool run_local_tdb_opener(int dummy)
14692 t = tdb_open("test.tdb", 1000, TDB_CLEAR_IF_FIRST,
14693 O_RDWR|O_CREAT, 0755);
14695 perror("tdb_open failed");
14706 static bool run_local_tdb_writer(int dummy)
14712 t = tdb_open("test.tdb", 1000, 0, O_RDWR|O_CREAT, 0755);
14714 perror("tdb_open failed");
14718 val.dptr = (uint8_t *)&v;
14719 val.dsize = sizeof(v);
14725 ret = tdb_store(t, val, val, 0);
14727 printf("%s\n", tdb_errorstr(t));
14732 data = tdb_fetch(t, val);
14733 if (data.dptr != NULL) {
14734 SAFE_FREE(data.dptr);
14740 static bool run_local_canonicalize_path(int dummy)
14742 const char *src[] = {
14749 ".././././../../../boo",
14761 "/foo/bar/../baz/",
14762 "////////////////",
14763 "/////////./././././.",
14764 "/./.././../.boo/../baz",
14765 "/a/component/path",
14766 "/a/component/path/",
14767 "/a/component/path/..",
14768 "/a/component/../path/",
14769 "///a/./././///component/../////path/",
14772 const char *dst[] = {
14795 "/a/component/path",
14796 "/a/component/path",
14804 for (i = 0; src[i] != NULL; i++) {
14805 char *d = canonicalize_absolute_path(talloc_tos(), src[i]);
14807 perror("talloc fail\n");
14810 if (strcmp(d, dst[i]) != 0) {
14812 "canonicalize mismatch %s -> %s != %s",
14813 src[i], d, dst[i]);
14820 struct session_setup_nt1_truncated_state {
14825 static void smb1_session_setup_nt1_truncated_done(struct tevent_req *subreq);
14827 static struct tevent_req *smb1_session_setup_nt1_truncated_send(
14828 TALLOC_CTX *mem_ctx,
14829 struct tevent_context *ev,
14830 struct smbXcli_conn *conn)
14832 uint16_t *vwv = NULL;
14833 uint8_t *bytes = NULL;
14834 const char *pass = "12345678";
14835 const char *uname = "z";
14836 struct session_setup_nt1_truncated_state *state = NULL;
14837 struct tevent_req *req = NULL;
14838 struct tevent_req *subreq = NULL;
14840 req = tevent_req_create(mem_ctx,
14842 struct session_setup_nt1_truncated_state);
14846 vwv = &state->vwv[0];
14847 bytes = &state->bytes[0];
14849 SCVAL(vwv+0, 0, 0xff);
14850 SCVAL(vwv+0, 1, 0);
14851 SSVAL(vwv+1, 0, 0);
14852 SSVAL(vwv+2, 0, 8192);
14853 SSVAL(vwv+3, 0, 2);
14854 SSVAL(vwv+4, 0, 1);
14855 SIVAL(vwv+5, 0, 0);
14856 SSVAL(vwv+7, 0, strlen(pass)); /* OEMPasswordLen */
14857 SSVAL(vwv+8, 0, 0); /* UnicodePasswordLen */
14858 SSVAL(vwv+9, 0, 0); /* reserved */
14859 SSVAL(vwv+10, 0, 0); /* reserved */
14860 SIVAL(vwv+11, 0, CAP_STATUS32);
14862 memcpy(bytes, pass, strlen(pass));
14863 bytes += strlen(pass);
14864 memcpy(bytes, uname, strlen(uname)+1);
14866 subreq = smb1cli_req_send(state, ev, conn,
14868 0, /* additional_flags */
14869 0, /* clear_flags */
14870 0, /* additional_flags2 */
14871 0, /* clear_flags2 */
14872 10000, /* timeout_msec */
14875 NULL, /* session */
14878 strlen(pass), /* Truncate length at password. */
14880 if (tevent_req_nomem(subreq, req)) {
14881 return tevent_req_post(req, ev);
14883 tevent_req_set_callback(subreq,
14884 smb1_session_setup_nt1_truncated_done,
14889 static void smb1_session_setup_nt1_truncated_done(struct tevent_req *subreq)
14891 struct tevent_req *req =
14892 tevent_req_callback_data(subreq,
14893 struct tevent_req);
14894 struct session_setup_nt1_truncated_state *state =
14895 tevent_req_data(req,
14896 struct session_setup_nt1_truncated_state);
14898 struct smb1cli_req_expected_response expected[] = {
14900 .status = NT_STATUS_OK,
14905 status = smb1cli_req_recv(subreq, state,
14910 NULL, /* pvwv_offset */
14913 NULL, /* pbytes_offset */
14915 expected, ARRAY_SIZE(expected));
14916 TALLOC_FREE(subreq);
14917 if (tevent_req_nterror(req, status)) {
14920 tevent_req_done(req);
14923 static NTSTATUS smb1_session_setup_nt1_truncated_recv(struct tevent_req *req)
14925 return tevent_req_simple_recv_ntstatus(req);
14928 static bool run_smb1_truncated_sesssetup(int dummy)
14930 struct tevent_context *ev;
14931 struct tevent_req *req;
14932 struct smbXcli_conn *conn;
14933 struct sockaddr_storage ss;
14938 printf("Starting send truncated SMB1 sesssetup.\n");
14940 ok = resolve_name(host, &ss, 0x20, true);
14942 d_fprintf(stderr, "Could not resolve name %s\n", host);
14946 status = open_socket_out(&ss, 445, 10000, &fd);
14947 if (!NT_STATUS_IS_OK(status)) {
14948 d_fprintf(stderr, "open_socket_out failed: %s\n",
14949 nt_errstr(status));
14953 conn = smbXcli_conn_create(talloc_tos(), fd, host, SMB_SIGNING_OFF, 0,
14955 if (conn == NULL) {
14956 d_fprintf(stderr, "smbXcli_conn_create failed\n");
14960 status = smbXcli_negprot(conn,
14967 if (!NT_STATUS_IS_OK(status)) {
14968 d_fprintf(stderr, "smbXcli_negprot failed!\n");
14972 ev = samba_tevent_context_init(talloc_tos());
14974 d_fprintf(stderr, "samba_tevent_context_init failed\n");
14978 req = smb1_session_setup_nt1_truncated_send(ev, ev, conn);
14980 d_fprintf(stderr, "smb1_session_setup_nt1_truncated_send failed\n");
14984 ok = tevent_req_poll_ntstatus(req, ev, &status);
14986 d_fprintf(stderr, "tevent_req_poll failed with status %s\n",
14987 nt_errstr(status));
14991 status = smb1_session_setup_nt1_truncated_recv(req);
14992 if (!NT_STATUS_IS_OK(status)) {
14993 d_fprintf(stderr, "smb1_session_setup_nt1_truncated_recv returned "
14994 "%s, expected NT_STATUS_OK\n",
14995 nt_errstr(status));
15003 struct smb1_negotiate_exit_state {
15007 static void smb1_negotiate_exit_done(struct tevent_req *subreq);
15009 static struct tevent_req *smb1_negotiate_exit_send(
15010 TALLOC_CTX *mem_ctx,
15011 struct tevent_context *ev,
15012 struct smbXcli_conn *conn)
15014 struct smb1_negotiate_exit_state *state = NULL;
15015 struct tevent_req *req = NULL;
15016 struct tevent_req *subreq = NULL;
15018 req = tevent_req_create(mem_ctx,
15020 struct smb1_negotiate_exit_state);
15024 subreq = smb1cli_req_send(state, ev, conn,
15026 0, /* additional_flags */
15027 0, /* clear_flags */
15028 0, /* additional_flags2 */
15029 0, /* clear_flags2 */
15030 10000, /* timeout_msec */
15033 NULL, /* session */
15038 if (tevent_req_nomem(subreq, req)) {
15039 return tevent_req_post(req, ev);
15041 tevent_req_set_callback(subreq,
15042 smb1_negotiate_exit_done,
15047 static void smb1_negotiate_exit_done(struct tevent_req *subreq)
15049 struct tevent_req *req =
15050 tevent_req_callback_data(subreq,
15051 struct tevent_req);
15052 struct smb1_negotiate_exit_state *state =
15053 tevent_req_data(req,
15054 struct smb1_negotiate_exit_state);
15056 struct smb1cli_req_expected_response expected[] = {
15058 .status = NT_STATUS_OK,
15063 status = smb1cli_req_recv(subreq, state,
15068 NULL, /* pvwv_offset */
15071 NULL, /* pbytes_offset */
15073 expected, ARRAY_SIZE(expected));
15074 TALLOC_FREE(subreq);
15075 if (tevent_req_nterror(req, status)) {
15078 tevent_req_done(req);
15081 static NTSTATUS smb1_negotiate_exit_recv(struct tevent_req *req)
15083 return tevent_req_simple_recv_ntstatus(req);
15086 static bool do_smb1_exit(TALLOC_CTX *mem_ctx,
15087 struct tevent_context *ev,
15088 struct smbXcli_conn *conn)
15090 struct tevent_req *req;
15093 NTSTATUS expected_status = NT_STATUS_DOS(ERRSRV, ERRinvnid);;
15095 req = smb1_negotiate_exit_send(ev, ev, conn);
15097 d_fprintf(stderr, "smb1_negotiate_exit_send failed\n");
15101 ok = tevent_req_poll_ntstatus(req, ev, &status);
15103 d_fprintf(stderr, "tevent_req_poll failed with status %s\n",
15104 nt_errstr(status));
15108 status = smb1_negotiate_exit_recv(req);
15109 if (!NT_STATUS_EQUAL(status, expected_status)) {
15110 d_fprintf(stderr, "smb1_negotiate_exit_recv returned "
15111 "%s, expected ERRSRV, ERRinvnid\n",
15112 nt_errstr(status));
15118 static bool run_smb1_negotiate_exit(int dummy)
15120 struct tevent_context *ev;
15121 struct smbXcli_conn *conn;
15122 struct sockaddr_storage ss;
15127 printf("Starting send SMB1 negotiate+exit.\n");
15129 ok = resolve_name(host, &ss, 0x20, true);
15131 d_fprintf(stderr, "Could not resolve name %s\n", host);
15135 status = open_socket_out(&ss, 445, 10000, &fd);
15136 if (!NT_STATUS_IS_OK(status)) {
15137 d_fprintf(stderr, "open_socket_out failed: %s\n",
15138 nt_errstr(status));
15142 conn = smbXcli_conn_create(talloc_tos(), fd, host, SMB_SIGNING_OFF, 0,
15144 if (conn == NULL) {
15145 d_fprintf(stderr, "smbXcli_conn_create failed\n");
15149 status = smbXcli_negprot(conn,
15156 if (!NT_STATUS_IS_OK(status)) {
15157 d_fprintf(stderr, "smbXcli_negprot failed!\n");
15161 ev = samba_tevent_context_init(talloc_tos());
15163 d_fprintf(stderr, "samba_tevent_context_init failed\n");
15168 * Call do_smb1_exit twice to catch a server crash, the
15169 * server sends the first return code then crashes.
15171 ok = do_smb1_exit(ev, ev, conn);
15173 d_fprintf(stderr, "do_smb1_exit (1) failed\n");
15176 ok = do_smb1_exit(ev, ev, conn);
15178 d_fprintf(stderr, "do_smb1_exit (2) failed\n");
15186 static bool run_smb1_negotiate_tcon(int dummy)
15188 struct cli_state *cli = NULL;
15190 uint16_t max_xmit = 0;
15193 printf("Starting send SMB1 negotiate+tcon.\n");
15194 cli = open_nbt_connection();
15196 d_fprintf(stderr, "open_nbt_connection failed!\n");
15199 smbXcli_conn_set_sockopt(cli->conn, sockops);
15201 status = smbXcli_negprot(cli->conn,
15208 if (!NT_STATUS_IS_OK(status)) {
15209 d_fprintf(stderr, "smbXcli_negprot failed %s!\n",
15210 nt_errstr(status));
15213 status = cli_raw_tcon(cli,
15219 if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
15220 d_fprintf(stderr, "cli_raw_tcon failed - got %s "
15221 "(should get NT_STATUS_ACCESS_DENIED)!\n",
15222 nt_errstr(status));
15228 static bool run_ign_bad_negprot(int dummy)
15230 struct tevent_context *ev;
15231 struct tevent_req *req;
15232 struct smbXcli_conn *conn;
15233 struct sockaddr_storage ss;
15238 printf("starting ignore bad negprot\n");
15240 ok = resolve_name(host, &ss, 0x20, true);
15242 d_fprintf(stderr, "Could not resolve name %s\n", host);
15246 status = open_socket_out(&ss, 445, 10000, &fd);
15247 if (!NT_STATUS_IS_OK(status)) {
15248 d_fprintf(stderr, "open_socket_out failed: %s\n",
15249 nt_errstr(status));
15253 conn = smbXcli_conn_create(talloc_tos(), fd, host, SMB_SIGNING_OFF, 0,
15255 if (conn == NULL) {
15256 d_fprintf(stderr, "smbXcli_conn_create failed\n");
15260 status = smbXcli_negprot(conn,
15267 if (NT_STATUS_IS_OK(status)) {
15268 d_fprintf(stderr, "smbXcli_negprot succeeded!\n");
15272 ev = samba_tevent_context_init(talloc_tos());
15274 d_fprintf(stderr, "samba_tevent_context_init failed\n");
15278 req = smb1cli_session_setup_nt1_send(
15279 ev, ev, conn, 0, getpid(), NULL, 65503, 2, 1, 0, "", "",
15280 data_blob_null, data_blob_null, 0x40,
15281 "Windows 2000 2195", "Windows 2000 5.0");
15283 d_fprintf(stderr, "smb1cli_session_setup_nt1_send failed\n");
15287 ok = tevent_req_poll_ntstatus(req, ev, &status);
15289 d_fprintf(stderr, "tevent_req_poll failed\n");
15293 status = smb1cli_session_setup_nt1_recv(req, NULL, NULL, NULL, NULL,
15295 if (!NT_STATUS_EQUAL(status, NT_STATUS_CONNECTION_RESET)) {
15296 d_fprintf(stderr, "smb1cli_session_setup_nt1_recv returned "
15297 "%s, expected NT_STATUS_CONNECTION_RESET\n",
15298 nt_errstr(status));
15304 printf("starting ignore bad negprot\n");
15310 static double create_procs(bool (*fn)(int), bool *result)
15313 volatile pid_t *child_status;
15314 volatile bool *child_status_out;
15317 struct timeval start;
15321 child_status = (volatile pid_t *)anonymous_shared_allocate(sizeof(pid_t)*torture_nprocs);
15322 if (!child_status) {
15323 printf("Failed to setup shared memory\n");
15327 child_status_out = (volatile bool *)anonymous_shared_allocate(sizeof(bool)*torture_nprocs);
15328 if (!child_status_out) {
15329 printf("Failed to setup result status shared memory\n");
15333 for (i = 0; i < torture_nprocs; i++) {
15334 child_status[i] = 0;
15335 child_status_out[i] = True;
15338 start = timeval_current();
15340 for (i=0;i<torture_nprocs;i++) {
15343 pid_t mypid = getpid();
15344 sys_srandom(((int)mypid) ^ ((int)time(NULL)));
15346 slprintf(myname,sizeof(myname),"CLIENT%d", i);
15349 if (torture_open_connection(¤t_cli, i)) break;
15350 if (tries-- == 0) {
15351 printf("pid %d failed to start\n", (int)getpid());
15357 child_status[i] = getpid();
15359 while (child_status[i] && timeval_elapsed(&start) < 5) smb_msleep(2);
15361 child_status_out[i] = fn(i);
15368 for (i=0;i<torture_nprocs;i++) {
15369 if (child_status[i]) synccount++;
15371 if (synccount == torture_nprocs) break;
15373 } while (timeval_elapsed(&start) < 30);
15375 if (synccount != torture_nprocs) {
15376 printf("FAILED TO START %d CLIENTS (started %d)\n", torture_nprocs, synccount);
15378 return timeval_elapsed(&start);
15381 /* start the client load */
15382 start = timeval_current();
15384 for (i=0;i<torture_nprocs;i++) {
15385 child_status[i] = 0;
15388 printf("%d clients started\n", torture_nprocs);
15390 for (i=0;i<torture_nprocs;i++) {
15391 while (waitpid(0, &status, 0) == -1 && errno == EINTR) /* noop */ ;
15396 for (i=0;i<torture_nprocs;i++) {
15397 if (!child_status_out[i]) {
15401 return timeval_elapsed(&start);
15404 #define FLAG_MULTIPROC 1
15410 } torture_ops[] = {
15413 .fn = run_fdpasstest,
15417 .fn = run_locktest1,
15421 .fn = run_locktest2,
15425 .fn = run_locktest3,
15429 .fn = run_locktest4,
15433 .fn = run_locktest5,
15437 .fn = run_locktest6,
15441 .fn = run_locktest7,
15445 .fn = run_locktest8,
15449 .fn = run_locktest9a,
15453 .fn = run_locktest9b,
15457 .fn = run_locktest10,
15461 .fn = run_locktest11,
15465 .fn = run_locktest12,
15469 .fn = run_locktest13,
15473 .fn = run_unlinktest,
15477 .fn = run_browsetest,
15481 .fn = run_attrtest,
15485 .fn = run_trans2test,
15489 .fn = run_maxfidtest,
15490 .flags = FLAG_MULTIPROC,
15495 .flags = FLAG_MULTIPROC,
15498 .name = "RANDOMIPC",
15499 .fn = run_randomipc,
15502 .name = "NEGNOWAIT",
15503 .fn = run_negprot_nowait,
15525 #ifdef HAVE_KERNEL_OPLOCKS_LINUX
15537 .fn = run_dirtest1,
15540 .name = "DIR-CREATETIME",
15541 .fn = run_dir_createtime,
15545 .fn = torture_denytest1,
15549 .fn = torture_denytest2,
15553 .fn = run_tcon_test,
15557 .fn = run_tcon_devtype_test,
15561 .fn = run_readwritetest,
15565 .fn = run_readwritemulti,
15566 .flags = FLAG_MULTIPROC
15570 .fn = run_readwritelarge,
15573 .name = "RW-SIGNING",
15574 .fn = run_readwritelarge_signtest,
15578 .fn = run_opentest,
15582 .fn = run_simple_posix_open_test,
15585 .name = "POSIX-APPEND",
15586 .fn = run_posix_append,
15589 .name = "POSIX-SYMLINK-ACL",
15590 .fn = run_acl_symlink_test,
15593 .name = "POSIX-SYMLINK-EA",
15594 .fn = run_ea_symlink_test,
15597 .name = "POSIX-STREAM-DELETE",
15598 .fn = run_posix_stream_delete,
15601 .name = "POSIX-OFD-LOCK",
15602 .fn = run_posix_ofd_lock_test,
15605 .name = "POSIX-BLOCKING-LOCK",
15606 .fn = run_posix_blocking_lock,
15609 .name = "POSIX-MKDIR",
15610 .fn = run_posix_mkdir_test,
15613 .name = "POSIX-ACL-OPLOCK",
15614 .fn = run_posix_acl_oplock_test,
15617 .name = "POSIX-ACL-SHAREROOT",
15618 .fn = run_posix_acl_shareroot_test,
15621 .name = "POSIX-LS-WILDCARD",
15622 .fn = run_posix_ls_wildcard_test,
15625 .name = "POSIX-LS-SINGLE",
15626 .fn = run_posix_ls_single_test,
15629 .name = "POSIX-READLINK",
15630 .fn = run_posix_readlink_test,
15633 .name = "POSIX-STAT",
15634 .fn = run_posix_stat_test,
15637 .name = "POSIX-SYMLINK-PARENT",
15638 .fn = run_posix_symlink_parent_test,
15641 .name = "POSIX-SYMLINK-CHMOD",
15642 .fn = run_posix_symlink_chmod_test,
15645 .name = "POSIX-SYMLINK-RENAME",
15646 .fn = run_posix_symlink_rename_test,
15649 .name = "POSIX-DIR-DEFAULT-ACL",
15650 .fn = run_posix_dir_default_acl_test,
15653 .name = "POSIX-SYMLINK-GETPATHINFO",
15654 .fn = run_posix_symlink_getpathinfo_test,
15657 .name = "POSIX-SYMLINK-SETPATHINFO",
15658 .fn = run_posix_symlink_setpathinfo_test,
15661 .name = "WINDOWS-BAD-SYMLINK",
15662 .fn = run_symlink_open_test,
15665 .name = "SMB1-WILD-MANGLE-UNLINK",
15666 .fn = run_smb1_wild_mangle_unlink_test,
15669 .name = "SMB1-WILD-MANGLE-RENAME",
15670 .fn = run_smb1_wild_mangle_rename_test,
15673 .name = "CASE-INSENSITIVE-CREATE",
15674 .fn = run_case_insensitive_create,
15677 .name = "ASYNC-ECHO",
15678 .fn = run_async_echo,
15681 .name = "UID-REGRESSION-TEST",
15682 .fn = run_uid_regression_test,
15685 .name = "SHORTNAME-TEST",
15686 .fn = run_shortname_test,
15689 .name = "ADDRCHANGE",
15690 .fn = run_addrchange,
15694 .name = "OPENATTR",
15695 .fn = run_openattrtest,
15707 .name = "RENAME-ACCESS",
15708 .fn = run_rename_access,
15711 .name = "OWNER-RIGHTS",
15712 .fn = run_owner_rights,
15716 .fn = run_deletetest,
15719 .name = "DELETE-STREAM",
15720 .fn = run_delete_stream,
15723 .name = "DELETE-PRINT",
15724 .fn = run_delete_print_test,
15727 .name = "DELETE-LN",
15728 .fn = run_deletetest_ln,
15731 .name = "PROPERTIES",
15732 .fn = run_properties,
15736 .fn = torture_mangle,
15743 .name = "MANGLE-ILLEGAL",
15744 .fn = run_mangle_illegal,
15751 .name = "TRANS2SCAN",
15752 .fn = torture_trans2_scan,
15755 .name = "NTTRANSSCAN",
15756 .fn = torture_nttrans_scan,
15760 .fn = torture_utable,
15763 .name = "CASETABLE",
15764 .fn = torture_casetable,
15767 .name = "ERRMAPEXTRACT",
15768 .fn = run_error_map_extract,
15771 .name = "PIPE_NUMBER",
15772 .fn = run_pipe_number,
15776 .fn = run_tcon2_test,
15780 .fn = torture_ioctl_test,
15784 .fn = torture_chkpath_test,
15788 .fn = run_fdsesstest,
15795 .name = "SESSSETUP_BENCH",
15796 .fn = run_sesssetup_bench,
15811 .name = "WINDOWS-WRITE",
15812 .fn = run_windows_write,
15815 .name = "LARGE_READX",
15816 .fn = run_large_readx,
15819 .name = "MSDFS-ATTRIBUTE",
15820 .fn = run_msdfs_attribute,
15823 .name = "NTTRANS-CREATE",
15824 .fn = run_nttrans_create,
15827 .name = "NTTRANS-FSCTL",
15828 .fn = run_nttrans_fsctl,
15831 .name = "CLI_ECHO",
15832 .fn = run_cli_echo,
15835 .name = "CLI_SPLICE",
15836 .fn = run_cli_splice,
15843 .name = "STREAMERROR",
15844 .fn = run_streamerror,
15847 .name = "NOTIFY-BENCH",
15848 .fn = run_notify_bench,
15851 .name = "NOTIFY-BENCH2",
15852 .fn = run_notify_bench2,
15855 .name = "NOTIFY-BENCH3",
15856 .fn = run_notify_bench3,
15859 .name = "BAD-NBT-SESSION",
15860 .fn = run_bad_nbt_session,
15863 .name = "IGN-BAD-NEGPROT",
15864 .fn = run_ign_bad_negprot,
15867 .name = "SMB-ANY-CONNECT",
15868 .fn = run_smb_any_connect,
15871 .name = "NOTIFY-ONLINE",
15872 .fn = run_notify_online,
15875 .name = "SMB2-BASIC",
15876 .fn = run_smb2_basic,
15879 .name = "SMB2-NEGPROT",
15880 .fn = run_smb2_negprot,
15883 .name = "SMB2-ANONYMOUS",
15884 .fn = run_smb2_anonymous,
15887 .name = "SMB2-SESSION-RECONNECT",
15888 .fn = run_smb2_session_reconnect,
15891 .name = "SMB2-TCON-DEPENDENCE",
15892 .fn = run_smb2_tcon_dependence,
15895 .name = "SMB2-MULTI-CHANNEL",
15896 .fn = run_smb2_multi_channel,
15899 .name = "SMB2-SESSION-REAUTH",
15900 .fn = run_smb2_session_reauth,
15903 .name = "SMB2-FTRUNCATE",
15904 .fn = run_smb2_ftruncate,
15907 .name = "SMB2-DIR-FSYNC",
15908 .fn = run_smb2_dir_fsync,
15911 .name = "SMB2-PATH-SLASH",
15912 .fn = run_smb2_path_slash,
15915 .name = "SMB1-SYSTEM-SECURITY",
15916 .fn = run_smb1_system_security,
15919 .name = "SMB2-SACL",
15920 .fn = run_smb2_sacl,
15923 .name = "SMB2-QUOTA1",
15924 .fn = run_smb2_quota1,
15927 .name = "SMB2-INVALID-PIPENAME",
15928 .fn = run_smb2_invalid_pipename,
15931 .name = "SMB2-STREAM-ACL",
15932 .fn = run_smb2_stream_acl,
15935 .name = "SMB2-LIST-DIR-ASYNC",
15936 .fn = run_list_dir_async_test,
15939 .name = "SMB2-DEL-ON-CLOSE-NONEMPTY",
15940 .fn = run_delete_on_close_non_empty,
15943 .name = "SMB2-DEL-ON-CLOSE-NONWRITE-DELETE-YES",
15944 .fn = run_delete_on_close_nonwrite_delete_yes_test,
15947 .name = "SMB2-DEL-ON-CLOSE-NONWRITE-DELETE-NO",
15948 .fn = run_delete_on_close_nonwrite_delete_no_test,
15951 .name = "SMB2-DFS-PATHS",
15952 .fn = run_smb2_dfs_paths,
15955 .name = "SMB2-NON-DFS-SHARE",
15956 .fn = run_smb2_non_dfs_share,
15959 .name = "SMB2-DFS-SHARE-NON-DFS-PATH",
15960 .fn = run_smb2_dfs_share_non_dfs_path,
15963 .name = "SMB2-DFS-FILENAME-LEADING-BACKSLASH",
15964 .fn = run_smb2_dfs_filename_leading_backslash,
15967 .name = "SMB2-PIPE-READ-ASYNC-DISCONNECT",
15968 .fn = run_smb2_pipe_read_async_disconnect,
15971 .name = "SMB1-TRUNCATED-SESSSETUP",
15972 .fn = run_smb1_truncated_sesssetup,
15975 .name = "SMB1-NEGOTIATE-EXIT",
15976 .fn = run_smb1_negotiate_exit,
15979 .name = "SMB1-NEGOTIATE-TCON",
15980 .fn = run_smb1_negotiate_tcon,
15983 .name = "SMB1-DFS-PATHS",
15984 .fn = run_smb1_dfs_paths,
15987 .name = "SMB1-DFS-SEARCH-PATHS",
15988 .fn = run_smb1_dfs_search_paths,
15991 .name = "SMB1-DFS-OPERATIONS",
15992 .fn = run_smb1_dfs_operations,
15995 .name = "SMB1-DFS-BADPATH",
15996 .fn = run_smb1_dfs_check_badpath,
15999 .name = "CLEANUP1",
16000 .fn = run_cleanup1,
16003 .name = "CLEANUP2",
16004 .fn = run_cleanup2,
16007 .name = "CLEANUP4",
16008 .fn = run_cleanup4,
16011 .name = "OPLOCK-CANCEL",
16012 .fn = run_oplock_cancel,
16019 .name = "LOCAL-SUBSTITUTE",
16020 .fn = run_local_substitute,
16023 .name = "LOCAL-GENCACHE",
16024 .fn = run_local_gencache,
16027 .name = "LOCAL-DBWRAP-WATCH1",
16028 .fn = run_dbwrap_watch1,
16031 .name = "LOCAL-DBWRAP-WATCH2",
16032 .fn = run_dbwrap_watch2,
16035 .name = "LOCAL-DBWRAP-WATCH3",
16036 .fn = run_dbwrap_watch3,
16039 .name = "LOCAL-DBWRAP-WATCH4",
16040 .fn = run_dbwrap_watch4,
16043 .name = "LOCAL-DBWRAP-DO-LOCKED1",
16044 .fn = run_dbwrap_do_locked1,
16047 .name = "LOCAL-MESSAGING-READ1",
16048 .fn = run_messaging_read1,
16051 .name = "LOCAL-MESSAGING-READ2",
16052 .fn = run_messaging_read2,
16055 .name = "LOCAL-MESSAGING-READ3",
16056 .fn = run_messaging_read3,
16059 .name = "LOCAL-MESSAGING-READ4",
16060 .fn = run_messaging_read4,
16063 .name = "LOCAL-MESSAGING-FDPASS1",
16064 .fn = run_messaging_fdpass1,
16067 .name = "LOCAL-MESSAGING-FDPASS2",
16068 .fn = run_messaging_fdpass2,
16071 .name = "LOCAL-MESSAGING-FDPASS2a",
16072 .fn = run_messaging_fdpass2a,
16075 .name = "LOCAL-MESSAGING-FDPASS2b",
16076 .fn = run_messaging_fdpass2b,
16079 .name = "LOCAL-MESSAGING-SEND-ALL",
16080 .fn = run_messaging_send_all,
16083 .name = "LOCAL-BASE64",
16084 .fn = run_local_base64,
16087 .name = "LOCAL-RBTREE",
16088 .fn = run_local_rbtree,
16091 .name = "LOCAL-MEMCACHE",
16092 .fn = run_local_memcache,
16095 .name = "LOCAL-STREAM-NAME",
16096 .fn = run_local_stream_name,
16099 .name = "LOCAL-STR-MATCH-MSWILD",
16100 .fn = run_str_match_mswild,
16103 .name = "LOCAL-STR-MATCH-REGEX-SUB1",
16104 .fn = run_str_match_regex_sub1,
16107 .name = "WBCLIENT-MULTI-PING",
16108 .fn = run_wbclient_multi_ping,
16111 .name = "LOCAL-string_to_sid",
16112 .fn = run_local_string_to_sid,
16115 .name = "LOCAL-sid_to_string",
16116 .fn = run_local_sid_to_string,
16119 .name = "LOCAL-binary_to_sid",
16120 .fn = run_local_binary_to_sid,
16123 .name = "LOCAL-DBTRANS",
16124 .fn = run_local_dbtrans,
16127 .name = "LOCAL-TEVENT-POLL",
16128 .fn = run_local_tevent_poll,
16131 .name = "LOCAL-CONVERT-STRING",
16132 .fn = run_local_convert_string,
16135 .name = "LOCAL-CONV-AUTH-INFO",
16136 .fn = run_local_conv_auth_info,
16139 .name = "LOCAL-hex_encode_buf",
16140 .fn = run_local_hex_encode_buf,
16143 .name = "LOCAL-IDMAP-TDB-COMMON",
16144 .fn = run_idmap_tdb_common_test,
16147 .name = "LOCAL-remove_duplicate_addrs2",
16148 .fn = run_local_remove_duplicate_addrs2,
16151 .name = "local-tdb-opener",
16152 .fn = run_local_tdb_opener,
16155 .name = "local-tdb-writer",
16156 .fn = run_local_tdb_writer,
16159 .name = "LOCAL-DBWRAP-CTDB1",
16160 .fn = run_local_dbwrap_ctdb1,
16163 .name = "LOCAL-BENCH-PTHREADPOOL",
16164 .fn = run_bench_pthreadpool,
16167 .name = "LOCAL-PTHREADPOOL-TEVENT",
16168 .fn = run_pthreadpool_tevent,
16171 .name = "LOCAL-G-LOCK1",
16175 .name = "LOCAL-G-LOCK2",
16179 .name = "LOCAL-G-LOCK3",
16183 .name = "LOCAL-G-LOCK4",
16187 .name = "LOCAL-G-LOCK4A",
16188 .fn = run_g_lock4a,
16191 .name = "LOCAL-G-LOCK5",
16195 .name = "LOCAL-G-LOCK6",
16199 .name = "LOCAL-G-LOCK7",
16203 .name = "LOCAL-G-LOCK8",
16207 .name = "LOCAL-G-LOCK-PING-PONG",
16208 .fn = run_g_lock_ping_pong,
16211 .name = "LOCAL-CANONICALIZE-PATH",
16212 .fn = run_local_canonicalize_path,
16215 .name = "LOCAL-NAMEMAP-CACHE1",
16216 .fn = run_local_namemap_cache1,
16219 .name = "LOCAL-IDMAP-CACHE1",
16220 .fn = run_local_idmap_cache1,
16223 .name = "qpathinfo-bufsize",
16224 .fn = run_qpathinfo_bufsize,
16227 .name = "hide-new-files-timeout",
16228 .fn = run_hidenewfiles,
16231 .name = "hide-new-files-timeout-showdirs",
16232 .fn = run_hidenewfiles_showdirs,
16234 #ifdef CLUSTER_SUPPORT
16236 .name = "ctdbd-conn1",
16237 .fn = run_ctdbd_conn1,
16241 .name = "readdir-timestamp",
16242 .fn = run_readdir_timestamp,
16245 .name = "rpc-scale",
16246 .fn = run_rpc_scale,
16249 .name = "LOCAL-TDB-VALIDATE",
16250 .fn = run_tdb_validate,
16257 /****************************************************************************
16258 run a specified test or "ALL"
16259 ****************************************************************************/
16260 static bool run_test(const char *name)
16263 bool result = True;
16264 bool found = False;
16267 if (strequal(name,"ALL")) {
16268 for (i=0;torture_ops[i].name;i++) {
16269 run_test(torture_ops[i].name);
16274 for (i=0;torture_ops[i].name;i++) {
16275 fstr_sprintf(randomfname, "\\XX%x",
16276 (unsigned)random());
16278 if (strequal(name, torture_ops[i].name)) {
16280 printf("Running %s\n", name);
16281 if (torture_ops[i].flags & FLAG_MULTIPROC) {
16282 t = create_procs(torture_ops[i].fn, &result);
16285 printf("TEST %s FAILED!\n", name);
16288 struct timeval start;
16289 start = timeval_current();
16290 if (!torture_ops[i].fn(0)) {
16292 printf("TEST %s FAILED!\n", name);
16294 t = timeval_elapsed(&start);
16296 printf("%s took %g secs\n\n", name, t);
16301 printf("Did not find a test named %s\n", name);
16309 static void usage(void)
16313 printf("WARNING samba4 test suite is much more complete nowadays.\n");
16314 printf("Please use samba4 torture.\n\n");
16316 printf("Usage: smbtorture //server/share <options> TEST1 TEST2 ...\n");
16318 printf("\t-d debuglevel\n");
16319 printf("\t-U user%%pass\n");
16320 printf("\t-k use kerberos\n");
16321 printf("\t-N numprocs\n");
16322 printf("\t-n my_netbios_name\n");
16323 printf("\t-W workgroup\n");
16324 printf("\t-o num_operations\n");
16325 printf("\t-O socket_options\n");
16326 printf("\t-m maximum protocol\n");
16327 printf("\t-L use oplocks\n");
16328 printf("\t-c CLIENT.TXT specify client load file for NBENCH\n");
16329 printf("\t-A showall\n");
16330 printf("\t-p port\n");
16331 printf("\t-s seed\n");
16332 printf("\t-b unclist_filename specify multiple shares for multiple connections\n");
16333 printf("\t-f filename filename to test\n");
16334 printf("\t-e encrypt\n");
16335 printf("\t-T 'OPTION=VALUE' smb.conf option line\n");
16338 printf("tests are:");
16339 for (i=0;torture_ops[i].name;i++) {
16340 printf(" %s", torture_ops[i].name);
16344 printf("default test is ALL\n");
16349 /****************************************************************************
16351 ****************************************************************************/
16352 int main(int argc,char *argv[])
16358 bool correct = True;
16359 TALLOC_CTX *frame = talloc_stackframe();
16360 int seed = time(NULL);
16361 struct loadparm_context *lp_ctx = NULL;
16363 #ifdef HAVE_SETBUFFER
16364 setbuffer(stdout, NULL, 0);
16367 setup_logging("smbtorture", DEBUG_STDOUT);
16372 lp_ctx = loadparm_init_s3(frame, loadparm_s3_helpers());
16373 if (lp_ctx == NULL) {
16375 "Failed to initialise the global parameter structure.\n");
16379 if (is_default_dyn_CONFIGFILE()) {
16380 if(getenv("SMB_CONF_PATH")) {
16381 set_dyn_CONFIGFILE(getenv("SMB_CONF_PATH"));
16384 lp_load_global(get_dyn_CONFIGFILE());
16391 for(p = argv[1]; *p; p++)
16395 if (strncmp(argv[1], "//", 2)) {
16399 fstrcpy(host, &argv[1][2]);
16400 p = strchr_m(&host[2],'/');
16405 fstrcpy(share, p+1);
16407 fstrcpy(myname, get_myname(talloc_tos()));
16409 fprintf(stderr, "Failed to get my hostname.\n");
16413 if (*username == 0 && getenv("LOGNAME")) {
16414 fstrcpy(username,getenv("LOGNAME"));
16420 fstrcpy(workgroup, lp_workgroup());
16422 while ((opt = getopt(argc, argv, "p:hW:U:n:N:O:o:m:Ll:d:Aec:ks:b:B:f:T:"))
16426 port_to_use = atoi(optarg);
16429 seed = atoi(optarg);
16432 fstrcpy(workgroup,optarg);
16435 lpcfg_set_cmdline(lp_ctx, "client max protocol", optarg);
16438 torture_nprocs = atoi(optarg);
16441 torture_numops = atoi(optarg);
16444 lpcfg_set_cmdline(lp_ctx, "log level", optarg);
16450 use_oplocks = True;
16453 local_path = optarg;
16456 torture_showall = True;
16459 fstrcpy(myname, optarg);
16462 client_txt = optarg;
16469 use_kerberos = True;
16471 d_printf("No kerberos support compiled in\n");
16477 fstrcpy(username,optarg);
16478 p = strchr_m(username,'%');
16481 fstrcpy(password, p+1);
16486 fstrcpy(multishare_conn_fname, optarg);
16487 use_multishare_conn = True;
16490 torture_blocksize = atoi(optarg);
16493 test_filename = SMB_STRDUP(optarg);
16496 lpcfg_set_option(lp_ctx, optarg);
16499 printf("Unknown option %c (%d)\n", (char)opt, opt);
16504 d_printf("using seed %d\n", seed);
16508 if(use_kerberos && !gotuser) gotpass = True;
16511 char pwd[256] = {0};
16514 rc = samba_getpass("Password:", pwd, sizeof(pwd), false, false);
16516 fstrcpy(password, pwd);
16521 printf("host=%s share=%s user=%s myname=%s\n",
16522 host, share, username, myname);
16524 torture_creds = cli_session_creds_init(frame,
16530 false, /* fallback_after_kerberos */
16531 false, /* use_ccache */
16532 false); /* password_is_nt_hash */
16533 if (torture_creds == NULL) {
16534 d_printf("cli_session_creds_init() failed.\n");
16538 if (argc == optind) {
16539 correct = run_test("ALL");
16541 for (i=optind;i<argc;i++) {
16542 if (!run_test(argv[i])) {
16548 TALLOC_FREE(frame);