2 Unix SMB/CIFS implementation.
4 Copyright (C) Andrew Tridgell 1997-1998
5 Copyright (C) Jeremy Allison 2009
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program. If not, see <http://www.gnu.org/licenses/>.
22 #include "system/shmem.h"
23 #include "libsmb/namequery.h"
24 #include "wbc_async.h"
25 #include "torture/proto.h"
26 #include "libcli/security/security.h"
28 #include "tldap_util.h"
29 #include "tldap_gensec_bind.h"
30 #include "../librpc/gen_ndr/svcctl.h"
31 #include "../lib/util/memcache.h"
32 #include "nsswitch/winbind_client.h"
33 #include "dbwrap/dbwrap.h"
34 #include "dbwrap/dbwrap_open.h"
35 #include "dbwrap/dbwrap_rbt.h"
36 #include "async_smb.h"
37 #include "libsmb/libsmb.h"
38 #include "libsmb/clirap.h"
40 #include "libsmb/nmblib.h"
41 #include "../lib/util/tevent_ntstatus.h"
43 #include "../libcli/smb/read_smb.h"
44 #include "../libcli/smb/smbXcli_base.h"
45 #include "lib/util/sys_rw_data.h"
46 #include "lib/util/base64.h"
47 #include "lib/util/time.h"
48 #include "lib/gencache.h"
49 #include "lib/util/sys_rw.h"
50 #include "lib/util/asn1.h"
51 #include "lib/param/param.h"
52 #include "auth/gensec/gensec.h"
53 #include "lib/util/string_wrappers.h"
54 #include "source3/lib/substitute.h"
56 #include <gnutls/gnutls.h>
57 #include <gnutls/crypto.h>
62 fstring host, workgroup, share, password, username, myname;
63 struct cli_credentials *torture_creds;
64 static const char *sockops="TCP_NODELAY";
66 static int port_to_use=0;
67 int torture_numops=100;
68 int torture_blocksize=1024*1024;
69 static int procnum; /* records process count number when forking */
70 static struct cli_state *current_cli;
71 static fstring randomfname;
72 static bool use_oplocks;
73 static bool use_level_II_oplocks;
74 static const char *client_txt = "client_oplocks.txt";
75 static bool disable_spnego;
76 static bool use_kerberos;
77 static bool force_dos_errors;
78 static fstring multishare_conn_fname;
79 static bool use_multishare_conn = False;
80 static bool do_encrypt;
81 static const char *local_path = NULL;
82 static enum smb_signing_setting signing_state = SMB_SIGNING_DEFAULT;
85 bool torture_showall = False;
87 static double create_procs(bool (*fn)(int), bool *result);
89 /********************************************************************
90 Ensure a connection is encrypted.
91 ********************************************************************/
93 static bool force_cli_encryption(struct cli_state *c,
94 const char *sharename)
96 uint16_t major, minor;
97 uint32_t caplow, caphigh;
100 if (!SERVER_HAS_UNIX_CIFS(c)) {
101 d_printf("Encryption required and "
102 "server that doesn't support "
103 "UNIX extensions - failing connect\n");
107 status = cli_unix_extensions_version(c, &major, &minor, &caplow,
109 if (!NT_STATUS_IS_OK(status)) {
110 d_printf("Encryption required and "
111 "can't get UNIX CIFS extensions "
112 "version from server: %s\n", nt_errstr(status));
116 if (!(caplow & CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP)) {
117 d_printf("Encryption required and "
118 "share %s doesn't support "
119 "encryption.\n", sharename);
123 status = cli_smb1_setup_encryption(c, torture_creds);
124 if (!NT_STATUS_IS_OK(status)) {
125 d_printf("Encryption required and "
126 "setup failed with error %s.\n",
135 static struct cli_state *open_nbt_connection(void)
141 if (disable_spnego) {
142 flags |= CLI_FULL_CONNECTION_DONT_SPNEGO;
146 flags |= CLI_FULL_CONNECTION_OPLOCKS;
149 if (use_level_II_oplocks) {
150 flags |= CLI_FULL_CONNECTION_LEVEL_II_OPLOCKS;
153 if (force_dos_errors) {
154 flags |= CLI_FULL_CONNECTION_FORCE_DOS_ERRORS;
157 status = cli_connect_nb(host, NULL, port_to_use, 0x20, myname,
158 signing_state, flags, &c);
159 if (!NT_STATUS_IS_OK(status)) {
160 printf("Failed to connect with %s. Error %s\n", host, nt_errstr(status) );
164 cli_set_timeout(c, 120000); /* set a really long timeout (2 minutes) */
169 /****************************************************************************
170 Send a corrupt session request. See rfc1002.txt 4.3 and 4.3.2.
171 ****************************************************************************/
173 static bool cli_bad_session_request(int fd,
174 struct nmb_name *calling, struct nmb_name *called)
183 uint8_t message_type;
185 struct tevent_context *ev;
186 struct tevent_req *req;
188 frame = talloc_stackframe();
190 iov[0].iov_base = len_buf;
191 iov[0].iov_len = sizeof(len_buf);
193 /* put in the destination name */
195 iov[1].iov_base = name_mangle(talloc_tos(), called->name,
197 if (iov[1].iov_base == NULL) {
200 iov[1].iov_len = name_len((unsigned char *)iov[1].iov_base,
201 talloc_get_size(iov[1].iov_base));
205 iov[2].iov_base = name_mangle(talloc_tos(), calling->name,
207 if (iov[2].iov_base == NULL) {
210 iov[2].iov_len = name_len((unsigned char *)iov[2].iov_base,
211 talloc_get_size(iov[2].iov_base));
213 /* Deliberately corrupt the name len (first byte) */
214 *((uint8_t *)iov[2].iov_base) = 100;
216 /* send a session request (RFC 1002) */
217 /* setup the packet length
218 * Remove four bytes from the length count, since the length
219 * field in the NBT Session Service header counts the number
220 * of bytes which follow. The cli_send_smb() function knows
221 * about this and accounts for those four bytes.
225 _smb_setlen(len_buf, iov[1].iov_len + iov[2].iov_len);
226 SCVAL(len_buf,0,0x81);
228 len = write_data_iov(fd, iov, 3);
233 ev = samba_tevent_context_init(frame);
237 req = read_smb_send(frame, ev, fd);
241 if (!tevent_req_poll(req, ev)) {
244 len = read_smb_recv(req, talloc_tos(), &inbuf, &err);
251 message_type = CVAL(inbuf, 0);
252 if (message_type != 0x83) {
253 d_fprintf(stderr, "Expected msg type 0x83, got 0x%2.2x\n",
258 if (smb_len(inbuf) != 1) {
259 d_fprintf(stderr, "Expected smb_len 1, got %d\n",
260 (int)smb_len(inbuf));
264 error = CVAL(inbuf, 4);
266 d_fprintf(stderr, "Expected error 0x82, got %d\n",
277 /* Insert a NULL at the first separator of the given path and return a pointer
278 * to the remainder of the string.
281 terminate_path_at_separator(char * path)
289 if ((p = strchr_m(path, '/'))) {
294 if ((p = strchr_m(path, '\\'))) {
304 parse a //server/share type UNC name
306 bool smbcli_parse_unc(const char *unc_name, TALLOC_CTX *mem_ctx,
307 char **hostname, char **sharename)
311 *hostname = *sharename = NULL;
313 if (strncmp(unc_name, "\\\\", 2) &&
314 strncmp(unc_name, "//", 2)) {
318 *hostname = talloc_strdup(mem_ctx, &unc_name[2]);
319 p = terminate_path_at_separator(*hostname);
322 *sharename = talloc_strdup(mem_ctx, p);
323 terminate_path_at_separator(*sharename);
326 if (*hostname && *sharename) {
330 TALLOC_FREE(*hostname);
331 TALLOC_FREE(*sharename);
335 static bool torture_open_connection_share(struct cli_state **c,
336 const char *hostname,
337 const char *sharename,
342 status = cli_full_connection_creds(c,
351 if (!NT_STATUS_IS_OK(status)) {
352 printf("failed to open share connection: //%s/%s port:%d - %s\n",
353 hostname, sharename, port_to_use, nt_errstr(status));
357 cli_set_timeout(*c, 120000); /* set a really long timeout (2 minutes) */
360 return force_cli_encryption(*c,
366 bool torture_open_connection_flags(struct cli_state **c, int conn_index, int flags)
368 char **unc_list = NULL;
369 int num_unc_names = 0;
372 if (use_multishare_conn==True) {
374 unc_list = file_lines_load(multishare_conn_fname, &num_unc_names, 0, NULL);
375 if (!unc_list || num_unc_names <= 0) {
376 printf("Failed to load unc names list from '%s'\n", multishare_conn_fname);
380 if (!smbcli_parse_unc(unc_list[conn_index % num_unc_names],
382 printf("Failed to parse UNC name %s\n",
383 unc_list[conn_index % num_unc_names]);
384 TALLOC_FREE(unc_list);
388 result = torture_open_connection_share(c, h, s, flags);
390 /* h, s were copied earlier */
391 TALLOC_FREE(unc_list);
395 return torture_open_connection_share(c, host, share, flags);
398 bool torture_open_connection(struct cli_state **c, int conn_index)
400 int flags = CLI_FULL_CONNECTION_FORCE_SMB1;
403 flags |= CLI_FULL_CONNECTION_OPLOCKS;
405 if (use_level_II_oplocks) {
406 flags |= CLI_FULL_CONNECTION_LEVEL_II_OPLOCKS;
409 return torture_open_connection_flags(c, conn_index, flags);
412 bool torture_init_connection(struct cli_state **pcli)
414 struct cli_state *cli;
416 cli = open_nbt_connection();
425 bool torture_cli_session_setup2(struct cli_state *cli, uint16_t *new_vuid)
427 uint16_t old_vuid = cli_state_get_uid(cli);
431 cli_state_set_uid(cli, 0);
432 status = cli_session_setup_creds(cli, torture_creds);
433 ret = NT_STATUS_IS_OK(status);
434 *new_vuid = cli_state_get_uid(cli);
435 cli_state_set_uid(cli, old_vuid);
440 bool torture_close_connection(struct cli_state *c)
445 status = cli_tdis(c);
446 if (!NT_STATUS_IS_OK(status)) {
447 printf("tdis failed (%s)\n", nt_errstr(status));
456 void torture_conn_set_sockopt(struct cli_state *cli)
458 smbXcli_conn_set_sockopt(cli->conn, sockops);
461 static NTSTATUS torture_delete_fn(struct file_info *finfo,
466 char *filename = NULL;
467 char *dirname = NULL;
469 TALLOC_CTX *frame = talloc_stackframe();
470 struct cli_state *cli = (struct cli_state *)state;
472 if (ISDOT(finfo->name) || ISDOTDOT(finfo->name)) {
477 dirname = talloc_strdup(frame, pattern);
478 if (dirname == NULL) {
480 return NT_STATUS_NO_MEMORY;
482 p = strrchr_m(dirname, '\\');
484 /* Remove the terminating '\' */
487 if (dirname[0] != '\0') {
488 filename = talloc_asprintf(frame,
493 filename = talloc_asprintf(frame,
497 if (filename == NULL) {
499 return NT_STATUS_NO_MEMORY;
501 if (finfo->attr & FILE_ATTRIBUTE_DIRECTORY) {
502 char *subdirname = talloc_asprintf(frame,
505 if (subdirname == NULL) {
507 return NT_STATUS_NO_MEMORY;
509 status = cli_list(cli,
511 FILE_ATTRIBUTE_DIRECTORY |
512 FILE_ATTRIBUTE_HIDDEN |
513 FILE_ATTRIBUTE_SYSTEM,
516 if (!NT_STATUS_IS_OK(status)) {
517 printf("torture_delete_fn: cli_list "
518 "of %s failed (%s)\n",
524 status = cli_rmdir(cli, filename);
526 status = cli_unlink(cli,
528 FILE_ATTRIBUTE_SYSTEM |
529 FILE_ATTRIBUTE_HIDDEN);
531 if (!NT_STATUS_IS_OK(status)) {
532 if (finfo->attr & FILE_ATTRIBUTE_DIRECTORY) {
533 printf("torture_delete_fn: cli_rmdir"
534 " of %s failed (%s)\n",
538 printf("torture_delete_fn: cli_unlink"
539 " of %s failed (%s)\n",
548 void torture_deltree(struct cli_state *cli, const char *dname)
553 /* It might be a file */
554 (void)cli_unlink(cli,
556 FILE_ATTRIBUTE_SYSTEM |
557 FILE_ATTRIBUTE_HIDDEN);
559 mask = talloc_asprintf(cli,
563 printf("torture_deltree: talloc_asprintf failed\n");
567 status = cli_list(cli,
569 FILE_ATTRIBUTE_DIRECTORY |
570 FILE_ATTRIBUTE_HIDDEN|
571 FILE_ATTRIBUTE_SYSTEM,
574 if (!NT_STATUS_IS_OK(status)) {
575 printf("torture_deltree: cli_list of %s failed (%s)\n",
580 status = cli_rmdir(cli, dname);
581 if (!NT_STATUS_IS_OK(status)) {
582 printf("torture_deltree: cli_rmdir of %s failed (%s)\n",
588 /* check if the server produced the expected dos or nt error code */
589 static bool check_both_error(int line, NTSTATUS status,
590 uint8_t eclass, uint32_t ecode, NTSTATUS nterr)
592 if (NT_STATUS_IS_DOS(status)) {
596 /* Check DOS error */
597 cclass = NT_STATUS_DOS_CLASS(status);
598 num = NT_STATUS_DOS_CODE(status);
600 if (eclass != cclass || ecode != num) {
601 printf("unexpected error code class=%d code=%d\n",
602 (int)cclass, (int)num);
603 printf(" expected %d/%d %s (line=%d)\n",
604 (int)eclass, (int)ecode, nt_errstr(nterr), line);
609 if (!NT_STATUS_EQUAL(nterr, status)) {
610 printf("unexpected error code %s\n",
612 printf(" expected %s (line=%d)\n",
613 nt_errstr(nterr), line);
622 /* check if the server produced the expected error code */
623 static bool check_error(int line, NTSTATUS status,
624 uint8_t eclass, uint32_t ecode, NTSTATUS nterr)
626 if (NT_STATUS_IS_DOS(status)) {
630 /* Check DOS error */
632 cclass = NT_STATUS_DOS_CLASS(status);
633 num = NT_STATUS_DOS_CODE(status);
635 if (eclass != cclass || ecode != num) {
636 printf("unexpected error code class=%d code=%d\n",
637 (int)cclass, (int)num);
638 printf(" expected %d/%d %s (line=%d)\n",
639 (int)eclass, (int)ecode, nt_errstr(nterr),
647 if (NT_STATUS_V(nterr) != NT_STATUS_V(status)) {
648 printf("unexpected error code %s\n",
650 printf(" expected %s (line=%d)\n", nt_errstr(nterr),
659 NTSTATUS cli_qpathinfo1(struct cli_state *cli,
667 int timezone = smb1cli_conn_server_time_zone(cli->conn);
668 time_t (*date_fn)(const void *buf, int serverzone) = NULL;
669 uint8_t *rdata = NULL;
673 status = cli_qpathinfo(talloc_tos(),
681 if (!NT_STATUS_IS_OK(status)) {
685 date_fn = make_unix_date;
687 date_fn = make_unix_date2;
691 *change_time = date_fn(rdata + 0, timezone);
694 *access_time = date_fn(rdata + 4, timezone);
697 *write_time = date_fn(rdata + 8, timezone);
700 *size = PULL_LE_U32(rdata, 12);
703 *pattr = PULL_LE_U16(rdata, l1_attrFile);
708 static bool wait_lock(struct cli_state *c, int fnum, uint32_t offset, uint32_t len)
712 status = cli_lock32(c, fnum, offset, len, -1, WRITE_LOCK);
714 while (!NT_STATUS_IS_OK(status)) {
715 if (!check_both_error(__LINE__, status, ERRDOS,
716 ERRlock, NT_STATUS_LOCK_NOT_GRANTED)) {
720 status = cli_lock32(c, fnum, offset, len, -1, WRITE_LOCK);
727 static bool rw_torture(struct cli_state *c)
729 const char *lockfname = "\\torture.lck";
733 pid_t pid2, pid = getpid();
740 memset(buf, '\0', sizeof(buf));
742 status = cli_openx(c, lockfname, O_RDWR | O_CREAT | O_EXCL,
744 if (!NT_STATUS_IS_OK(status)) {
745 status = cli_openx(c, lockfname, O_RDWR, DENY_NONE, &fnum2);
747 if (!NT_STATUS_IS_OK(status)) {
748 printf("open of %s failed (%s)\n",
749 lockfname, nt_errstr(status));
753 for (i=0;i<torture_numops;i++) {
754 unsigned n = (unsigned)sys_random()%10;
757 printf("%d\r", i); fflush(stdout);
759 slprintf(fname, sizeof(fstring) - 1, "\\torture.%u", n);
761 if (!wait_lock(c, fnum2, n*sizeof(int), sizeof(int))) {
765 status = cli_openx(c, fname, O_RDWR | O_CREAT | O_TRUNC,
767 if (!NT_STATUS_IS_OK(status)) {
768 printf("open failed (%s)\n", nt_errstr(status));
773 status = cli_writeall(c, fnum, 0, (uint8_t *)&pid, 0,
775 if (!NT_STATUS_IS_OK(status)) {
776 printf("write failed (%s)\n", nt_errstr(status));
781 status = cli_writeall(c, fnum, 0, (uint8_t *)buf,
782 sizeof(pid)+(j*sizeof(buf)),
784 if (!NT_STATUS_IS_OK(status)) {
785 printf("write failed (%s)\n",
793 status = cli_read(c, fnum, (char *)&pid2, 0, sizeof(pid),
795 if (!NT_STATUS_IS_OK(status)) {
796 printf("read failed (%s)\n", nt_errstr(status));
798 } else if (nread != sizeof(pid)) {
799 printf("read/write compare failed: "
800 "recv %ld req %ld\n", (unsigned long)nread,
801 (unsigned long)sizeof(pid));
806 printf("data corruption!\n");
810 status = cli_close(c, fnum);
811 if (!NT_STATUS_IS_OK(status)) {
812 printf("close failed (%s)\n", nt_errstr(status));
816 status = cli_unlink(c, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
817 if (!NT_STATUS_IS_OK(status)) {
818 printf("unlink failed (%s)\n", nt_errstr(status));
822 status = cli_unlock(c, fnum2, n*sizeof(int), sizeof(int));
823 if (!NT_STATUS_IS_OK(status)) {
824 printf("unlock failed (%s)\n", nt_errstr(status));
830 cli_unlink(c, lockfname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
837 static bool run_torture(int dummy)
839 struct cli_state *cli;
844 smbXcli_conn_set_sockopt(cli->conn, sockops);
846 ret = rw_torture(cli);
848 if (!torture_close_connection(cli)) {
855 static bool rw_torture3(struct cli_state *c, char *lockfname)
857 uint16_t fnum = (uint16_t)-1;
862 unsigned countprev = 0;
865 NTSTATUS status = NT_STATUS_OK;
868 for (i = 0; i < sizeof(buf); i += sizeof(uint32_t))
870 SIVAL(buf, i, sys_random());
877 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
878 if (!NT_STATUS_IS_OK(status)) {
879 printf("unlink failed (%s) (normal, this file should "
880 "not exist)\n", nt_errstr(status));
883 status = cli_openx(c, lockfname, O_RDWR | O_CREAT | O_EXCL,
885 if (!NT_STATUS_IS_OK(status)) {
886 printf("first open read/write of %s failed (%s)\n",
887 lockfname, nt_errstr(status));
893 for (i = 0; i < 500 && fnum == (uint16_t)-1; i++)
895 status = cli_openx(c, lockfname, O_RDONLY,
897 if (NT_STATUS_IS_OK(status)) {
902 if (!NT_STATUS_IS_OK(status)) {
903 printf("second open read-only of %s failed (%s)\n",
904 lockfname, nt_errstr(status));
910 for (count = 0; count < sizeof(buf); count += sent)
912 if (count >= countprev) {
913 printf("%d %8d\r", i, count);
916 countprev += (sizeof(buf) / 20);
921 sent = ((unsigned)sys_random()%(20))+ 1;
922 if (sent > sizeof(buf) - count)
924 sent = sizeof(buf) - count;
927 status = cli_writeall(c, fnum, 0, (uint8_t *)buf+count,
929 if (!NT_STATUS_IS_OK(status)) {
930 printf("write failed (%s)\n",
937 status = cli_read(c, fnum, buf_rd+count, count,
938 sizeof(buf)-count, &sent);
939 if(!NT_STATUS_IS_OK(status)) {
940 printf("read failed offset:%d size:%ld (%s)\n",
941 count, (unsigned long)sizeof(buf)-count,
945 } else if (sent > 0) {
946 if (memcmp(buf_rd+count, buf+count, sent) != 0)
948 printf("read/write compare failed\n");
949 printf("offset: %d req %ld recvd %ld\n", count, (unsigned long)sizeof(buf)-count, (unsigned long)sent);
958 status = cli_close(c, fnum);
959 if (!NT_STATUS_IS_OK(status)) {
960 printf("close failed (%s)\n", nt_errstr(status));
967 static bool rw_torture2(struct cli_state *c1, struct cli_state *c2)
969 const char *lockfname = "\\torture2.lck";
979 status = cli_unlink(c1, lockfname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
980 if (!NT_STATUS_IS_OK(status)) {
981 printf("unlink failed (%s) (normal, this file should not exist)\n", nt_errstr(status));
984 status = cli_openx(c1, lockfname, O_RDWR | O_CREAT | O_EXCL,
986 if (!NT_STATUS_IS_OK(status)) {
987 printf("first open read/write of %s failed (%s)\n",
988 lockfname, nt_errstr(status));
992 status = cli_openx(c2, lockfname, O_RDONLY, DENY_NONE, &fnum2);
993 if (!NT_STATUS_IS_OK(status)) {
994 printf("second open read-only of %s failed (%s)\n",
995 lockfname, nt_errstr(status));
996 cli_close(c1, fnum1);
1000 for (i = 0; i < torture_numops; i++)
1002 size_t buf_size = ((unsigned)sys_random()%(sizeof(buf)-1))+ 1;
1004 printf("%d\r", i); fflush(stdout);
1007 generate_random_buffer((unsigned char *)buf, buf_size);
1009 status = cli_writeall(c1, fnum1, 0, (uint8_t *)buf, 0,
1011 if (!NT_STATUS_IS_OK(status)) {
1012 printf("write failed (%s)\n", nt_errstr(status));
1017 status = cli_read(c2, fnum2, buf_rd, 0, buf_size, &bytes_read);
1018 if(!NT_STATUS_IS_OK(status)) {
1019 printf("read failed (%s)\n", nt_errstr(status));
1022 } else if (bytes_read != buf_size) {
1023 printf("read failed\n");
1024 printf("read %ld, expected %ld\n",
1025 (unsigned long)bytes_read,
1026 (unsigned long)buf_size);
1031 if (memcmp(buf_rd, buf, buf_size) != 0)
1033 printf("read/write compare failed\n");
1039 status = cli_close(c2, fnum2);
1040 if (!NT_STATUS_IS_OK(status)) {
1041 printf("close failed (%s)\n", nt_errstr(status));
1045 status = cli_close(c1, fnum1);
1046 if (!NT_STATUS_IS_OK(status)) {
1047 printf("close failed (%s)\n", nt_errstr(status));
1051 status = cli_unlink(c1, lockfname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1052 if (!NT_STATUS_IS_OK(status)) {
1053 printf("unlink failed (%s)\n", nt_errstr(status));
1060 static bool run_readwritetest(int dummy)
1062 struct cli_state *cli1, *cli2;
1063 bool test1, test2 = False;
1065 if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
1068 smbXcli_conn_set_sockopt(cli1->conn, sockops);
1069 smbXcli_conn_set_sockopt(cli2->conn, sockops);
1071 printf("starting readwritetest\n");
1073 test1 = rw_torture2(cli1, cli2);
1074 printf("Passed readwritetest v1: %s\n", BOOLSTR(test1));
1077 test2 = rw_torture2(cli1, cli1);
1078 printf("Passed readwritetest v2: %s\n", BOOLSTR(test2));
1081 if (!torture_close_connection(cli1)) {
1085 if (!torture_close_connection(cli2)) {
1089 return (test1 && test2);
1092 static bool run_readwritemulti(int dummy)
1094 struct cli_state *cli;
1099 smbXcli_conn_set_sockopt(cli->conn, sockops);
1101 printf("run_readwritemulti: fname %s\n", randomfname);
1102 test = rw_torture3(cli, randomfname);
1104 if (!torture_close_connection(cli)) {
1111 static bool run_readwritelarge_internal(void)
1113 static struct cli_state *cli1;
1115 const char *lockfname = "\\large.dat";
1118 bool correct = True;
1121 if (!torture_open_connection(&cli1, 0)) {
1124 smbXcli_conn_set_sockopt(cli1->conn, sockops);
1125 memset(buf,'\0',sizeof(buf));
1127 printf("starting readwritelarge_internal\n");
1129 cli_unlink(cli1, lockfname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1131 status = cli_openx(cli1, lockfname, O_RDWR | O_CREAT | O_EXCL,
1133 if (!NT_STATUS_IS_OK(status)) {
1134 printf("open read/write of %s failed (%s)\n", lockfname, nt_errstr(status));
1138 cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 0, sizeof(buf), NULL);
1140 status = cli_qfileinfo_basic(cli1, fnum1, NULL, &fsize, NULL, NULL,
1142 if (!NT_STATUS_IS_OK(status)) {
1143 printf("qfileinfo failed (%s)\n", nt_errstr(status));
1147 if (fsize == sizeof(buf))
1148 printf("readwritelarge_internal test 1 succeeded (size = %lx)\n",
1149 (unsigned long)fsize);
1151 printf("readwritelarge_internal test 1 failed (size = %lx)\n",
1152 (unsigned long)fsize);
1156 status = cli_close(cli1, fnum1);
1157 if (!NT_STATUS_IS_OK(status)) {
1158 printf("close failed (%s)\n", nt_errstr(status));
1162 status = cli_unlink(cli1, lockfname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1163 if (!NT_STATUS_IS_OK(status)) {
1164 printf("unlink failed (%s)\n", nt_errstr(status));
1168 status = cli_openx(cli1, lockfname, O_RDWR | O_CREAT | O_EXCL,
1170 if (!NT_STATUS_IS_OK(status)) {
1171 printf("open read/write of %s failed (%s)\n", lockfname, nt_errstr(status));
1175 cli_smbwrite(cli1, fnum1, buf, 0, sizeof(buf), NULL);
1177 status = cli_qfileinfo_basic(cli1, fnum1, NULL, &fsize, NULL, NULL,
1179 if (!NT_STATUS_IS_OK(status)) {
1180 printf("qfileinfo failed (%s)\n", nt_errstr(status));
1184 if (fsize == sizeof(buf))
1185 printf("readwritelarge_internal test 2 succeeded (size = %lx)\n",
1186 (unsigned long)fsize);
1188 printf("readwritelarge_internal test 2 failed (size = %lx)\n",
1189 (unsigned long)fsize);
1193 status = cli_close(cli1, fnum1);
1194 if (!NT_STATUS_IS_OK(status)) {
1195 printf("close failed (%s)\n", nt_errstr(status));
1199 if (!torture_close_connection(cli1)) {
1205 static bool run_readwritelarge(int dummy)
1207 return run_readwritelarge_internal();
1210 static bool run_readwritelarge_signtest(int dummy)
1213 signing_state = SMB_SIGNING_REQUIRED;
1214 ret = run_readwritelarge_internal();
1215 signing_state = SMB_SIGNING_DEFAULT;
1222 #define ival(s) strtol(s, NULL, 0)
1224 /* run a test that simulates an approximate netbench client load */
1225 static bool run_netbench(int client)
1227 struct cli_state *cli;
1232 const char *params[20];
1233 bool correct = True;
1239 smbXcli_conn_set_sockopt(cli->conn, sockops);
1243 slprintf(cname,sizeof(cname)-1, "client%d", client);
1245 f = fopen(client_txt, "r");
1252 while (fgets(line, sizeof(line)-1, f)) {
1256 line[strlen(line)-1] = 0;
1258 /* printf("[%d] %s\n", line_count, line); */
1260 all_string_sub(line,"client1", cname, sizeof(line));
1262 /* parse the command parameters */
1263 params[0] = strtok_r(line, " ", &saveptr);
1265 while (params[i]) params[++i] = strtok_r(NULL, " ", &saveptr);
1269 if (i < 2) continue;
1271 if (!strncmp(params[0],"SMB", 3)) {
1272 printf("ERROR: You are using a dbench 1 load file\n");
1276 if (!strcmp(params[0],"NTCreateX")) {
1277 nb_createx(params[1], ival(params[2]), ival(params[3]),
1279 } else if (!strcmp(params[0],"Close")) {
1280 nb_close(ival(params[1]));
1281 } else if (!strcmp(params[0],"Rename")) {
1282 nb_rename(params[1], params[2]);
1283 } else if (!strcmp(params[0],"Unlink")) {
1284 nb_unlink(params[1]);
1285 } else if (!strcmp(params[0],"Deltree")) {
1286 nb_deltree(params[1]);
1287 } else if (!strcmp(params[0],"Rmdir")) {
1288 nb_rmdir(params[1]);
1289 } else if (!strcmp(params[0],"QUERY_PATH_INFORMATION")) {
1290 nb_qpathinfo(params[1]);
1291 } else if (!strcmp(params[0],"QUERY_FILE_INFORMATION")) {
1292 nb_qfileinfo(ival(params[1]));
1293 } else if (!strcmp(params[0],"QUERY_FS_INFORMATION")) {
1294 nb_qfsinfo(ival(params[1]));
1295 } else if (!strcmp(params[0],"FIND_FIRST")) {
1296 nb_findfirst(params[1]);
1297 } else if (!strcmp(params[0],"WriteX")) {
1298 nb_writex(ival(params[1]),
1299 ival(params[2]), ival(params[3]), ival(params[4]));
1300 } else if (!strcmp(params[0],"ReadX")) {
1301 nb_readx(ival(params[1]),
1302 ival(params[2]), ival(params[3]), ival(params[4]));
1303 } else if (!strcmp(params[0],"Flush")) {
1304 nb_flush(ival(params[1]));
1306 printf("Unknown operation %s\n", params[0]);
1314 if (!torture_close_connection(cli)) {
1322 /* run a test that simulates an approximate netbench client load */
1323 static bool run_nbench(int dummy)
1326 bool correct = True;
1328 nbio_shmem(torture_nprocs);
1332 signal(SIGALRM, nb_alarm);
1334 t = create_procs(run_netbench, &correct);
1337 printf("\nThroughput %g MB/sec\n",
1338 1.0e-6 * nbio_total() / t);
1344 This test checks for two things:
1346 1) correct support for retaining locks over a close (ie. the server
1347 must not use posix semantics)
1348 2) support for lock timeouts
1350 static bool run_locktest1(int dummy)
1352 struct cli_state *cli1, *cli2;
1353 const char *fname = "\\lockt1.lck";
1354 uint16_t fnum1, fnum2, fnum3;
1356 unsigned lock_timeout;
1359 if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
1362 smbXcli_conn_set_sockopt(cli1->conn, sockops);
1363 smbXcli_conn_set_sockopt(cli2->conn, sockops);
1365 printf("starting locktest1\n");
1367 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1369 status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
1371 if (!NT_STATUS_IS_OK(status)) {
1372 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
1376 status = cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum2);
1377 if (!NT_STATUS_IS_OK(status)) {
1378 printf("open2 of %s failed (%s)\n", fname, nt_errstr(status));
1382 status = cli_openx(cli2, fname, O_RDWR, DENY_NONE, &fnum3);
1383 if (!NT_STATUS_IS_OK(status)) {
1384 printf("open3 of %s failed (%s)\n", fname, nt_errstr(status));
1388 status = cli_lock32(cli1, fnum1, 0, 4, 0, WRITE_LOCK);
1389 if (!NT_STATUS_IS_OK(status)) {
1390 printf("lock1 failed (%s)\n", nt_errstr(status));
1394 status = cli_lock32(cli2, fnum3, 0, 4, 0, WRITE_LOCK);
1395 if (NT_STATUS_IS_OK(status)) {
1396 printf("lock2 succeeded! This is a locking bug\n");
1399 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1400 NT_STATUS_LOCK_NOT_GRANTED)) {
1405 lock_timeout = (1 + (random() % 20));
1406 printf("Testing lock timeout with timeout=%u\n", lock_timeout);
1408 status = cli_lock32(cli2, fnum3, 0, 4, lock_timeout * 1000, WRITE_LOCK);
1409 if (NT_STATUS_IS_OK(status)) {
1410 printf("lock3 succeeded! This is a locking bug\n");
1413 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1414 NT_STATUS_FILE_LOCK_CONFLICT)) {
1420 if (ABS(t2 - t1) < lock_timeout-1) {
1421 printf("error: This server appears not to support timed lock requests\n");
1424 printf("server slept for %u seconds for a %u second timeout\n",
1425 (unsigned int)(t2-t1), lock_timeout);
1427 status = cli_close(cli1, fnum2);
1428 if (!NT_STATUS_IS_OK(status)) {
1429 printf("close1 failed (%s)\n", nt_errstr(status));
1433 status = cli_lock32(cli2, fnum3, 0, 4, 0, WRITE_LOCK);
1434 if (NT_STATUS_IS_OK(status)) {
1435 printf("lock4 succeeded! This is a locking bug\n");
1438 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1439 NT_STATUS_FILE_LOCK_CONFLICT)) {
1444 status = cli_close(cli1, fnum1);
1445 if (!NT_STATUS_IS_OK(status)) {
1446 printf("close2 failed (%s)\n", nt_errstr(status));
1450 status = cli_close(cli2, fnum3);
1451 if (!NT_STATUS_IS_OK(status)) {
1452 printf("close3 failed (%s)\n", nt_errstr(status));
1456 status = cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1457 if (!NT_STATUS_IS_OK(status)) {
1458 printf("unlink failed (%s)\n", nt_errstr(status));
1463 if (!torture_close_connection(cli1)) {
1467 if (!torture_close_connection(cli2)) {
1471 printf("Passed locktest1\n");
1476 this checks to see if a secondary tconx can use open files from an
1479 static bool run_tcon_test(int dummy)
1481 static struct cli_state *cli;
1482 const char *fname = "\\tcontest.tmp";
1484 uint32_t cnum1, cnum2, cnum3;
1485 struct smbXcli_tcon *orig_tcon = NULL;
1486 char *orig_share = NULL;
1487 uint16_t vuid1, vuid2;
1492 memset(buf, '\0', sizeof(buf));
1494 if (!torture_open_connection(&cli, 0)) {
1497 smbXcli_conn_set_sockopt(cli->conn, sockops);
1499 printf("starting tcontest\n");
1501 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1503 status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
1504 if (!NT_STATUS_IS_OK(status)) {
1505 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
1509 cnum1 = cli_state_get_tid(cli);
1510 vuid1 = cli_state_get_uid(cli);
1512 status = cli_writeall(cli, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
1513 if (!NT_STATUS_IS_OK(status)) {
1514 printf("initial write failed (%s)", nt_errstr(status));
1518 cli_state_save_tcon_share(cli, &orig_tcon, &orig_share);
1520 status = cli_tree_connect_creds(cli, share, "?????", torture_creds);
1521 if (!NT_STATUS_IS_OK(status)) {
1522 printf("%s refused 2nd tree connect (%s)\n", host,
1524 cli_state_restore_tcon_share(cli, orig_tcon, orig_share);
1529 cnum2 = cli_state_get_tid(cli);
1530 cnum3 = MAX(cnum1, cnum2) + 1; /* any invalid number */
1531 vuid2 = cli_state_get_uid(cli) + 1;
1533 /* try a write with the wrong tid */
1534 cli_state_set_tid(cli, cnum2);
1536 status = cli_writeall(cli, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
1537 if (NT_STATUS_IS_OK(status)) {
1538 printf("* server allows write with wrong TID\n");
1541 printf("server fails write with wrong TID : %s\n",
1546 /* try a write with an invalid tid */
1547 cli_state_set_tid(cli, cnum3);
1549 status = cli_writeall(cli, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
1550 if (NT_STATUS_IS_OK(status)) {
1551 printf("* server allows write with invalid TID\n");
1554 printf("server fails write with invalid TID : %s\n",
1558 /* try a write with an invalid vuid */
1559 cli_state_set_uid(cli, vuid2);
1560 cli_state_set_tid(cli, cnum1);
1562 status = cli_writeall(cli, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
1563 if (NT_STATUS_IS_OK(status)) {
1564 printf("* server allows write with invalid VUID\n");
1567 printf("server fails write with invalid VUID : %s\n",
1571 cli_state_set_tid(cli, cnum1);
1572 cli_state_set_uid(cli, vuid1);
1574 status = cli_close(cli, fnum1);
1575 if (!NT_STATUS_IS_OK(status)) {
1576 printf("close failed (%s)\n", nt_errstr(status));
1577 cli_state_restore_tcon_share(cli, orig_tcon, orig_share);
1582 cli_state_set_tid(cli, cnum2);
1584 status = cli_tdis(cli);
1585 if (!NT_STATUS_IS_OK(status)) {
1586 printf("secondary tdis failed (%s)\n", nt_errstr(status));
1587 cli_state_restore_tcon_share(cli, orig_tcon, orig_share);
1592 cli_state_restore_tcon_share(cli, orig_tcon, orig_share);
1594 cli_state_set_tid(cli, cnum1);
1596 if (!torture_close_connection(cli)) {
1605 checks for old style tcon support
1607 static bool run_tcon2_test(int dummy)
1609 static struct cli_state *cli;
1610 uint16_t cnum, max_xmit;
1614 if (!torture_open_connection(&cli, 0)) {
1617 smbXcli_conn_set_sockopt(cli->conn, sockops);
1619 printf("starting tcon2 test\n");
1621 if (asprintf(&service, "\\\\%s\\%s", host, share) == -1) {
1625 status = cli_raw_tcon(cli, service, password, "?????", &max_xmit, &cnum);
1629 if (!NT_STATUS_IS_OK(status)) {
1630 printf("tcon2 failed : %s\n", nt_errstr(status));
1632 printf("tcon OK : max_xmit=%d cnum=%d\n",
1633 (int)max_xmit, (int)cnum);
1636 if (!torture_close_connection(cli)) {
1640 printf("Passed tcon2 test\n");
1644 static bool tcon_devtest(struct cli_state *cli,
1645 const char *myshare, const char *devtype,
1646 const char *return_devtype,
1647 NTSTATUS expected_error)
1652 status = cli_tree_connect_creds(cli, myshare, devtype, torture_creds);
1654 if (NT_STATUS_IS_OK(expected_error)) {
1655 if (NT_STATUS_IS_OK(status)) {
1656 if (return_devtype != NULL &&
1657 strequal(cli->dev, return_devtype)) {
1660 printf("tconX to share %s with type %s "
1661 "succeeded but returned the wrong "
1662 "device type (got [%s] but should have got [%s])\n",
1663 myshare, devtype, cli->dev, return_devtype);
1667 printf("tconX to share %s with type %s "
1668 "should have succeeded but failed\n",
1674 if (NT_STATUS_IS_OK(status)) {
1675 printf("tconx to share %s with type %s "
1676 "should have failed but succeeded\n",
1680 if (NT_STATUS_EQUAL(status, expected_error)) {
1683 printf("Returned unexpected error\n");
1692 checks for correct tconX support
1694 static bool run_tcon_devtype_test(int dummy)
1696 static struct cli_state *cli1 = NULL;
1697 int flags = CLI_FULL_CONNECTION_FORCE_SMB1;
1701 status = cli_full_connection_creds(&cli1,
1707 NULL, /* service_type */
1711 if (!NT_STATUS_IS_OK(status)) {
1712 printf("could not open connection\n");
1716 if (!tcon_devtest(cli1, "IPC$", "A:", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1719 if (!tcon_devtest(cli1, "IPC$", "?????", "IPC", NT_STATUS_OK))
1722 if (!tcon_devtest(cli1, "IPC$", "LPT:", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1725 if (!tcon_devtest(cli1, "IPC$", "IPC", "IPC", NT_STATUS_OK))
1728 if (!tcon_devtest(cli1, "IPC$", "FOOBA", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1731 if (!tcon_devtest(cli1, share, "A:", "A:", NT_STATUS_OK))
1734 if (!tcon_devtest(cli1, share, "?????", "A:", NT_STATUS_OK))
1737 if (!tcon_devtest(cli1, share, "LPT:", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1740 if (!tcon_devtest(cli1, share, "IPC", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1743 if (!tcon_devtest(cli1, share, "FOOBA", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1749 printf("Passed tcondevtest\n");
1756 This test checks that
1758 1) the server supports multiple locking contexts on the one SMB
1759 connection, distinguished by PID.
1761 2) the server correctly fails overlapping locks made by the same PID (this
1762 goes against POSIX behaviour, which is why it is tricky to implement)
1764 3) the server denies unlock requests by an incorrect client PID
1766 static bool run_locktest2(int dummy)
1768 static struct cli_state *cli;
1769 const char *fname = "\\lockt2.lck";
1770 uint16_t fnum1, fnum2, fnum3;
1771 bool correct = True;
1774 if (!torture_open_connection(&cli, 0)) {
1778 smbXcli_conn_set_sockopt(cli->conn, sockops);
1780 printf("starting locktest2\n");
1782 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1786 status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
1787 if (!NT_STATUS_IS_OK(status)) {
1788 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
1792 status = cli_openx(cli, fname, O_RDWR, DENY_NONE, &fnum2);
1793 if (!NT_STATUS_IS_OK(status)) {
1794 printf("open2 of %s failed (%s)\n", fname, nt_errstr(status));
1800 status = cli_openx(cli, fname, O_RDWR, DENY_NONE, &fnum3);
1801 if (!NT_STATUS_IS_OK(status)) {
1802 printf("open3 of %s failed (%s)\n", fname, nt_errstr(status));
1808 status = cli_lock32(cli, fnum1, 0, 4, 0, WRITE_LOCK);
1809 if (!NT_STATUS_IS_OK(status)) {
1810 printf("lock1 failed (%s)\n", nt_errstr(status));
1814 status = cli_lock32(cli, fnum1, 0, 4, 0, WRITE_LOCK);
1815 if (NT_STATUS_IS_OK(status)) {
1816 printf("WRITE lock1 succeeded! This is a locking bug\n");
1819 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1820 NT_STATUS_LOCK_NOT_GRANTED)) {
1825 status = cli_lock32(cli, fnum2, 0, 4, 0, WRITE_LOCK);
1826 if (NT_STATUS_IS_OK(status)) {
1827 printf("WRITE lock2 succeeded! This is a locking bug\n");
1830 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1831 NT_STATUS_LOCK_NOT_GRANTED)) {
1836 status = cli_lock32(cli, fnum2, 0, 4, 0, READ_LOCK);
1837 if (NT_STATUS_IS_OK(status)) {
1838 printf("READ lock2 succeeded! This is a locking bug\n");
1841 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1842 NT_STATUS_FILE_LOCK_CONFLICT)) {
1847 status = cli_lock32(cli, fnum1, 100, 4, 0, WRITE_LOCK);
1848 if (!NT_STATUS_IS_OK(status)) {
1849 printf("lock at 100 failed (%s)\n", nt_errstr(status));
1852 if (NT_STATUS_IS_OK(cli_unlock(cli, fnum1, 100, 4))) {
1853 printf("unlock at 100 succeeded! This is a locking bug\n");
1857 status = cli_unlock(cli, fnum1, 0, 4);
1858 if (NT_STATUS_IS_OK(status)) {
1859 printf("unlock1 succeeded! This is a locking bug\n");
1862 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1863 NT_STATUS_RANGE_NOT_LOCKED)) {
1868 status = cli_unlock(cli, fnum1, 0, 8);
1869 if (NT_STATUS_IS_OK(status)) {
1870 printf("unlock2 succeeded! This is a locking bug\n");
1873 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1874 NT_STATUS_RANGE_NOT_LOCKED)) {
1879 status = cli_lock32(cli, fnum3, 0, 4, 0, WRITE_LOCK);
1880 if (NT_STATUS_IS_OK(status)) {
1881 printf("lock3 succeeded! This is a locking bug\n");
1884 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1885 NT_STATUS_LOCK_NOT_GRANTED)) {
1892 status = cli_close(cli, fnum1);
1893 if (!NT_STATUS_IS_OK(status)) {
1894 printf("close1 failed (%s)\n", nt_errstr(status));
1898 status = cli_close(cli, fnum2);
1899 if (!NT_STATUS_IS_OK(status)) {
1900 printf("close2 failed (%s)\n", nt_errstr(status));
1904 status = cli_close(cli, fnum3);
1905 if (!NT_STATUS_IS_OK(status)) {
1906 printf("close3 failed (%s)\n", nt_errstr(status));
1910 if (!torture_close_connection(cli)) {
1914 printf("locktest2 finished\n");
1921 This test checks that
1923 1) the server supports the full offset range in lock requests
1925 static bool run_locktest3(int dummy)
1927 static struct cli_state *cli1, *cli2;
1928 const char *fname = "\\lockt3.lck";
1929 uint16_t fnum1, fnum2;
1932 bool correct = True;
1935 #define NEXT_OFFSET offset += (~(uint32_t)0) / torture_numops
1937 if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
1940 smbXcli_conn_set_sockopt(cli1->conn, sockops);
1941 smbXcli_conn_set_sockopt(cli2->conn, sockops);
1943 printf("starting locktest3\n");
1945 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1947 status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
1949 if (!NT_STATUS_IS_OK(status)) {
1950 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
1954 status = cli_openx(cli2, fname, O_RDWR, DENY_NONE, &fnum2);
1955 if (!NT_STATUS_IS_OK(status)) {
1956 printf("open2 of %s failed (%s)\n", fname, nt_errstr(status));
1960 for (offset=i=0;i<torture_numops;i++) {
1963 status = cli_lock32(cli1, fnum1, offset-1, 1, 0, WRITE_LOCK);
1964 if (!NT_STATUS_IS_OK(status)) {
1965 printf("lock1 %d failed (%s)\n",
1971 status = cli_lock32(cli2, fnum2, offset-2, 1, 0, WRITE_LOCK);
1972 if (!NT_STATUS_IS_OK(status)) {
1973 printf("lock2 %d failed (%s)\n",
1980 for (offset=i=0;i<torture_numops;i++) {
1983 status = cli_lock32(cli1, fnum1, offset-2, 1, 0, WRITE_LOCK);
1984 if (NT_STATUS_IS_OK(status)) {
1985 printf("error: lock1 %d succeeded!\n", i);
1989 status = cli_lock32(cli2, fnum2, offset-1, 1, 0, WRITE_LOCK);
1990 if (NT_STATUS_IS_OK(status)) {
1991 printf("error: lock2 %d succeeded!\n", i);
1995 status = cli_lock32(cli1, fnum1, offset-1, 1, 0, WRITE_LOCK);
1996 if (NT_STATUS_IS_OK(status)) {
1997 printf("error: lock3 %d succeeded!\n", i);
2001 status = cli_lock32(cli2, fnum2, offset-2, 1, 0, WRITE_LOCK);
2002 if (NT_STATUS_IS_OK(status)) {
2003 printf("error: lock4 %d succeeded!\n", i);
2008 for (offset=i=0;i<torture_numops;i++) {
2011 status = cli_unlock(cli1, fnum1, offset-1, 1);
2012 if (!NT_STATUS_IS_OK(status)) {
2013 printf("unlock1 %d failed (%s)\n",
2019 status = cli_unlock(cli2, fnum2, offset-2, 1);
2020 if (!NT_STATUS_IS_OK(status)) {
2021 printf("unlock2 %d failed (%s)\n",
2028 status = cli_close(cli1, fnum1);
2029 if (!NT_STATUS_IS_OK(status)) {
2030 printf("close1 failed (%s)\n", nt_errstr(status));
2034 status = cli_close(cli2, fnum2);
2035 if (!NT_STATUS_IS_OK(status)) {
2036 printf("close2 failed (%s)\n", nt_errstr(status));
2040 status = cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2041 if (!NT_STATUS_IS_OK(status)) {
2042 printf("unlink failed (%s)\n", nt_errstr(status));
2046 if (!torture_close_connection(cli1)) {
2050 if (!torture_close_connection(cli2)) {
2054 printf("finished locktest3\n");
2059 static bool test_cli_read(struct cli_state *cli, uint16_t fnum,
2060 char *buf, off_t offset, size_t size,
2061 size_t *nread, size_t expect)
2066 status = cli_read(cli, fnum, buf, offset, size, &l_nread);
2068 if(!NT_STATUS_IS_OK(status)) {
2070 } else if (l_nread != expect) {
2081 #define EXPECTED(ret, v) if ((ret) != (v)) { \
2082 printf("** "); correct = False; \
2086 looks at overlapping locks
2088 static bool run_locktest4(int dummy)
2090 static struct cli_state *cli1, *cli2;
2091 const char *fname = "\\lockt4.lck";
2092 uint16_t fnum1, fnum2, f;
2095 bool correct = True;
2098 if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
2102 smbXcli_conn_set_sockopt(cli1->conn, sockops);
2103 smbXcli_conn_set_sockopt(cli2->conn, sockops);
2105 printf("starting locktest4\n");
2107 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2109 cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
2110 cli_openx(cli2, fname, O_RDWR, DENY_NONE, &fnum2);
2112 memset(buf, 0, sizeof(buf));
2114 status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 0, sizeof(buf),
2116 if (!NT_STATUS_IS_OK(status)) {
2117 printf("Failed to create file: %s\n", nt_errstr(status));
2122 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 4, 0, WRITE_LOCK)) &&
2123 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 2, 4, 0, WRITE_LOCK));
2124 EXPECTED(ret, False);
2125 printf("the same process %s set overlapping write locks\n", ret?"can":"cannot");
2127 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 10, 4, 0, READ_LOCK)) &&
2128 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 12, 4, 0, READ_LOCK));
2129 EXPECTED(ret, True);
2130 printf("the same process %s set overlapping read locks\n", ret?"can":"cannot");
2132 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 20, 4, 0, WRITE_LOCK)) &&
2133 NT_STATUS_IS_OK(cli_lock32(cli2, fnum2, 22, 4, 0, WRITE_LOCK));
2134 EXPECTED(ret, False);
2135 printf("a different connection %s set overlapping write locks\n", ret?"can":"cannot");
2137 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 30, 4, 0, READ_LOCK)) &&
2138 NT_STATUS_IS_OK(cli_lock32(cli2, fnum2, 32, 4, 0, READ_LOCK));
2139 EXPECTED(ret, True);
2140 printf("a different connection %s set overlapping read locks\n", ret?"can":"cannot");
2142 ret = (cli_setpid(cli1, 1),
2143 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 40, 4, 0, WRITE_LOCK))) &&
2144 (cli_setpid(cli1, 2),
2145 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 42, 4, 0, WRITE_LOCK)));
2146 EXPECTED(ret, False);
2147 printf("a different pid %s set overlapping write locks\n", ret?"can":"cannot");
2149 ret = (cli_setpid(cli1, 1),
2150 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 50, 4, 0, READ_LOCK))) &&
2151 (cli_setpid(cli1, 2),
2152 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 52, 4, 0, READ_LOCK)));
2153 EXPECTED(ret, True);
2154 printf("a different pid %s set overlapping read locks\n", ret?"can":"cannot");
2156 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 60, 4, 0, READ_LOCK)) &&
2157 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 60, 4, 0, READ_LOCK));
2158 EXPECTED(ret, True);
2159 printf("the same process %s set the same read lock twice\n", ret?"can":"cannot");
2161 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 70, 4, 0, WRITE_LOCK)) &&
2162 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 70, 4, 0, WRITE_LOCK));
2163 EXPECTED(ret, False);
2164 printf("the same process %s set the same write lock twice\n", ret?"can":"cannot");
2166 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 80, 4, 0, READ_LOCK)) &&
2167 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 80, 4, 0, WRITE_LOCK));
2168 EXPECTED(ret, False);
2169 printf("the same process %s overlay a read lock with a write lock\n", ret?"can":"cannot");
2171 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 90, 4, 0, WRITE_LOCK)) &&
2172 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 90, 4, 0, READ_LOCK));
2173 EXPECTED(ret, True);
2174 printf("the same process %s overlay a write lock with a read lock\n", ret?"can":"cannot");
2176 ret = (cli_setpid(cli1, 1),
2177 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 100, 4, 0, WRITE_LOCK))) &&
2178 (cli_setpid(cli1, 2),
2179 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 100, 4, 0, READ_LOCK)));
2180 EXPECTED(ret, False);
2181 printf("a different pid %s overlay a write lock with a read lock\n", ret?"can":"cannot");
2183 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 110, 4, 0, READ_LOCK)) &&
2184 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 112, 4, 0, READ_LOCK)) &&
2185 NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 110, 6));
2186 EXPECTED(ret, False);
2187 printf("the same process %s coalesce read locks\n", ret?"can":"cannot");
2190 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 120, 4, 0, WRITE_LOCK)) &&
2191 test_cli_read(cli2, fnum2, buf, 120, 4, NULL, 4);
2192 EXPECTED(ret, False);
2193 printf("this server %s strict write locking\n", ret?"doesn't do":"does");
2195 status = cli_lock32(cli1, fnum1, 130, 4, 0, READ_LOCK);
2196 ret = NT_STATUS_IS_OK(status);
2198 status = cli_writeall(cli2, fnum2, 0, (uint8_t *)buf, 130, 4,
2200 ret = NT_STATUS_IS_OK(status);
2202 EXPECTED(ret, False);
2203 printf("this server %s strict read locking\n", ret?"doesn't do":"does");
2206 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 140, 4, 0, READ_LOCK)) &&
2207 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 140, 4, 0, READ_LOCK)) &&
2208 NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 140, 4)) &&
2209 NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 140, 4));
2210 EXPECTED(ret, True);
2211 printf("this server %s do recursive read locking\n", ret?"does":"doesn't");
2214 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 150, 4, 0, WRITE_LOCK)) &&
2215 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 150, 4, 0, READ_LOCK)) &&
2216 NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 150, 4)) &&
2217 test_cli_read(cli2, fnum2, buf, 150, 4, NULL, 4) &&
2218 !(NT_STATUS_IS_OK(cli_writeall(cli2, fnum2, 0, (uint8_t *)buf,
2220 NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 150, 4));
2221 EXPECTED(ret, True);
2222 printf("this server %s do recursive lock overlays\n", ret?"does":"doesn't");
2224 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 160, 4, 0, READ_LOCK)) &&
2225 NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 160, 4)) &&
2226 NT_STATUS_IS_OK(cli_writeall(cli2, fnum2, 0, (uint8_t *)buf,
2228 test_cli_read(cli2, fnum2, buf, 160, 4, NULL, 4);
2229 EXPECTED(ret, True);
2230 printf("the same process %s remove a read lock using write locking\n", ret?"can":"cannot");
2232 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 170, 4, 0, WRITE_LOCK)) &&
2233 NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 170, 4)) &&
2234 NT_STATUS_IS_OK(cli_writeall(cli2, fnum2, 0, (uint8_t *)buf,
2236 test_cli_read(cli2, fnum2, buf, 170, 4, NULL, 4);
2237 EXPECTED(ret, True);
2238 printf("the same process %s remove a write lock using read locking\n", ret?"can":"cannot");
2240 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 190, 4, 0, WRITE_LOCK)) &&
2241 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 190, 4, 0, READ_LOCK)) &&
2242 NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 190, 4)) &&
2243 !NT_STATUS_IS_OK(cli_writeall(cli2, fnum2, 0, (uint8_t *)buf,
2245 test_cli_read(cli2, fnum2, buf, 190, 4, NULL, 4);
2246 EXPECTED(ret, True);
2247 printf("the same process %s remove the first lock first\n", ret?"does":"doesn't");
2249 cli_close(cli1, fnum1);
2250 cli_close(cli2, fnum2);
2251 cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
2252 cli_openx(cli1, fname, O_RDWR, DENY_NONE, &f);
2253 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 8, 0, READ_LOCK)) &&
2254 NT_STATUS_IS_OK(cli_lock32(cli1, f, 0, 1, 0, READ_LOCK)) &&
2255 NT_STATUS_IS_OK(cli_close(cli1, fnum1)) &&
2256 NT_STATUS_IS_OK(cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1)) &&
2257 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 7, 1, 0, WRITE_LOCK));
2259 cli_close(cli1, fnum1);
2260 EXPECTED(ret, True);
2261 printf("the server %s have the NT byte range lock bug\n", !ret?"does":"doesn't");
2264 cli_close(cli1, fnum1);
2265 cli_close(cli2, fnum2);
2266 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2267 torture_close_connection(cli1);
2268 torture_close_connection(cli2);
2270 printf("finished locktest4\n");
2275 looks at lock upgrade/downgrade.
2277 static bool run_locktest5(int dummy)
2279 static struct cli_state *cli1, *cli2;
2280 const char *fname = "\\lockt5.lck";
2281 uint16_t fnum1, fnum2, fnum3;
2284 bool correct = True;
2287 if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
2291 smbXcli_conn_set_sockopt(cli1->conn, sockops);
2292 smbXcli_conn_set_sockopt(cli2->conn, sockops);
2294 printf("starting locktest5\n");
2296 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2298 cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
2299 cli_openx(cli2, fname, O_RDWR, DENY_NONE, &fnum2);
2300 cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum3);
2302 memset(buf, 0, sizeof(buf));
2304 status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 0, sizeof(buf),
2306 if (!NT_STATUS_IS_OK(status)) {
2307 printf("Failed to create file: %s\n", nt_errstr(status));
2312 /* Check for NT bug... */
2313 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 8, 0, READ_LOCK)) &&
2314 NT_STATUS_IS_OK(cli_lock32(cli1, fnum3, 0, 1, 0, READ_LOCK));
2315 cli_close(cli1, fnum1);
2316 cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
2317 status = cli_lock32(cli1, fnum1, 7, 1, 0, WRITE_LOCK);
2318 ret = NT_STATUS_IS_OK(status);
2319 EXPECTED(ret, True);
2320 printf("this server %s the NT locking bug\n", ret ? "doesn't have" : "has");
2321 cli_close(cli1, fnum1);
2322 cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
2323 cli_unlock(cli1, fnum3, 0, 1);
2325 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 4, 0, WRITE_LOCK)) &&
2326 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 1, 1, 0, READ_LOCK));
2327 EXPECTED(ret, True);
2328 printf("the same process %s overlay a write with a read lock\n", ret?"can":"cannot");
2330 status = cli_lock32(cli2, fnum2, 0, 4, 0, READ_LOCK);
2331 ret = NT_STATUS_IS_OK(status);
2332 EXPECTED(ret, False);
2334 printf("a different process %s get a read lock on the first process lock stack\n", ret?"can":"cannot");
2336 /* Unlock the process 2 lock. */
2337 cli_unlock(cli2, fnum2, 0, 4);
2339 status = cli_lock32(cli1, fnum3, 0, 4, 0, READ_LOCK);
2340 ret = NT_STATUS_IS_OK(status);
2341 EXPECTED(ret, False);
2343 printf("the same process on a different fnum %s get a read lock\n", ret?"can":"cannot");
2345 /* Unlock the process 1 fnum3 lock. */
2346 cli_unlock(cli1, fnum3, 0, 4);
2348 /* Stack 2 more locks here. */
2349 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 4, 0, READ_LOCK)) &&
2350 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 4, 0, READ_LOCK));
2352 EXPECTED(ret, True);
2353 printf("the same process %s stack read locks\n", ret?"can":"cannot");
2355 /* Unlock the first process lock, then check this was the WRITE lock that was
2358 ret = NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 0, 4)) &&
2359 NT_STATUS_IS_OK(cli_lock32(cli2, fnum2, 0, 4, 0, READ_LOCK));
2361 EXPECTED(ret, True);
2362 printf("the first unlock removes the %s lock\n", ret?"WRITE":"READ");
2364 /* Unlock the process 2 lock. */
2365 cli_unlock(cli2, fnum2, 0, 4);
2367 /* We should have 3 stacked locks here. Ensure we need to do 3 unlocks. */
2369 ret = NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 1, 1)) &&
2370 NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 0, 4)) &&
2371 NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 0, 4));
2373 EXPECTED(ret, True);
2374 printf("the same process %s unlock the stack of 4 locks\n", ret?"can":"cannot");
2376 /* Ensure the next unlock fails. */
2377 ret = NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 0, 4));
2378 EXPECTED(ret, False);
2379 printf("the same process %s count the lock stack\n", !ret?"can":"cannot");
2381 /* Ensure connection 2 can get a write lock. */
2382 status = cli_lock32(cli2, fnum2, 0, 4, 0, WRITE_LOCK);
2383 ret = NT_STATUS_IS_OK(status);
2384 EXPECTED(ret, True);
2386 printf("a different process %s get a write lock on the unlocked stack\n", ret?"can":"cannot");
2390 cli_close(cli1, fnum1);
2391 cli_close(cli2, fnum2);
2392 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2393 if (!torture_close_connection(cli1)) {
2396 if (!torture_close_connection(cli2)) {
2400 printf("finished locktest5\n");
2406 tries the unusual lockingX locktype bits
2408 static bool run_locktest6(int dummy)
2410 static struct cli_state *cli;
2411 const char *fname[1] = { "\\lock6.txt" };
2416 if (!torture_open_connection(&cli, 0)) {
2420 smbXcli_conn_set_sockopt(cli->conn, sockops);
2422 printf("starting locktest6\n");
2425 printf("Testing %s\n", fname[i]);
2427 cli_unlink(cli, fname[i], FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2429 cli_openx(cli, fname[i], O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
2430 status = cli_locktype(cli, fnum, 0, 8, 0, LOCKING_ANDX_CHANGE_LOCKTYPE);
2431 cli_close(cli, fnum);
2432 printf("CHANGE_LOCKTYPE gave %s\n", nt_errstr(status));
2434 cli_openx(cli, fname[i], O_RDWR, DENY_NONE, &fnum);
2435 status = cli_locktype(cli, fnum, 0, 8, 0, LOCKING_ANDX_CANCEL_LOCK);
2436 cli_close(cli, fnum);
2437 printf("CANCEL_LOCK gave %s\n", nt_errstr(status));
2439 cli_unlink(cli, fname[i], FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2442 torture_close_connection(cli);
2444 printf("finished locktest6\n");
2448 static bool run_locktest7(int dummy)
2450 struct cli_state *cli1;
2451 const char *fname = "\\lockt7.lck";
2454 bool correct = False;
2458 if (!torture_open_connection(&cli1, 0)) {
2462 smbXcli_conn_set_sockopt(cli1->conn, sockops);
2464 printf("starting locktest7\n");
2466 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2468 cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
2470 memset(buf, 0, sizeof(buf));
2472 status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 0, sizeof(buf),
2474 if (!NT_STATUS_IS_OK(status)) {
2475 printf("Failed to create file: %s\n", nt_errstr(status));
2479 cli_setpid(cli1, 1);
2481 status = cli_lock32(cli1, fnum1, 130, 4, 0, READ_LOCK);
2482 if (!NT_STATUS_IS_OK(status)) {
2483 printf("Unable to apply read lock on range 130:4, "
2484 "error was %s\n", nt_errstr(status));
2487 printf("pid1 successfully locked range 130:4 for READ\n");
2490 status = cli_read(cli1, fnum1, buf, 130, 4, &nread);
2491 if (!NT_STATUS_IS_OK(status)) {
2492 printf("pid1 unable to read the range 130:4, error was %s\n",
2495 } else if (nread != 4) {
2496 printf("pid1 unable to read the range 130:4, "
2497 "recv %ld req %d\n", (unsigned long)nread, 4);
2500 printf("pid1 successfully read the range 130:4\n");
2503 status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
2504 if (!NT_STATUS_IS_OK(status)) {
2505 printf("pid1 unable to write to the range 130:4, error was "
2506 "%s\n", nt_errstr(status));
2507 if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
2508 printf("Incorrect error (should be NT_STATUS_FILE_LOCK_CONFLICT)\n");
2512 printf("pid1 successfully wrote to the range 130:4 (should be denied)\n");
2516 cli_setpid(cli1, 2);
2518 status = cli_read(cli1, fnum1, buf, 130, 4, &nread);
2519 if (!NT_STATUS_IS_OK(status)) {
2520 printf("pid2 unable to read the range 130:4, error was %s\n",
2523 } else if (nread != 4) {
2524 printf("pid2 unable to read the range 130:4, "
2525 "recv %ld req %d\n", (unsigned long)nread, 4);
2528 printf("pid2 successfully read the range 130:4\n");
2531 status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
2532 if (!NT_STATUS_IS_OK(status)) {
2533 printf("pid2 unable to write to the range 130:4, error was "
2534 "%s\n", nt_errstr(status));
2535 if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
2536 printf("Incorrect error (should be NT_STATUS_FILE_LOCK_CONFLICT)\n");
2540 printf("pid2 successfully wrote to the range 130:4 (should be denied)\n");
2544 cli_setpid(cli1, 1);
2545 cli_unlock(cli1, fnum1, 130, 4);
2547 status = cli_lock32(cli1, fnum1, 130, 4, 0, WRITE_LOCK);
2548 if (!NT_STATUS_IS_OK(status)) {
2549 printf("Unable to apply write lock on range 130:4, error was %s\n", nt_errstr(status));
2552 printf("pid1 successfully locked range 130:4 for WRITE\n");
2555 status = cli_read(cli1, fnum1, buf, 130, 4, &nread);
2556 if (!NT_STATUS_IS_OK(status)) {
2557 printf("pid1 unable to read the range 130:4, error was %s\n",
2560 } else if (nread != 4) {
2561 printf("pid1 unable to read the range 130:4, "
2562 "recv %ld req %d\n", (unsigned long)nread, 4);
2565 printf("pid1 successfully read the range 130:4\n");
2568 status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
2569 if (!NT_STATUS_IS_OK(status)) {
2570 printf("pid1 unable to write to the range 130:4, error was "
2571 "%s\n", nt_errstr(status));
2574 printf("pid1 successfully wrote to the range 130:4\n");
2577 cli_setpid(cli1, 2);
2579 status = cli_read(cli1, fnum1, buf, 130, 4, &nread);
2580 if (!NT_STATUS_IS_OK(status)) {
2581 printf("pid2 unable to read the range 130:4, error was "
2582 "%s\n", nt_errstr(status));
2583 if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
2584 printf("Incorrect error (should be NT_STATUS_FILE_LOCK_CONFLICT)\n");
2588 printf("pid2 successfully read the range 130:4 (should be denied) recv %ld\n",
2589 (unsigned long)nread);
2593 status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
2594 if (!NT_STATUS_IS_OK(status)) {
2595 printf("pid2 unable to write to the range 130:4, error was "
2596 "%s\n", nt_errstr(status));
2597 if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
2598 printf("Incorrect error (should be NT_STATUS_FILE_LOCK_CONFLICT)\n");
2602 printf("pid2 successfully wrote to the range 130:4 (should be denied)\n");
2606 cli_unlock(cli1, fnum1, 130, 0);
2610 cli_close(cli1, fnum1);
2611 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2612 torture_close_connection(cli1);
2614 printf("finished locktest7\n");
2619 * This demonstrates a problem with our use of GPFS share modes: A file
2620 * descriptor sitting in the pending close queue holding a GPFS share mode
2621 * blocks opening a file another time. Happens with Word 2007 temp files.
2622 * With "posix locking = yes" and "gpfs:sharemodes = yes" enabled, the third
2623 * open is denied with NT_STATUS_SHARING_VIOLATION.
2626 static bool run_locktest8(int dummy)
2628 struct cli_state *cli1;
2629 const char *fname = "\\lockt8.lck";
2630 uint16_t fnum1, fnum2;
2632 bool correct = False;
2635 if (!torture_open_connection(&cli1, 0)) {
2639 smbXcli_conn_set_sockopt(cli1->conn, sockops);
2641 printf("starting locktest8\n");
2643 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2645 status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_WRITE,
2647 if (!NT_STATUS_IS_OK(status)) {
2648 d_fprintf(stderr, "cli_openx returned %s\n", nt_errstr(status));
2652 memset(buf, 0, sizeof(buf));
2654 status = cli_openx(cli1, fname, O_RDONLY, DENY_NONE, &fnum2);
2655 if (!NT_STATUS_IS_OK(status)) {
2656 d_fprintf(stderr, "cli_openx second time returned %s\n",
2661 status = cli_lock32(cli1, fnum2, 1, 1, 0, READ_LOCK);
2662 if (!NT_STATUS_IS_OK(status)) {
2663 printf("Unable to apply read lock on range 1:1, error was "
2664 "%s\n", nt_errstr(status));
2668 status = cli_close(cli1, fnum1);
2669 if (!NT_STATUS_IS_OK(status)) {
2670 d_fprintf(stderr, "cli_close(fnum1) %s\n", nt_errstr(status));
2674 status = cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
2675 if (!NT_STATUS_IS_OK(status)) {
2676 d_fprintf(stderr, "cli_openx third time returned %s\n",
2684 cli_close(cli1, fnum1);
2685 cli_close(cli1, fnum2);
2686 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2687 torture_close_connection(cli1);
2689 printf("finished locktest8\n");
2694 * This test is designed to be run in conjunction with
2695 * external NFS or POSIX locks taken in the filesystem.
2696 * It checks that the smbd server will block until the
2697 * lock is released and then acquire it. JRA.
2700 static bool got_alarm;
2701 static struct cli_state *alarm_cli;
2703 static void alarm_handler(int dummy)
2708 static void alarm_handler_parent(int dummy)
2710 smbXcli_conn_disconnect(alarm_cli->conn, NT_STATUS_LOCAL_DISCONNECT);
2713 static void do_local_lock(const char *fname, int read_fd, int write_fd)
2718 const char *local_pathname = NULL;
2721 local_pathname = talloc_asprintf(talloc_tos(),
2722 "%s/%s", local_path, fname);
2723 if (!local_pathname) {
2724 printf("child: alloc fail\n");
2728 unlink(local_pathname);
2729 fd = open(local_pathname, O_RDWR|O_CREAT, 0666);
2731 printf("child: open of %s failed %s.\n",
2732 local_pathname, strerror(errno));
2736 /* Now take a fcntl lock. */
2737 lock.l_type = F_WRLCK;
2738 lock.l_whence = SEEK_SET;
2741 lock.l_pid = getpid();
2743 ret = fcntl(fd,F_SETLK,&lock);
2745 printf("child: failed to get lock 0:4 on file %s. Error %s\n",
2746 local_pathname, strerror(errno));
2749 printf("child: got lock 0:4 on file %s.\n",
2754 CatchSignal(SIGALRM, alarm_handler);
2756 /* Signal the parent. */
2757 if (write(write_fd, &c, 1) != 1) {
2758 printf("child: start signal fail %s.\n",
2765 /* Wait for the parent to be ready. */
2766 if (read(read_fd, &c, 1) != 1) {
2767 printf("child: reply signal fail %s.\n",
2775 printf("child: released lock 0:4 on file %s.\n",
2781 static bool _run_locktest9X(const char *fname, int timeout)
2783 struct cli_state *cli1;
2784 char *fpath = talloc_asprintf(talloc_tos(), "\\%s", fname);
2786 bool correct = False;
2787 int pipe_in[2], pipe_out[2];
2791 struct timeval start;
2795 printf("starting locktest9X: %s\n", fname);
2797 if (local_path == NULL) {
2798 d_fprintf(stderr, "locktest9X must be given a local path via -l <localpath>\n");
2802 if (pipe(pipe_in) == -1 || pipe(pipe_out) == -1) {
2807 if (child_pid == -1) {
2811 if (child_pid == 0) {
2813 do_local_lock(fname, pipe_out[0], pipe_in[1]);
2823 ret = read(pipe_in[0], &c, 1);
2825 d_fprintf(stderr, "failed to read start signal from child. %s\n",
2830 if (!torture_open_connection(&cli1, 0)) {
2834 smbXcli_conn_set_sockopt(cli1->conn, sockops);
2836 status = cli_openx(cli1, fpath, O_RDWR, DENY_NONE,
2838 if (!NT_STATUS_IS_OK(status)) {
2839 d_fprintf(stderr, "cli_openx returned %s\n", nt_errstr(status));
2843 /* Ensure the child has the lock. */
2844 status = cli_lock32(cli1, fnum, 0, 4, 0, WRITE_LOCK);
2845 if (NT_STATUS_IS_OK(status)) {
2846 d_fprintf(stderr, "Got the lock on range 0:4 - this should not happen !\n");
2849 d_printf("Child has the lock.\n");
2852 /* Tell the child to wait 5 seconds then exit. */
2853 ret = write(pipe_out[1], &c, 1);
2855 d_fprintf(stderr, "failed to send exit signal to child. %s\n",
2860 /* Wait 20 seconds for the lock. */
2862 CatchSignal(SIGALRM, alarm_handler_parent);
2865 start = timeval_current();
2867 status = cli_lock32(cli1, fnum, 0, 4, timeout, WRITE_LOCK);
2868 if (!NT_STATUS_IS_OK(status)) {
2869 d_fprintf(stderr, "Unable to apply write lock on range 0:4, error was "
2870 "%s\n", nt_errstr(status));
2875 seconds = timeval_elapsed(&start);
2877 printf("Parent got the lock after %.2f seconds.\n",
2880 status = cli_close(cli1, fnum);
2881 if (!NT_STATUS_IS_OK(status)) {
2882 d_fprintf(stderr, "cli_close(fnum1) %s\n", nt_errstr(status));
2889 cli_close(cli1, fnum);
2890 torture_close_connection(cli1);
2894 printf("finished locktest9X: %s\n", fname);
2898 static bool run_locktest9a(int dummy)
2900 return _run_locktest9X("lock9a.dat", -1);
2903 static bool run_locktest9b(int dummy)
2905 return _run_locktest9X("lock9b.dat", 10000);
2908 struct locktest10_state {
2913 static void locktest10_lockingx_done(struct tevent_req *subreq);
2914 static void locktest10_read_andx_done(struct tevent_req *subreq);
2916 static bool run_locktest10(int dummy)
2918 struct tevent_context *ev = NULL;
2919 struct cli_state *cli1 = NULL;
2920 struct cli_state *cli2 = NULL;
2921 struct smb1_lock_element lck = { 0 };
2922 struct tevent_req *reqs[2] = { NULL };
2923 struct tevent_req *smbreqs[2] = { NULL };
2924 const char fname[] = "\\lockt10.lck";
2925 uint16_t fnum1, fnum2;
2929 struct locktest10_state state = { .ok = true };
2932 printf("starting locktest10\n");
2934 ev = samba_tevent_context_init(NULL);
2936 d_fprintf(stderr, "samba_tevent_context_init failed\n");
2940 ok = torture_open_connection(&cli1, 0);
2944 smbXcli_conn_set_sockopt(cli1->conn, sockops);
2946 ok = torture_open_connection(&cli2, 1);
2950 smbXcli_conn_set_sockopt(cli2->conn, sockops);
2952 status = cli_openx(cli1, fname, O_CREAT|O_RDWR, DENY_NONE, &fnum1);
2953 if (!NT_STATUS_IS_OK(status)) {
2955 "cli_openx failed: %s\n",
2960 status = cli_writeall(cli1, fnum1, 0, &data, 0, sizeof(data), NULL);
2961 if (!NT_STATUS_IS_OK(status)) {
2963 "cli_writeall failed: %s\n",
2968 status = cli_openx(cli2, fname, O_CREAT|O_RDWR, DENY_NONE, &fnum2);
2969 if (!NT_STATUS_IS_OK(status)) {
2971 "cli_openx failed: %s\n",
2976 status = cli_locktype(
2977 cli2, fnum2, 0, 1, 0, LOCKING_ANDX_EXCLUSIVE_LOCK);
2978 if (!NT_STATUS_IS_OK(status)) {
2980 "cli_locktype failed: %s\n",
2985 lck = (struct smb1_lock_element) {
2986 .pid = cli_getpid(cli1), .offset = 0, .length = 1,
2989 reqs[0] = cli_lockingx_create(
2991 ev, /* tevent_context */
2994 LOCKING_ANDX_EXCLUSIVE_LOCK, /* typeoflock */
2995 0, /* newoplocklevel */
2997 0, /* num_unlocks */
3001 &smbreqs[0]); /* psmbreq */
3002 if (reqs[0] == NULL) {
3003 d_fprintf(stderr, "cli_lockingx_create failed\n");
3006 tevent_req_set_callback(reqs[0], locktest10_lockingx_done, &state);
3008 reqs[1] = cli_read_andx_create(
3015 &smbreqs[1]); /* psmbreq */
3016 if (reqs[1] == NULL) {
3017 d_fprintf(stderr, "cli_read_andx_create failed\n");
3020 tevent_req_set_callback(reqs[1], locktest10_read_andx_done, &state);
3022 status = smb1cli_req_chain_submit(smbreqs, ARRAY_SIZE(smbreqs));
3023 if (!NT_STATUS_IS_OK(status)) {
3025 "smb1cli_req_chain_submit failed: %s\n",
3030 while (!state.done) {
3031 tevent_loop_once(ev);
3034 torture_close_connection(cli1);
3043 static void locktest10_lockingx_done(struct tevent_req *subreq)
3045 struct locktest10_state *state = tevent_req_callback_data_void(subreq);
3048 status = cli_lockingx_recv(subreq);
3049 TALLOC_FREE(subreq);
3051 if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
3052 d_printf("cli_lockingx returned %s\n", nt_errstr(status));
3057 static void locktest10_read_andx_done(struct tevent_req *subreq)
3059 struct locktest10_state *state = tevent_req_callback_data_void(subreq);
3060 ssize_t received = -1;
3061 uint8_t *rcvbuf = NULL;
3064 status = cli_read_andx_recv(subreq, &received, &rcvbuf);
3066 if (!NT_STATUS_EQUAL(status, NT_STATUS_REQUEST_ABORTED)) {
3067 d_printf("cli_read_andx returned %s\n", nt_errstr(status));
3072 TALLOC_FREE(subreq);
3075 static bool run_locktest11(int dummy)
3077 struct cli_state *cli1;
3078 const char *fname = "\\lockt11.lck";
3083 if (!torture_open_connection(&cli1, 0)) {
3087 smbXcli_conn_set_sockopt(cli1->conn, sockops);
3089 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3091 status = cli_openx(cli1, fname, O_CREAT|O_RDWR, DENY_NONE, &fnum);
3092 if (!NT_STATUS_IS_OK(status)) {
3094 "cli_openx returned %s\n",
3100 * Test that LOCKING_ANDX_CANCEL_LOCK without any locks
3101 * returns NT_STATUS_OK
3104 status = cli_lockingx(
3107 LOCKING_ANDX_CANCEL_LOCK, /* typeoflock */
3108 0, /* newoplocklevel */
3110 0, /* num_unlocks */
3115 if (!NT_STATUS_IS_OK(status)) {
3116 d_printf("cli_lockingX returned %s\n", nt_errstr(status));
3122 cli_close(cli1, fnum);
3123 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3128 struct deferred_close_state {
3129 struct tevent_context *ev;
3130 struct cli_state *cli;
3134 static void deferred_close_waited(struct tevent_req *subreq);
3135 static void deferred_close_done(struct tevent_req *subreq);
3137 static struct tevent_req *deferred_close_send(
3138 TALLOC_CTX *mem_ctx,
3139 struct tevent_context *ev,
3141 struct cli_state *cli,
3144 struct tevent_req *req = NULL, *subreq = NULL;
3145 struct deferred_close_state *state = NULL;
3146 struct timeval wakeup_time = timeval_current_ofs(wait_secs, 0);
3148 req = tevent_req_create(
3149 mem_ctx, &state, struct deferred_close_state);
3157 subreq = tevent_wakeup_send(state, state->ev, wakeup_time);
3158 if (tevent_req_nomem(subreq, req)) {
3159 return tevent_req_post(req, ev);
3161 tevent_req_set_callback(subreq, deferred_close_waited, req);
3165 static void deferred_close_waited(struct tevent_req *subreq)
3167 struct tevent_req *req = tevent_req_callback_data(
3168 subreq, struct tevent_req);
3169 struct deferred_close_state *state = tevent_req_data(
3170 req, struct deferred_close_state);
3173 ok = tevent_wakeup_recv(subreq);
3174 TALLOC_FREE(subreq);
3176 tevent_req_oom(req);
3180 subreq = cli_close_send(state, state->ev, state->cli, state->fnum, 0);
3181 if (tevent_req_nomem(subreq, req)) {
3184 tevent_req_set_callback(subreq, deferred_close_done, req);
3187 static void deferred_close_done(struct tevent_req *subreq)
3189 NTSTATUS status = cli_close_recv(subreq);
3190 tevent_req_simple_finish_ntstatus(subreq, status);
3193 static NTSTATUS deferred_close_recv(struct tevent_req *req)
3195 return tevent_req_simple_recv_ntstatus(req);
3198 struct lockread_state {
3199 struct smb1_lock_element lck;
3200 struct tevent_req *reqs[2];
3201 struct tevent_req *smbreqs[2];
3202 NTSTATUS lock_status;
3203 NTSTATUS read_status;
3207 static void lockread_lockingx_done(struct tevent_req *subreq);
3208 static void lockread_read_andx_done(struct tevent_req *subreq);
3210 static struct tevent_req *lockread_send(
3211 TALLOC_CTX *mem_ctx,
3212 struct tevent_context *ev,
3213 struct cli_state *cli,
3216 struct tevent_req *req = NULL;
3217 struct lockread_state *state = NULL;
3220 req = tevent_req_create(mem_ctx, &state, struct lockread_state);
3225 state->lck = (struct smb1_lock_element) {
3226 .pid = cli_getpid(cli), .offset = 0, .length = 1,
3229 state->reqs[0] = cli_lockingx_create(
3231 ev, /* tevent_context */
3234 LOCKING_ANDX_EXCLUSIVE_LOCK, /* typeoflock */
3235 0, /* newoplocklevel */
3236 10000, /* timeout */
3237 0, /* num_unlocks */
3240 &state->lck, /* locks */
3241 &state->smbreqs[0]); /* psmbreq */
3242 if (tevent_req_nomem(state->reqs[0], req)) {
3243 return tevent_req_post(req, ev);
3245 tevent_req_set_callback(
3246 state->reqs[0], lockread_lockingx_done, req);
3248 state->reqs[1] = cli_read_andx_create(
3255 &state->smbreqs[1]); /* psmbreq */
3256 if (tevent_req_nomem(state->reqs[1], req)) {
3257 return tevent_req_post(req, ev);
3259 tevent_req_set_callback(
3260 state->reqs[1], lockread_read_andx_done, req);
3262 status = smb1cli_req_chain_submit(state->smbreqs, 2);
3263 if (tevent_req_nterror(req, status)) {
3264 return tevent_req_post(req, ev);
3269 static void lockread_lockingx_done(struct tevent_req *subreq)
3271 struct tevent_req *req = tevent_req_callback_data(
3272 subreq, struct tevent_req);
3273 struct lockread_state *state = tevent_req_data(
3274 req, struct lockread_state);
3275 state->lock_status = cli_lockingx_recv(subreq);
3276 TALLOC_FREE(subreq);
3278 "lockingx returned %s\n",
3279 nt_errstr(state->lock_status));
3282 static void lockread_read_andx_done(struct tevent_req *subreq)
3284 struct tevent_req *req = tevent_req_callback_data(
3285 subreq, struct tevent_req);
3286 struct lockread_state *state = tevent_req_data(
3287 req, struct lockread_state);
3288 ssize_t received = -1;
3289 uint8_t *rcvbuf = NULL;
3291 state->read_status = cli_read_andx_recv(subreq, &received, &rcvbuf);
3294 "read returned %s\n",
3295 nt_errstr(state->read_status));
3297 if (!NT_STATUS_IS_OK(state->read_status)) {
3298 TALLOC_FREE(subreq);
3299 tevent_req_done(req);
3304 state->readbuf = talloc_memdup(state, rcvbuf, received);
3305 TALLOC_FREE(subreq);
3306 if (tevent_req_nomem(state->readbuf, req)) {
3310 TALLOC_FREE(subreq);
3311 tevent_req_done(req);
3314 static NTSTATUS lockread_recv(
3315 struct tevent_req *req,
3316 NTSTATUS *lock_status,
3317 NTSTATUS *read_status,
3318 TALLOC_CTX *mem_ctx,
3321 struct lockread_state *state = tevent_req_data(
3322 req, struct lockread_state);
3325 if (tevent_req_is_nterror(req, &status)) {
3329 *lock_status = state->lock_status;
3330 *read_status = state->read_status;
3331 if (state->readbuf != NULL) {
3332 *read_buf = talloc_move(mem_ctx, &state->readbuf);
3337 return NT_STATUS_OK;
3340 struct lock12_state {
3344 static void lock12_closed(struct tevent_req *subreq);
3345 static void lock12_read(struct tevent_req *subreq);
3347 static struct tevent_req *lock12_send(
3348 TALLOC_CTX *mem_ctx,
3349 struct tevent_context *ev,
3350 struct cli_state *cli,
3354 struct tevent_req *req = NULL, *subreq = NULL;
3355 struct lock12_state *state = NULL;
3357 req = tevent_req_create(mem_ctx, &state, struct lock12_state);
3362 subreq = deferred_close_send(state, ev, 1, cli, fnum1);
3363 if (tevent_req_nomem(subreq, req)) {
3364 return tevent_req_post(req, ev);
3366 tevent_req_set_callback(subreq, lock12_closed, req);
3368 subreq = lockread_send(state, ev, cli, fnum2);
3369 if (tevent_req_nomem(subreq, req)) {
3370 return tevent_req_post(req, ev);
3372 tevent_req_set_callback(subreq, lock12_read, req);
3377 static void lock12_closed(struct tevent_req *subreq)
3379 struct tevent_req *req = tevent_req_callback_data(
3380 subreq, struct tevent_req);
3383 status = deferred_close_recv(subreq);
3384 TALLOC_FREE(subreq);
3385 DBG_DEBUG("close returned %s\n", nt_errstr(status));
3386 if (tevent_req_nterror(req, status)) {
3391 static void lock12_read(struct tevent_req *subreq)
3393 struct tevent_req *req = tevent_req_callback_data(
3394 subreq, struct tevent_req);
3395 struct lock12_state *state = tevent_req_data(
3396 req, struct lock12_state);
3397 NTSTATUS status, lock_status, read_status;
3398 uint8_t *buf = NULL;
3400 status = lockread_recv(
3401 subreq, &lock_status, &read_status, state, &buf);
3402 TALLOC_FREE(subreq);
3403 if (tevent_req_nterror(req, status) ||
3404 tevent_req_nterror(req, lock_status) ||
3405 tevent_req_nterror(req, read_status)) {
3408 tevent_req_done(req);
3411 static NTSTATUS lock12_recv(struct tevent_req *req)
3416 if (tevent_req_is_nterror(req, &status)) {
3419 return NT_STATUS_OK;
3422 static bool run_locktest12(int dummy)
3424 struct tevent_context *ev = NULL;
3425 struct tevent_req *req = NULL;
3426 struct cli_state *cli = NULL;
3427 const char fname[] = "\\lockt12.lck";
3428 uint16_t fnum1, fnum2;
3434 printf("starting locktest12\n");
3436 ev = samba_tevent_context_init(NULL);
3438 d_fprintf(stderr, "samba_tevent_context_init failed\n");
3442 ok = torture_open_connection(&cli, 0);
3446 smbXcli_conn_set_sockopt(cli->conn, sockops);
3448 status = cli_openx(cli, fname, O_CREAT|O_RDWR, DENY_NONE, &fnum1);
3449 if (!NT_STATUS_IS_OK(status)) {
3451 "cli_openx failed: %s\n",
3456 status = cli_openx(cli, fname, O_CREAT|O_RDWR, DENY_NONE, &fnum2);
3457 if (!NT_STATUS_IS_OK(status)) {
3459 "cli_openx failed: %s\n",
3464 status = cli_writeall(cli, fnum1, 0, &data, 0, sizeof(data), NULL);
3465 if (!NT_STATUS_IS_OK(status)) {
3467 "cli_writeall failed: %s\n",
3472 status = cli_locktype(
3473 cli, fnum1, 0, 1, 0, LOCKING_ANDX_EXCLUSIVE_LOCK);
3474 if (!NT_STATUS_IS_OK(status)) {
3476 "cli_locktype failed: %s\n",
3481 req = lock12_send(ev, ev, cli, fnum1, fnum2);
3483 d_fprintf(stderr, "lock12_send failed\n");
3487 ok = tevent_req_poll_ntstatus(req, ev, &status);
3489 d_fprintf(stderr, "tevent_req_poll_ntstatus failed\n");
3493 if (!NT_STATUS_IS_OK(status)) {
3495 "tevent_req_poll_ntstatus returned %s\n",
3500 status = lock12_recv(req);
3501 if (!NT_STATUS_IS_OK(status)) {
3502 d_fprintf(stderr, "lock12 returned %s\n", nt_errstr(status));
3509 torture_close_connection(cli);
3514 struct lock_ntcancel_state {
3515 struct timeval start;
3516 struct smb1_lock_element lck;
3517 struct tevent_req *subreq;
3520 static void lock_ntcancel_waited(struct tevent_req *subreq);
3521 static void lock_ntcancel_done(struct tevent_req *subreq);
3523 static struct tevent_req *lock_ntcancel_send(
3524 TALLOC_CTX *mem_ctx,
3525 struct tevent_context *ev,
3526 struct cli_state *cli,
3529 struct tevent_req *req = NULL, *subreq = NULL;
3530 struct lock_ntcancel_state *state = NULL;
3532 req = tevent_req_create(mem_ctx, &state, struct lock_ntcancel_state);
3536 state->lck = (struct smb1_lock_element) {
3537 .pid = cli_getpid(cli), .offset = 0, .length = 1,
3539 state->start = timeval_current();
3541 state->subreq = cli_lockingx_send(
3542 state, /* mem_ctx */
3543 ev, /* tevent_context */
3546 LOCKING_ANDX_EXCLUSIVE_LOCK, /* typeoflock */
3547 0, /* newoplocklevel */
3548 10000, /* timeout */
3549 0, /* num_unlocks */
3552 &state->lck); /* locks */
3553 if (tevent_req_nomem(state->subreq, req)) {
3554 return tevent_req_post(req, ev);
3556 tevent_req_set_callback(state->subreq, lock_ntcancel_done, req);
3558 subreq = tevent_wakeup_send(state, ev, timeval_current_ofs(1, 0));
3559 if (tevent_req_nomem(subreq, req)) {
3560 return tevent_req_post(req, ev);
3562 tevent_req_set_callback(subreq, lock_ntcancel_waited, req);
3566 static void lock_ntcancel_waited(struct tevent_req *subreq)
3568 struct tevent_req *req = tevent_req_callback_data(
3569 subreq, struct tevent_req);
3570 struct lock_ntcancel_state *state = tevent_req_data(
3571 req, struct lock_ntcancel_state);
3574 ok = tevent_wakeup_recv(subreq);
3575 TALLOC_FREE(subreq);
3577 tevent_req_oom(req);
3581 ok = tevent_req_cancel(state->subreq);
3583 d_fprintf(stderr, "Could not cancel subreq\n");
3584 tevent_req_oom(req);
3589 static void lock_ntcancel_done(struct tevent_req *subreq)
3591 struct tevent_req *req = tevent_req_callback_data(
3592 subreq, struct tevent_req);
3593 struct lock_ntcancel_state *state = tevent_req_data(
3594 req, struct lock_ntcancel_state);
3598 status = cli_lockingx_recv(subreq);
3599 TALLOC_FREE(subreq);
3601 if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
3602 d_printf("cli_lockingx returned %s\n", nt_errstr(status));
3603 tevent_req_nterror(req, NT_STATUS_UNSUCCESSFUL);
3607 elapsed = timeval_elapsed(&state->start);
3610 d_printf("cli_lockingx was too slow, cancel did not work\n");
3611 tevent_req_nterror(req, NT_STATUS_UNSUCCESSFUL);
3615 tevent_req_done(req);
3618 static NTSTATUS lock_ntcancel_recv(struct tevent_req *req)
3620 return tevent_req_simple_recv_ntstatus(req);
3623 static bool run_locktest13(int dummy)
3625 struct tevent_context *ev = NULL;
3626 struct tevent_req *req = NULL;
3627 struct cli_state *cli = NULL;
3628 const char fname[] = "\\lockt13.lck";
3629 uint16_t fnum1, fnum2;
3635 printf("starting locktest13\n");
3637 ev = samba_tevent_context_init(NULL);
3639 d_fprintf(stderr, "samba_tevent_context_init failed\n");
3643 ok = torture_open_connection(&cli, 0);
3647 smbXcli_conn_set_sockopt(cli->conn, sockops);
3649 status = cli_openx(cli, fname, O_CREAT|O_RDWR, DENY_NONE, &fnum1);
3650 if (!NT_STATUS_IS_OK(status)) {
3652 "cli_openx failed: %s\n",
3657 status = cli_openx(cli, fname, O_CREAT|O_RDWR, DENY_NONE, &fnum2);
3658 if (!NT_STATUS_IS_OK(status)) {
3660 "cli_openx failed: %s\n",
3665 status = cli_writeall(cli, fnum1, 0, &data, 0, sizeof(data), NULL);
3666 if (!NT_STATUS_IS_OK(status)) {
3668 "cli_writeall failed: %s\n",
3673 status = cli_locktype(
3674 cli, fnum1, 0, 1, 0, LOCKING_ANDX_EXCLUSIVE_LOCK);
3675 if (!NT_STATUS_IS_OK(status)) {
3677 "cli_locktype failed: %s\n",
3682 req = lock_ntcancel_send(ev, ev, cli, fnum2);
3684 d_fprintf(stderr, "lock_ntcancel_send failed\n");
3688 ok = tevent_req_poll_ntstatus(req, ev, &status);
3690 d_fprintf(stderr, "tevent_req_poll_ntstatus failed\n");
3694 if (!NT_STATUS_IS_OK(status)) {
3696 "tevent_req_poll_ntstatus returned %s\n",
3701 status = lock_ntcancel_recv(req);
3702 if (!NT_STATUS_IS_OK(status)) {
3704 "lock_ntcancel returned %s\n",
3712 torture_close_connection(cli);
3718 test whether fnums and tids open on one VC are available on another (a major
3721 static bool run_fdpasstest(int dummy)
3723 struct cli_state *cli1, *cli2;
3724 const char *fname = "\\fdpass.tst";
3729 if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
3732 smbXcli_conn_set_sockopt(cli1->conn, sockops);
3733 smbXcli_conn_set_sockopt(cli2->conn, sockops);
3735 printf("starting fdpasstest\n");
3737 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3739 status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
3741 if (!NT_STATUS_IS_OK(status)) {
3742 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
3746 status = cli_writeall(cli1, fnum1, 0, (const uint8_t *)"hello world\n", 0,
3748 if (!NT_STATUS_IS_OK(status)) {
3749 printf("write failed (%s)\n", nt_errstr(status));
3753 cli_state_set_uid(cli2, cli_state_get_uid(cli1));
3754 cli_state_set_tid(cli2, cli_state_get_tid(cli1));
3755 cli_setpid(cli2, cli_getpid(cli1));
3757 if (test_cli_read(cli2, fnum1, buf, 0, 13, NULL, 13)) {
3758 printf("read succeeded! nasty security hole [%s]\n", buf);
3762 cli_close(cli1, fnum1);
3763 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3765 torture_close_connection(cli1);
3766 torture_close_connection(cli2);
3768 printf("finished fdpasstest\n");
3772 static bool run_fdsesstest(int dummy)
3774 struct cli_state *cli;
3776 uint16_t saved_vuid;
3778 uint32_t saved_cnum;
3779 const char *fname = "\\fdsess.tst";
3780 const char *fname1 = "\\fdsess1.tst";
3787 if (!torture_open_connection(&cli, 0))
3789 smbXcli_conn_set_sockopt(cli->conn, sockops);
3791 if (!torture_cli_session_setup2(cli, &new_vuid))
3794 saved_cnum = cli_state_get_tid(cli);
3795 if (!NT_STATUS_IS_OK(cli_tree_connect(cli, share, "?????", NULL)))
3797 new_cnum = cli_state_get_tid(cli);
3798 cli_state_set_tid(cli, saved_cnum);
3800 printf("starting fdsesstest\n");
3802 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3803 cli_unlink(cli, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3805 status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
3806 if (!NT_STATUS_IS_OK(status)) {
3807 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
3811 status = cli_writeall(cli, fnum1, 0, (const uint8_t *)"hello world\n", 0, 13,
3813 if (!NT_STATUS_IS_OK(status)) {
3814 printf("write failed (%s)\n", nt_errstr(status));
3818 saved_vuid = cli_state_get_uid(cli);
3819 cli_state_set_uid(cli, new_vuid);
3821 if (test_cli_read(cli, fnum1, buf, 0, 13, NULL, 13)) {
3822 printf("read succeeded with different vuid! "
3823 "nasty security hole [%s]\n", buf);
3826 /* Try to open a file with different vuid, samba cnum. */
3827 if (NT_STATUS_IS_OK(cli_openx(cli, fname1, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum2))) {
3828 printf("create with different vuid, same cnum succeeded.\n");
3829 cli_close(cli, fnum2);
3830 cli_unlink(cli, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3832 printf("create with different vuid, same cnum failed.\n");
3833 printf("This will cause problems with service clients.\n");
3837 cli_state_set_uid(cli, saved_vuid);
3839 /* Try with same vuid, different cnum. */
3840 cli_state_set_tid(cli, new_cnum);
3842 if (test_cli_read(cli, fnum1, buf, 0, 13, NULL, 13)) {
3843 printf("read succeeded with different cnum![%s]\n", buf);
3847 cli_state_set_tid(cli, saved_cnum);
3848 cli_close(cli, fnum1);
3849 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3851 torture_close_connection(cli);
3853 printf("finished fdsesstest\n");
3858 This test checks that
3860 1) the server does not allow an unlink on a file that is open
3862 static bool run_unlinktest(int dummy)
3864 struct cli_state *cli;
3865 const char *fname = "\\unlink.tst";
3867 bool correct = True;
3870 if (!torture_open_connection(&cli, 0)) {
3874 smbXcli_conn_set_sockopt(cli->conn, sockops);
3876 printf("starting unlink test\n");
3878 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3882 status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
3883 if (!NT_STATUS_IS_OK(status)) {
3884 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
3888 status = cli_unlink(cli, fname,
3889 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3890 if (NT_STATUS_IS_OK(status)) {
3891 printf("error: server allowed unlink on an open file\n");
3894 correct = check_error(__LINE__, status, ERRDOS, ERRbadshare,
3895 NT_STATUS_SHARING_VIOLATION);
3898 cli_close(cli, fnum);
3899 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3901 if (!torture_close_connection(cli)) {
3905 printf("unlink test finished\n");
3912 test how many open files this server supports on the one socket
3914 static bool run_maxfidtest(int dummy)
3916 struct cli_state *cli;
3918 uint16_t fnums[0x11000];
3921 bool correct = True;
3927 printf("failed to connect\n");
3931 smbXcli_conn_set_sockopt(cli->conn, sockops);
3933 for (i=0; i<0x11000; i++) {
3934 slprintf(fname,sizeof(fname)-1,"\\maxfid.%d.%d", i,(int)getpid());
3935 status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_TRUNC, DENY_NONE,
3937 if (!NT_STATUS_IS_OK(status)) {
3938 printf("open of %s failed (%s)\n",
3939 fname, nt_errstr(status));
3940 printf("maximum fnum is %d\n", i);
3948 printf("cleaning up\n");
3950 slprintf(fname,sizeof(fname)-1,"\\maxfid.%d.%d", i,(int)getpid());
3951 cli_close(cli, fnums[i]);
3953 status = cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3954 if (!NT_STATUS_IS_OK(status)) {
3955 printf("unlink of %s failed (%s)\n",
3956 fname, nt_errstr(status));
3963 printf("maxfid test finished\n");
3964 if (!torture_close_connection(cli)) {
3970 /* generate a random buffer */
3971 static void rand_buf(char *buf, int len)
3974 *buf = (char)sys_random();
3979 /* send smb negprot commands, not reading the response */
3980 static bool run_negprot_nowait(int dummy)
3982 struct tevent_context *ev;
3984 struct cli_state *cli;
3985 bool correct = True;
3987 printf("starting negprot nowait test\n");
3989 ev = samba_tevent_context_init(talloc_tos());
3994 if (!(cli = open_nbt_connection())) {
3999 for (i=0;i<50000;i++) {
4000 struct tevent_req *req;
4002 req = smbXcli_negprot_send(
4015 if (!tevent_req_poll(req, ev)) {
4016 d_fprintf(stderr, "tevent_req_poll failed: %s\n",
4024 if (torture_close_connection(cli)) {
4028 printf("finished negprot nowait test\n");
4033 /* send smb negprot commands, not reading the response */
4034 static bool run_bad_nbt_session(int dummy)
4036 struct nmb_name called, calling;
4037 struct sockaddr_storage ss;
4042 printf("starting bad nbt session test\n");
4044 make_nmb_name(&calling, myname, 0x0);
4045 make_nmb_name(&called , host, 0x20);
4047 if (!resolve_name(host, &ss, 0x20, true)) {
4048 d_fprintf(stderr, "Could not resolve name %s\n", host);
4052 status = open_socket_out(&ss, NBT_SMB_PORT, 10000, &fd);
4053 if (!NT_STATUS_IS_OK(status)) {
4054 d_fprintf(stderr, "open_socket_out failed: %s\n",
4059 ret = cli_bad_session_request(fd, &calling, &called);
4062 d_fprintf(stderr, "open_socket_out failed: %s\n",
4067 printf("finished bad nbt session test\n");
4071 /* send random IPC commands */
4072 static bool run_randomipc(int dummy)
4074 char *rparam = NULL;
4076 unsigned int rdrcnt,rprcnt;
4078 int api, param_len, i;
4079 struct cli_state *cli;
4080 bool correct = True;
4083 printf("starting random ipc test\n");
4085 if (!torture_open_connection(&cli, 0)) {
4089 for (i=0;i<count;i++) {
4090 api = sys_random() % 500;
4091 param_len = (sys_random() % 64);
4093 rand_buf(param, param_len);
4098 param, param_len, 8,
4099 NULL, 0, CLI_BUFFER_SIZE,
4103 printf("%d/%d\r", i,count);
4106 printf("%d/%d\n", i, count);
4108 if (!torture_close_connection(cli)) {
4115 printf("finished random ipc test\n");
4122 static void browse_callback(const char *sname, uint32_t stype,
4123 const char *comment, void *state)
4125 printf("\t%20.20s %08x %s\n", sname, stype, comment);
4131 This test checks the browse list code
4134 static bool run_browsetest(int dummy)
4136 static struct cli_state *cli;
4137 bool correct = True;
4139 printf("starting browse test\n");
4141 if (!torture_open_connection(&cli, 0)) {
4145 printf("domain list:\n");
4146 cli_NetServerEnum(cli, cli->server_domain,
4147 SV_TYPE_DOMAIN_ENUM,
4148 browse_callback, NULL);
4150 printf("machine list:\n");
4151 cli_NetServerEnum(cli, cli->server_domain,
4153 browse_callback, NULL);
4155 if (!torture_close_connection(cli)) {
4159 printf("browse test finished\n");
4165 static bool check_attributes(struct cli_state *cli,
4167 uint32_t expected_attrs)
4170 NTSTATUS status = cli_getatr(cli,
4175 if (!NT_STATUS_IS_OK(status)) {
4176 printf("cli_getatr failed with %s\n",
4180 if (attrs != expected_attrs) {
4181 printf("Attributes incorrect 0x%x, should be 0x%x\n",
4182 (unsigned int)attrs,
4183 (unsigned int)expected_attrs);
4190 This checks how the getatr calls works
4192 static bool run_attrtest(int dummy)
4194 struct cli_state *cli;
4197 const char *fname = "\\attrib123456789.tst";
4198 bool correct = True;
4201 printf("starting attrib test\n");
4203 if (!torture_open_connection(&cli, 0)) {
4207 /* Ensure we can't unlink with out-of-range (unknown) attribute. */
4208 status = cli_unlink(cli, fname, 0x20000);
4209 if (!NT_STATUS_EQUAL(status, NT_STATUS_INVALID_PARAMETER)) {
4214 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4215 cli_openx(cli, fname,
4216 O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum);
4217 cli_close(cli, fnum);
4219 status = cli_getatr(cli, fname, NULL, NULL, &t);
4220 if (!NT_STATUS_IS_OK(status)) {
4221 printf("getatr failed (%s)\n", nt_errstr(status));
4225 if (labs(t - time(NULL)) > 60*60*24*10) {
4226 printf("ERROR: SMBgetatr bug. time is %s",
4232 t2 = t-60*60*24; /* 1 day ago */
4234 /* Ensure we can't set with out-of-range (unknown) attribute. */
4235 status = cli_setatr(cli, fname, 0x20000, t2);
4236 if (!NT_STATUS_EQUAL(status, NT_STATUS_INVALID_PARAMETER)) {
4241 status = cli_setatr(cli, fname, 0, t2);
4242 if (!NT_STATUS_IS_OK(status)) {
4243 printf("setatr failed (%s)\n", nt_errstr(status));
4247 status = cli_getatr(cli, fname, NULL, NULL, &t);
4248 if (!NT_STATUS_IS_OK(status)) {
4249 printf("getatr failed (%s)\n", nt_errstr(status));
4254 printf("ERROR: getatr/setatr bug. times are\n%s",
4256 printf("%s", ctime(&t2));
4260 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4262 /* Check cli_setpathinfo_ext() */
4263 /* Re-create the file. */
4264 status = cli_openx(cli, fname,
4265 O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum);
4266 if (!NT_STATUS_IS_OK(status)) {
4267 printf("Failed to recreate %s (%s)\n",
4268 fname, nt_errstr(status));
4271 cli_close(cli, fnum);
4273 status = cli_setpathinfo_ext(
4276 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* create */
4277 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* access */
4278 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* write */
4279 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* change */
4280 FILE_ATTRIBUTE_SYSTEM |
4281 FILE_ATTRIBUTE_HIDDEN |
4282 FILE_ATTRIBUTE_READONLY);
4283 if (!NT_STATUS_IS_OK(status)) {
4284 printf("cli_setpathinfo_ext failed with %s\n",
4289 /* Check attributes are correct. */
4290 correct = check_attributes(cli,
4292 FILE_ATTRIBUTE_SYSTEM |
4293 FILE_ATTRIBUTE_HIDDEN |
4294 FILE_ATTRIBUTE_READONLY);
4295 if (correct == false) {
4299 /* Setting to FILE_ATTRIBUTE_NORMAL should be ignored. */
4300 status = cli_setpathinfo_ext(
4303 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* create */
4304 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* access */
4305 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* write */
4306 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* change */
4307 FILE_ATTRIBUTE_NORMAL);
4308 if (!NT_STATUS_IS_OK(status)) {
4309 printf("cli_setpathinfo_ext failed with %s\n",
4314 /* Check attributes are correct. */
4315 correct = check_attributes(cli,
4317 FILE_ATTRIBUTE_SYSTEM |
4318 FILE_ATTRIBUTE_HIDDEN |
4319 FILE_ATTRIBUTE_READONLY);
4320 if (correct == false) {
4324 /* Setting to (uint16_t)-1 should also be ignored. */
4325 status = cli_setpathinfo_ext(
4328 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* create */
4329 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* access */
4330 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* write */
4331 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* change */
4333 if (!NT_STATUS_IS_OK(status)) {
4334 printf("cli_setpathinfo_ext failed with %s\n",
4339 /* Check attributes are correct. */
4340 correct = check_attributes(cli,
4342 FILE_ATTRIBUTE_SYSTEM |
4343 FILE_ATTRIBUTE_HIDDEN |
4344 FILE_ATTRIBUTE_READONLY);
4345 if (correct == false) {
4349 /* Setting to 0 should clear them all. */
4350 status = cli_setpathinfo_ext(
4353 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* create */
4354 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* access */
4355 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* write */
4356 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* change */
4358 if (!NT_STATUS_IS_OK(status)) {
4359 printf("cli_setpathinfo_ext failed with %s\n",
4364 /* Check attributes are correct. */
4365 correct = check_attributes(cli,
4367 FILE_ATTRIBUTE_NORMAL);
4368 if (correct == false) {
4376 FILE_ATTRIBUTE_SYSTEM |
4377 FILE_ATTRIBUTE_HIDDEN|
4378 FILE_ATTRIBUTE_READONLY);
4380 if (!torture_close_connection(cli)) {
4384 printf("attrib test finished\n");
4389 static NTSTATUS cli_qfilename(
4390 struct cli_state *cli,
4392 TALLOC_CTX *mem_ctx,
4395 uint16_t recv_flags2;
4402 status = cli_qfileinfo(talloc_tos(), cli, fnum,
4403 SMB_QUERY_FILE_NAME_INFO,
4404 4, CLI_BUFFER_SIZE, &recv_flags2,
4405 &rdata, &num_rdata);
4406 if (!NT_STATUS_IS_OK(status)) {
4410 namelen = IVAL(rdata, 0);
4411 if (namelen > (num_rdata - 4)) {
4413 return NT_STATUS_INVALID_NETWORK_RESPONSE;
4416 pull_string_talloc(mem_ctx,
4417 (const char *)rdata,
4424 status = map_nt_error_from_unix(errno);
4431 return NT_STATUS_OK;
4435 This checks a couple of trans2 calls
4437 static bool run_trans2test(int dummy)
4439 struct cli_state *cli;
4442 time_t c_time, a_time, m_time;
4443 struct timespec c_time_ts, a_time_ts, m_time_ts, w_time_ts, m_time2_ts;
4444 const char *fname = "\\trans2.tst";
4445 const char *dname = "\\trans2";
4446 const char *fname2 = "\\trans2\\trans2.tst";
4448 bool correct = True;
4453 printf("starting trans2 test\n");
4455 if (!torture_open_connection(&cli, 0)) {
4459 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
4460 /* Ensure ino is zero, SMB2 gets a real one. */
4463 /* Ensure ino is -1, SMB1 never gets a real one. */
4467 status = cli_get_fs_attr_info(cli, &fs_attr);
4468 if (!NT_STATUS_IS_OK(status)) {
4469 printf("ERROR: cli_get_fs_attr_info returned %s\n",
4474 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4475 cli_openx(cli, fname, O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum);
4476 status = cli_qfileinfo_basic(cli, fnum, NULL, &size, &c_time_ts,
4477 &a_time_ts, &w_time_ts, &m_time_ts, NULL);
4478 if (!NT_STATUS_IS_OK(status)) {
4479 printf("ERROR: qfileinfo failed (%s)\n", nt_errstr(status));
4483 status = cli_qfilename(cli, fnum, talloc_tos(), &pname);
4484 if (!NT_STATUS_IS_OK(status)) {
4485 printf("ERROR: qfilename failed (%s)\n", nt_errstr(status));
4488 else if (strcmp(pname, fname)) {
4489 printf("qfilename gave different name? [%s] [%s]\n",
4494 cli_close(cli, fnum);
4498 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4499 status = cli_openx(cli, fname, O_RDWR | O_CREAT | O_TRUNC, DENY_NONE,
4501 if (!NT_STATUS_IS_OK(status)) {
4502 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
4505 cli_close(cli, fnum);
4507 status = cli_qpathinfo1(cli, fname, &c_time, &a_time, &m_time, &size,
4509 if (!NT_STATUS_IS_OK(status)) {
4510 printf("ERROR: qpathinfo failed (%s)\n", nt_errstr(status));
4513 time_t t = time(NULL);
4515 if (c_time != m_time) {
4516 printf("create time=%s", ctime(&c_time));
4517 printf("modify time=%s", ctime(&m_time));
4518 printf("This system appears to have sticky create times\n");
4520 if ((labs(a_time - t) > 60) && (a_time % (60*60) == 0)) {
4521 printf("access time=%s", ctime(&a_time));
4522 printf("This system appears to set a midnight access time\n");
4526 if (labs(m_time - t) > 60*60*24*7) {
4527 printf("ERROR: totally incorrect times - maybe word reversed? mtime=%s", ctime(&m_time));
4533 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4534 cli_openx(cli, fname,
4535 O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum);
4536 cli_close(cli, fnum);
4537 status = cli_qpathinfo2(cli,
4547 if (!NT_STATUS_IS_OK(status)) {
4548 printf("ERROR: qpathinfo2 failed (%s)\n", nt_errstr(status));
4551 if (w_time_ts.tv_sec < 60*60*24*2) {
4552 printf("write time=%s", ctime(&w_time_ts.tv_sec));
4553 printf("This system appears to set a initial 0 write time\n");
4556 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
4557 /* SMB2 should always return an inode. */
4559 printf("SMB2 bad inode (0)\n");
4563 /* SMB1 must always return zero here. */
4565 printf("SMB1 bad inode (!0)\n");
4571 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4574 /* check if the server updates the directory modification time
4575 when creating a new file */
4576 status = cli_mkdir(cli, dname);
4577 if (!NT_STATUS_IS_OK(status)) {
4578 printf("ERROR: mkdir failed (%s)\n", nt_errstr(status));
4582 status = cli_qpathinfo2(cli,
4592 if (!NT_STATUS_IS_OK(status)) {
4593 printf("ERROR: qpathinfo2 failed (%s)\n", nt_errstr(status));
4597 cli_openx(cli, fname2,
4598 O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum);
4599 cli_writeall(cli, fnum, 0, (uint8_t *)&fnum, 0, sizeof(fnum), NULL);
4600 cli_close(cli, fnum);
4601 status = cli_qpathinfo2(cli,
4611 if (!NT_STATUS_IS_OK(status)) {
4612 printf("ERROR: qpathinfo2 failed (%s)\n", nt_errstr(status));
4615 if (memcmp(&m_time_ts, &m_time2_ts, sizeof(struct timespec))
4617 printf("This system does not update directory modification times\n");
4621 cli_unlink(cli, fname2, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4622 cli_rmdir(cli, dname);
4624 if (!torture_close_connection(cli)) {
4628 printf("trans2 test finished\n");
4634 This checks new W2K calls.
4637 static NTSTATUS new_trans(struct cli_state *pcli, int fnum, int level)
4639 uint8_t *buf = NULL;
4643 status = cli_qfileinfo(talloc_tos(), pcli, fnum, level, 0,
4644 CLI_BUFFER_SIZE, NULL, &buf, &len);
4645 if (!NT_STATUS_IS_OK(status)) {
4646 printf("ERROR: qfileinfo (%d) failed (%s)\n", level,
4649 printf("qfileinfo: level %d, len = %u\n", level, len);
4650 dump_data(0, (uint8_t *)buf, len);
4657 static bool run_w2ktest(int dummy)
4659 struct cli_state *cli;
4661 const char *fname = "\\w2ktest\\w2k.tst";
4663 bool correct = True;
4665 printf("starting w2k test\n");
4667 if (!torture_open_connection(&cli, 0)) {
4671 cli_openx(cli, fname,
4672 O_RDWR | O_CREAT , DENY_NONE, &fnum);
4674 for (level = 1004; level < 1040; level++) {
4675 new_trans(cli, fnum, level);
4678 cli_close(cli, fnum);
4680 if (!torture_close_connection(cli)) {
4684 printf("w2k test finished\n");
4691 this is a harness for some oplock tests
4693 static bool run_oplock1(int dummy)
4695 struct cli_state *cli1;
4696 const char *fname = "\\lockt1.lck";
4698 bool correct = True;
4701 printf("starting oplock test 1\n");
4703 if (!torture_open_connection(&cli1, 0)) {
4707 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4709 smbXcli_conn_set_sockopt(cli1->conn, sockops);
4711 cli1->use_oplocks = True;
4713 status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
4715 if (!NT_STATUS_IS_OK(status)) {
4716 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
4720 cli1->use_oplocks = False;
4722 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4723 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4725 status = cli_close(cli1, fnum1);
4726 if (!NT_STATUS_IS_OK(status)) {
4727 printf("close2 failed (%s)\n", nt_errstr(status));
4731 status = cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4732 if (!NT_STATUS_IS_OK(status)) {
4733 printf("unlink failed (%s)\n", nt_errstr(status));
4737 if (!torture_close_connection(cli1)) {
4741 printf("finished oplock test 1\n");
4746 static bool run_oplock2(int dummy)
4748 struct cli_state *cli1, *cli2;
4749 const char *fname = "\\lockt2.lck";
4750 uint16_t fnum1, fnum2;
4751 int saved_use_oplocks = use_oplocks;
4753 bool correct = True;
4754 volatile bool *shared_correct;
4758 shared_correct = (volatile bool *)anonymous_shared_allocate(sizeof(bool));
4759 *shared_correct = True;
4761 use_level_II_oplocks = True;
4764 printf("starting oplock test 2\n");
4766 if (!torture_open_connection(&cli1, 0)) {
4767 use_level_II_oplocks = False;
4768 use_oplocks = saved_use_oplocks;
4772 if (!torture_open_connection(&cli2, 1)) {
4773 use_level_II_oplocks = False;
4774 use_oplocks = saved_use_oplocks;
4778 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4780 smbXcli_conn_set_sockopt(cli1->conn, sockops);
4781 smbXcli_conn_set_sockopt(cli2->conn, sockops);
4783 status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
4785 if (!NT_STATUS_IS_OK(status)) {
4786 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
4790 /* Don't need the globals any more. */
4791 use_level_II_oplocks = False;
4792 use_oplocks = saved_use_oplocks;
4796 status = cli_openx(cli2, fname, O_RDWR, DENY_NONE, &fnum2);
4797 if (!NT_STATUS_IS_OK(status)) {
4798 printf("second open of %s failed (%s)\n", fname, nt_errstr(status));
4799 *shared_correct = False;
4805 status = cli_close(cli2, fnum2);
4806 if (!NT_STATUS_IS_OK(status)) {
4807 printf("close2 failed (%s)\n", nt_errstr(status));
4808 *shared_correct = False;
4816 /* Ensure cli1 processes the break. Empty file should always return 0
4818 status = cli_read(cli1, fnum1, buf, 0, 4, &nread);
4819 if (!NT_STATUS_IS_OK(status)) {
4820 printf("read on fnum1 failed (%s)\n", nt_errstr(status));
4822 } else if (nread != 0) {
4823 printf("read on empty fnum1 failed. recv %ld expected %d\n",
4824 (unsigned long)nread, 0);
4828 /* Should now be at level II. */
4829 /* Test if sending a write locks causes a break to none. */
4830 status = cli_lock32(cli1, fnum1, 0, 4, 0, READ_LOCK);
4831 if (!NT_STATUS_IS_OK(status)) {
4832 printf("lock failed (%s)\n", nt_errstr(status));
4836 cli_unlock(cli1, fnum1, 0, 4);
4840 status = cli_lock32(cli1, fnum1, 0, 4, 0, WRITE_LOCK);
4841 if (!NT_STATUS_IS_OK(status)) {
4842 printf("lock failed (%s)\n", nt_errstr(status));
4846 cli_unlock(cli1, fnum1, 0, 4);
4850 cli_read(cli1, fnum1, buf, 0, 4, NULL);
4852 status = cli_close(cli1, fnum1);
4853 if (!NT_STATUS_IS_OK(status)) {
4854 printf("close1 failed (%s)\n", nt_errstr(status));
4860 status = cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4861 if (!NT_STATUS_IS_OK(status)) {
4862 printf("unlink failed (%s)\n", nt_errstr(status));
4866 if (!torture_close_connection(cli1)) {
4870 if (!*shared_correct) {
4874 printf("finished oplock test 2\n");
4879 struct oplock4_state {
4880 struct tevent_context *ev;
4881 struct cli_state *cli;
4886 static void oplock4_got_break(struct tevent_req *req);
4887 static void oplock4_got_open(struct tevent_req *req);
4889 static bool run_oplock4(int dummy)
4891 struct tevent_context *ev;
4892 struct cli_state *cli1, *cli2;
4893 struct tevent_req *oplock_req, *open_req;
4894 const char *fname = "\\lockt4.lck";
4895 const char *fname_ln = "\\lockt4_ln.lck";
4896 uint16_t fnum1, fnum2;
4897 int saved_use_oplocks = use_oplocks;
4899 bool correct = true;
4903 struct oplock4_state *state;
4905 printf("starting oplock test 4\n");
4907 if (!torture_open_connection(&cli1, 0)) {
4908 use_level_II_oplocks = false;
4909 use_oplocks = saved_use_oplocks;
4913 if (!torture_open_connection(&cli2, 1)) {
4914 use_level_II_oplocks = false;
4915 use_oplocks = saved_use_oplocks;
4919 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4920 cli_unlink(cli1, fname_ln, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4922 smbXcli_conn_set_sockopt(cli1->conn, sockops);
4923 smbXcli_conn_set_sockopt(cli2->conn, sockops);
4925 /* Create the file. */
4926 status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
4928 if (!NT_STATUS_IS_OK(status)) {
4929 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
4933 status = cli_close(cli1, fnum1);
4934 if (!NT_STATUS_IS_OK(status)) {
4935 printf("close1 failed (%s)\n", nt_errstr(status));
4939 /* Now create a hardlink. */
4940 status = cli_hardlink(cli1, fname, fname_ln);
4941 if (!NT_STATUS_IS_OK(status)) {
4942 printf("nt hardlink failed (%s)\n", nt_errstr(status));
4946 /* Prove that opening hardlinks cause deny modes to conflict. */
4947 status = cli_openx(cli1, fname, O_RDWR, DENY_ALL, &fnum1);
4948 if (!NT_STATUS_IS_OK(status)) {
4949 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
4953 status = cli_openx(cli1, fname_ln, O_RDWR, DENY_NONE, &fnum2);
4954 if (NT_STATUS_IS_OK(status)) {
4955 printf("open of %s succeeded - should fail with sharing violation.\n",
4960 if (!NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
4961 printf("open of %s should fail with sharing violation. Got %s\n",
4962 fname_ln, nt_errstr(status));
4966 status = cli_close(cli1, fnum1);
4967 if (!NT_STATUS_IS_OK(status)) {
4968 printf("close1 failed (%s)\n", nt_errstr(status));
4972 cli1->use_oplocks = true;
4973 cli2->use_oplocks = true;
4975 status = cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
4976 if (!NT_STATUS_IS_OK(status)) {
4977 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
4981 ev = samba_tevent_context_init(talloc_tos());
4983 printf("tevent_context_init failed\n");
4987 state = talloc(ev, struct oplock4_state);
4988 if (state == NULL) {
4989 printf("talloc failed\n");
4994 state->got_break = &got_break;
4995 state->fnum2 = &fnum2;
4997 oplock_req = cli_smb_oplock_break_waiter_send(
4998 talloc_tos(), ev, cli1);
4999 if (oplock_req == NULL) {
5000 printf("cli_smb_oplock_break_waiter_send failed\n");
5003 tevent_req_set_callback(oplock_req, oplock4_got_break, state);
5005 open_req = cli_openx_send(
5006 talloc_tos(), ev, cli2, fname_ln, O_RDWR, DENY_NONE);
5007 if (open_req == NULL) {
5008 printf("cli_openx_send failed\n");
5011 tevent_req_set_callback(open_req, oplock4_got_open, state);
5016 while (!got_break || fnum2 == 0xffff) {
5018 ret = tevent_loop_once(ev);
5020 printf("tevent_loop_once failed: %s\n",
5026 status = cli_close(cli2, fnum2);
5027 if (!NT_STATUS_IS_OK(status)) {
5028 printf("close2 failed (%s)\n", nt_errstr(status));
5032 status = cli_close(cli1, fnum1);
5033 if (!NT_STATUS_IS_OK(status)) {
5034 printf("close1 failed (%s)\n", nt_errstr(status));
5038 status = cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5039 if (!NT_STATUS_IS_OK(status)) {
5040 printf("unlink failed (%s)\n", nt_errstr(status));
5044 status = cli_unlink(cli1, fname_ln, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5045 if (!NT_STATUS_IS_OK(status)) {
5046 printf("unlink failed (%s)\n", nt_errstr(status));
5050 if (!torture_close_connection(cli1)) {
5058 printf("finished oplock test 4\n");
5063 static void oplock4_got_break(struct tevent_req *req)
5065 struct oplock4_state *state = tevent_req_callback_data(
5066 req, struct oplock4_state);
5071 status = cli_smb_oplock_break_waiter_recv(req, &fnum, &level);
5073 if (!NT_STATUS_IS_OK(status)) {
5074 printf("cli_smb_oplock_break_waiter_recv returned %s\n",
5078 *state->got_break = true;
5080 req = cli_oplock_ack_send(state, state->ev, state->cli, fnum,
5083 printf("cli_oplock_ack_send failed\n");
5088 static void oplock4_got_open(struct tevent_req *req)
5090 struct oplock4_state *state = tevent_req_callback_data(
5091 req, struct oplock4_state);
5094 status = cli_openx_recv(req, state->fnum2);
5095 if (!NT_STATUS_IS_OK(status)) {
5096 printf("cli_openx_recv returned %s\n", nt_errstr(status));
5097 *state->fnum2 = 0xffff;
5101 #ifdef HAVE_KERNEL_OPLOCKS_LINUX
5103 struct oplock5_state {
5108 * Async open the file that has a kernel oplock, do an echo to get
5109 * that 100% across, close the file to signal to the child fd that the
5110 * oplock can be dropped, wait for the open reply.
5113 static void oplock5_opened(struct tevent_req *subreq);
5114 static void oplock5_pong(struct tevent_req *subreq);
5115 static void oplock5_timedout(struct tevent_req *subreq);
5117 static struct tevent_req *oplock5_send(
5118 TALLOC_CTX *mem_ctx,
5119 struct tevent_context *ev,
5120 struct cli_state *cli,
5124 struct tevent_req *req = NULL, *subreq = NULL;
5125 struct oplock5_state *state = NULL;
5126 static uint8_t data = 0;
5128 req = tevent_req_create(mem_ctx, &state, struct oplock5_state);
5132 state->pipe_down_fd = pipe_down_fd;
5134 subreq = cli_ntcreate_send(
5140 SEC_FILE_READ_DATA, /* DesiredAccess */
5141 FILE_ATTRIBUTE_NORMAL, /* FileAttributes */
5142 FILE_SHARE_WRITE|FILE_SHARE_READ, /* ShareAccess */
5143 FILE_OPEN, /* CreateDisposition */
5144 FILE_NON_DIRECTORY_FILE, /* CreateOptions */
5145 0, /* Impersonation */
5146 0); /* SecurityFlags */
5147 if (tevent_req_nomem(subreq, req)) {
5148 return tevent_req_post(req, ev);
5150 tevent_req_set_callback(subreq, oplock5_opened, req);
5152 subreq = cli_echo_send(
5157 (DATA_BLOB) { .data = &data, .length = sizeof(data) });
5158 if (tevent_req_nomem(subreq, req)) {
5159 return tevent_req_post(req, ev);
5161 tevent_req_set_callback(subreq, oplock5_pong, req);
5163 subreq = tevent_wakeup_send(state, ev, timeval_current_ofs(20, 0));
5164 if (tevent_req_nomem(subreq, req)) {
5165 return tevent_req_post(req, ev);
5167 tevent_req_set_callback(subreq, oplock5_timedout, req);
5172 static void oplock5_opened(struct tevent_req *subreq)
5174 struct tevent_req *req = tevent_req_callback_data(
5175 subreq, struct tevent_req);
5179 status = cli_ntcreate_recv(subreq, &fnum, NULL);
5180 TALLOC_FREE(subreq);
5181 if (tevent_req_nterror(req, status)) {
5184 tevent_req_done(req);
5187 static void oplock5_pong(struct tevent_req *subreq)
5189 struct tevent_req *req = tevent_req_callback_data(
5190 subreq, struct tevent_req);
5191 struct oplock5_state *state = tevent_req_data(
5192 req, struct oplock5_state);
5195 status = cli_echo_recv(subreq);
5196 TALLOC_FREE(subreq);
5197 if (tevent_req_nterror(req, status)) {
5201 close(state->pipe_down_fd);
5204 static void oplock5_timedout(struct tevent_req *subreq)
5206 struct tevent_req *req = tevent_req_callback_data(
5207 subreq, struct tevent_req);
5210 ok = tevent_wakeup_recv(subreq);
5211 TALLOC_FREE(subreq);
5213 tevent_req_oom(req);
5216 tevent_req_nterror(req, NT_STATUS_TIMEOUT);
5219 static NTSTATUS oplock5_recv(struct tevent_req *req)
5221 return tevent_req_simple_recv_ntstatus(req);
5224 static bool run_oplock5(int dummy)
5226 struct tevent_context *ev = NULL;
5227 struct tevent_req *req = NULL;
5228 struct cli_state *cli = NULL;
5229 const char *fname = "oplock5.txt";
5230 int pipe_down[2], pipe_up[2];
5237 printf("starting oplock5\n");
5239 if (local_path == NULL) {
5240 d_fprintf(stderr, "oplock5 must be given a local path via "
5241 "-l <localpath>\n");
5245 ret = pipe(pipe_down);
5247 d_fprintf(stderr, "pipe() failed: %s\n", strerror(errno));
5250 ret = pipe(pipe_up);
5252 d_fprintf(stderr, "pipe() failed: %s\n", strerror(errno));
5257 if (child_pid == -1) {
5258 d_fprintf(stderr, "fork() failed: %s\n", strerror(errno));
5262 if (child_pid == 0) {
5263 char *local_file = NULL;
5266 close(pipe_down[1]);
5269 local_file = talloc_asprintf(
5270 talloc_tos(), "%s/%s", local_path, fname);
5271 if (local_file == 0) {
5275 fd = open(local_file, O_RDWR|O_CREAT, 0644);
5278 "open(%s) in child failed: %s\n",
5285 signal(SIGIO, SIG_IGN);
5287 ret = fcntl(fd, F_SETLEASE, F_WRLCK);
5290 "SETLEASE in child failed: %s\n",
5297 ret = sys_write(pipe_up[1], &c, sizeof(c));
5300 "sys_write failed: %s\n",
5304 ret = sys_read(pipe_down[0], &c, sizeof(c));
5307 "sys_read failed: %s\n",
5315 close(pipe_down[0]);
5317 ret = sys_read(pipe_up[0], &c, sizeof(c));
5320 "sys_read failed: %s\n",
5325 d_fprintf(stderr, "got error code %"PRIu8"\n", c);
5329 ok = torture_open_connection(&cli, 0);
5331 d_fprintf(stderr, "torture_open_connection failed\n");
5335 ev = samba_tevent_context_init(talloc_tos());
5337 d_fprintf(stderr, "samba_tevent_context_init failed\n");
5341 req = oplock5_send(ev, ev, cli, fname, pipe_down[1]);
5343 d_fprintf(stderr, "oplock5_send failed\n");
5347 ok = tevent_req_poll_ntstatus(req, ev, &status);
5350 "tevent_req_poll_ntstatus failed: %s\n",
5355 status = oplock5_recv(req);
5357 if (!NT_STATUS_IS_OK(status)) {
5359 "oplock5 failed: %s\n",
5367 #endif /* HAVE_KERNEL_OPLOCKS_LINUX */
5370 Test delete on close semantics.
5372 static bool run_deletetest(int dummy)
5374 struct cli_state *cli1 = NULL;
5375 struct cli_state *cli2 = NULL;
5376 const char *fname = "\\delete.file";
5377 uint16_t fnum1 = (uint16_t)-1;
5378 uint16_t fnum2 = (uint16_t)-1;
5379 bool correct = false;
5382 printf("starting delete test\n");
5384 if (!torture_open_connection(&cli1, 0)) {
5388 smbXcli_conn_set_sockopt(cli1->conn, sockops);
5390 /* Test 1 - this should delete the file on close. */
5392 cli_setatr(cli1, fname, 0, 0);
5393 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5395 status = cli_ntcreate(cli1, fname, 0, GENERIC_ALL_ACCESS|DELETE_ACCESS,
5396 FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
5397 FILE_DELETE_ON_CLOSE, 0, &fnum1, NULL);
5398 if (!NT_STATUS_IS_OK(status)) {
5399 printf("[1] open of %s failed (%s)\n", fname, nt_errstr(status));
5403 status = cli_close(cli1, fnum1);
5404 if (!NT_STATUS_IS_OK(status)) {
5405 printf("[1] close failed (%s)\n", nt_errstr(status));
5409 status = cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
5410 if (NT_STATUS_IS_OK(status)) {
5411 printf("[1] open of %s succeeded (should fail)\n", fname);
5415 printf("first delete on close test succeeded.\n");
5417 /* Test 2 - this should delete the file on close. */
5419 cli_setatr(cli1, fname, 0, 0);
5420 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5422 status = cli_ntcreate(cli1, fname, 0, GENERIC_ALL_ACCESS,
5423 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
5424 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
5425 if (!NT_STATUS_IS_OK(status)) {
5426 printf("[2] open of %s failed (%s)\n", fname, nt_errstr(status));
5430 status = cli_nt_delete_on_close(cli1, fnum1, true);
5431 if (!NT_STATUS_IS_OK(status)) {
5432 printf("[2] setting delete_on_close failed (%s)\n", nt_errstr(status));
5436 status = cli_close(cli1, fnum1);
5437 if (!NT_STATUS_IS_OK(status)) {
5438 printf("[2] close failed (%s)\n", nt_errstr(status));
5442 status = cli_openx(cli1, fname, O_RDONLY, DENY_NONE, &fnum1);
5443 if (NT_STATUS_IS_OK(status)) {
5444 printf("[2] open of %s succeeded should have been deleted on close !\n", fname);
5445 status = cli_close(cli1, fnum1);
5446 if (!NT_STATUS_IS_OK(status)) {
5447 printf("[2] close failed (%s)\n", nt_errstr(status));
5449 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5453 printf("second delete on close test succeeded.\n");
5456 cli_setatr(cli1, fname, 0, 0);
5457 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5459 status = cli_ntcreate(cli1, fname, 0, GENERIC_ALL_ACCESS,
5460 FILE_ATTRIBUTE_NORMAL,
5461 FILE_SHARE_READ|FILE_SHARE_WRITE,
5462 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
5463 if (!NT_STATUS_IS_OK(status)) {
5464 printf("[3] open - 1 of %s failed (%s)\n", fname, nt_errstr(status));
5468 /* This should fail with a sharing violation - open for delete is only compatible
5469 with SHARE_DELETE. */
5471 status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
5472 FILE_ATTRIBUTE_NORMAL,
5473 FILE_SHARE_READ|FILE_SHARE_WRITE,
5474 FILE_OPEN, 0, 0, &fnum2, NULL);
5475 if (NT_STATUS_IS_OK(status)) {
5476 printf("[3] open - 2 of %s succeeded - should have failed.\n", fname);
5480 /* This should succeed. */
5481 status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
5482 FILE_ATTRIBUTE_NORMAL,
5483 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5484 FILE_OPEN, 0, 0, &fnum2, NULL);
5485 if (!NT_STATUS_IS_OK(status)) {
5486 printf("[3] open - 3 of %s failed (%s)\n", fname, nt_errstr(status));
5490 status = cli_nt_delete_on_close(cli1, fnum1, true);
5491 if (!NT_STATUS_IS_OK(status)) {
5492 printf("[3] setting delete_on_close failed (%s)\n", nt_errstr(status));
5496 status = cli_close(cli1, fnum1);
5497 if (!NT_STATUS_IS_OK(status)) {
5498 printf("[3] close 1 failed (%s)\n", nt_errstr(status));
5502 status = cli_close(cli1, fnum2);
5503 if (!NT_STATUS_IS_OK(status)) {
5504 printf("[3] close 2 failed (%s)\n", nt_errstr(status));
5508 /* This should fail - file should no longer be there. */
5510 status = cli_openx(cli1, fname, O_RDONLY, DENY_NONE, &fnum1);
5511 if (NT_STATUS_IS_OK(status)) {
5512 printf("[3] open of %s succeeded should have been deleted on close !\n", fname);
5513 status = cli_close(cli1, fnum1);
5514 if (!NT_STATUS_IS_OK(status)) {
5515 printf("[3] close failed (%s)\n", nt_errstr(status));
5517 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5521 printf("third delete on close test succeeded.\n");
5524 cli_setatr(cli1, fname, 0, 0);
5525 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5527 status = cli_ntcreate(cli1, fname, 0,
5528 FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
5529 FILE_ATTRIBUTE_NORMAL,
5530 FILE_SHARE_READ|FILE_SHARE_WRITE,
5531 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
5532 if (!NT_STATUS_IS_OK(status)) {
5533 printf("[4] open of %s failed (%s)\n", fname, nt_errstr(status));
5537 /* This should succeed. */
5538 status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
5539 FILE_ATTRIBUTE_NORMAL,
5540 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5541 FILE_OPEN, 0, 0, &fnum2, NULL);
5542 if (!NT_STATUS_IS_OK(status)) {
5543 printf("[4] open - 2 of %s failed (%s)\n", fname, nt_errstr(status));
5547 status = cli_close(cli1, fnum2);
5548 if (!NT_STATUS_IS_OK(status)) {
5549 printf("[4] close - 1 failed (%s)\n", nt_errstr(status));
5553 status = cli_nt_delete_on_close(cli1, fnum1, true);
5554 if (!NT_STATUS_IS_OK(status)) {
5555 printf("[4] setting delete_on_close failed (%s)\n", nt_errstr(status));
5559 /* This should fail - no more opens once delete on close set. */
5560 status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
5561 FILE_ATTRIBUTE_NORMAL,
5562 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5563 FILE_OPEN, 0, 0, &fnum2, NULL);
5564 if (NT_STATUS_IS_OK(status)) {
5565 printf("[4] open - 3 of %s succeeded ! Should have failed.\n", fname );
5569 status = cli_close(cli1, fnum1);
5570 if (!NT_STATUS_IS_OK(status)) {
5571 printf("[4] close - 2 failed (%s)\n", nt_errstr(status));
5575 printf("fourth delete on close test succeeded.\n");
5578 cli_setatr(cli1, fname, 0, 0);
5579 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5581 status = cli_openx(cli1, fname, O_RDWR|O_CREAT, DENY_NONE, &fnum1);
5582 if (!NT_STATUS_IS_OK(status)) {
5583 printf("[5] open of %s failed (%s)\n", fname, nt_errstr(status));
5587 /* This should fail - only allowed on NT opens with DELETE access. */
5589 status = cli_nt_delete_on_close(cli1, fnum1, true);
5590 if (NT_STATUS_IS_OK(status)) {
5591 printf("[5] setting delete_on_close on OpenX file succeeded - should fail !\n");
5595 status = cli_close(cli1, fnum1);
5596 if (!NT_STATUS_IS_OK(status)) {
5597 printf("[5] close failed (%s)\n", nt_errstr(status));
5601 printf("fifth delete on close test succeeded.\n");
5604 cli_setatr(cli1, fname, 0, 0);
5605 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5607 status = cli_ntcreate(cli1, fname, 0, FILE_READ_DATA|FILE_WRITE_DATA,
5608 FILE_ATTRIBUTE_NORMAL,
5609 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5610 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
5611 if (!NT_STATUS_IS_OK(status)) {
5612 printf("[6] open of %s failed (%s)\n", fname,
5617 /* This should fail - only allowed on NT opens with DELETE access. */
5619 status = cli_nt_delete_on_close(cli1, fnum1, true);
5620 if (NT_STATUS_IS_OK(status)) {
5621 printf("[6] setting delete_on_close on file with no delete access succeeded - should fail !\n");
5625 status = cli_close(cli1, fnum1);
5626 if (!NT_STATUS_IS_OK(status)) {
5627 printf("[6] close failed (%s)\n", nt_errstr(status));
5631 printf("sixth delete on close test succeeded.\n");
5634 cli_setatr(cli1, fname, 0, 0);
5635 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5637 status = cli_ntcreate(cli1, fname, 0,
5638 FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
5639 FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
5640 0, 0, &fnum1, NULL);
5641 if (!NT_STATUS_IS_OK(status)) {
5642 printf("[7] open of %s failed (%s)\n", fname, nt_errstr(status));
5646 status = cli_nt_delete_on_close(cli1, fnum1, true);
5647 if (!NT_STATUS_IS_OK(status)) {
5648 printf("[7] setting delete_on_close on file failed !\n");
5652 status = cli_nt_delete_on_close(cli1, fnum1, false);
5653 if (!NT_STATUS_IS_OK(status)) {
5654 printf("[7] unsetting delete_on_close on file failed !\n");
5658 status = cli_close(cli1, fnum1);
5659 if (!NT_STATUS_IS_OK(status)) {
5660 printf("[7] close - 1 failed (%s)\n", nt_errstr(status));
5664 /* This next open should succeed - we reset the flag. */
5665 status = cli_openx(cli1, fname, O_RDONLY, DENY_NONE, &fnum1);
5666 if (!NT_STATUS_IS_OK(status)) {
5667 printf("[7] open of %s failed (%s)\n", fname, nt_errstr(status));
5671 status = cli_close(cli1, fnum1);
5672 if (!NT_STATUS_IS_OK(status)) {
5673 printf("[7] close - 2 failed (%s)\n", nt_errstr(status));
5677 printf("seventh delete on close test succeeded.\n");
5680 cli_setatr(cli1, fname, 0, 0);
5681 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5683 if (!torture_open_connection(&cli2, 1)) {
5684 printf("[8] failed to open second connection.\n");
5688 smbXcli_conn_set_sockopt(cli1->conn, sockops);
5690 status = cli_ntcreate(cli1, fname, 0,
5691 FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
5692 FILE_ATTRIBUTE_NORMAL,
5693 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5694 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
5695 if (!NT_STATUS_IS_OK(status)) {
5696 printf("[8] open 1 of %s failed (%s)\n", fname, nt_errstr(status));
5700 status = cli_ntcreate(cli2, fname, 0,
5701 FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
5702 FILE_ATTRIBUTE_NORMAL,
5703 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5704 FILE_OPEN, 0, 0, &fnum2, NULL);
5705 if (!NT_STATUS_IS_OK(status)) {
5706 printf("[8] open 2 of %s failed (%s)\n", fname, nt_errstr(status));
5710 status = cli_nt_delete_on_close(cli1, fnum1, true);
5711 if (!NT_STATUS_IS_OK(status)) {
5712 printf("[8] setting delete_on_close on file failed !\n");
5716 status = cli_close(cli1, fnum1);
5717 if (!NT_STATUS_IS_OK(status)) {
5718 printf("[8] close - 1 failed (%s)\n", nt_errstr(status));
5722 status = cli_close(cli2, fnum2);
5723 if (!NT_STATUS_IS_OK(status)) {
5724 printf("[8] close - 2 failed (%s)\n", nt_errstr(status));
5728 /* This should fail.. */
5729 status = cli_openx(cli1, fname, O_RDONLY, DENY_NONE, &fnum1);
5730 if (NT_STATUS_IS_OK(status)) {
5731 printf("[8] open of %s succeeded should have been deleted on close !\n", fname);
5735 printf("eighth delete on close test succeeded.\n");
5739 /* This should fail - we need to set DELETE_ACCESS. */
5740 status = cli_ntcreate(cli1, fname, 0, FILE_READ_DATA|FILE_WRITE_DATA,
5741 FILE_ATTRIBUTE_NORMAL,
5744 FILE_DELETE_ON_CLOSE, 0, &fnum1, NULL);
5745 if (NT_STATUS_IS_OK(status)) {
5746 printf("[9] open of %s succeeded should have failed!\n", fname);
5750 printf("ninth delete on close test succeeded.\n");
5754 status = cli_ntcreate(cli1, fname, 0,
5755 FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
5756 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
5757 FILE_OVERWRITE_IF, FILE_DELETE_ON_CLOSE,
5759 if (!NT_STATUS_IS_OK(status)) {
5760 printf("[10] open of %s failed (%s)\n", fname, nt_errstr(status));
5764 /* This should delete the file. */
5765 status = cli_close(cli1, fnum1);
5766 if (!NT_STATUS_IS_OK(status)) {
5767 printf("[10] close failed (%s)\n", nt_errstr(status));
5771 /* This should fail.. */
5772 status = cli_openx(cli1, fname, O_RDONLY, DENY_NONE, &fnum1);
5773 if (NT_STATUS_IS_OK(status)) {
5774 printf("[10] open of %s succeeded should have been deleted on close !\n", fname);
5778 printf("tenth delete on close test succeeded.\n");
5782 cli_setatr(cli1, fname, 0, 0);
5783 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5785 /* Can we open a read-only file with delete access? */
5787 /* Create a readonly file. */
5788 status = cli_ntcreate(cli1, fname, 0, FILE_READ_DATA|FILE_WRITE_DATA,
5789 FILE_ATTRIBUTE_READONLY, FILE_SHARE_NONE,
5790 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
5791 if (!NT_STATUS_IS_OK(status)) {
5792 printf("[11] open of %s failed (%s)\n", fname, nt_errstr(status));
5796 status = cli_close(cli1, fnum1);
5797 if (!NT_STATUS_IS_OK(status)) {
5798 printf("[11] close failed (%s)\n", nt_errstr(status));
5802 /* Now try open for delete access. */
5803 status = cli_ntcreate(cli1, fname, 0,
5804 FILE_READ_ATTRIBUTES|DELETE_ACCESS,
5806 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5807 FILE_OPEN, 0, 0, &fnum1, NULL);
5808 if (!NT_STATUS_IS_OK(status)) {
5809 printf("[11] open of %s failed: %s\n", fname, nt_errstr(status));
5813 cli_close(cli1, fnum1);
5815 printf("eleventh delete on close test succeeded.\n");
5819 * like test 4 but with initial delete on close
5822 cli_setatr(cli1, fname, 0, 0);
5823 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5825 status = cli_ntcreate(cli1, fname, 0,
5826 FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
5827 FILE_ATTRIBUTE_NORMAL,
5828 FILE_SHARE_READ|FILE_SHARE_WRITE,
5830 FILE_DELETE_ON_CLOSE, 0, &fnum1, NULL);
5831 if (!NT_STATUS_IS_OK(status)) {
5832 printf("[12] open 1 of %s failed (%s)\n", fname, nt_errstr(status));
5836 status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
5837 FILE_ATTRIBUTE_NORMAL,
5838 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5839 FILE_OPEN, 0, 0, &fnum2, NULL);
5840 if (!NT_STATUS_IS_OK(status)) {
5841 printf("[12] open 2 of %s failed(%s).\n", fname, nt_errstr(status));
5845 status = cli_close(cli1, fnum2);
5846 if (!NT_STATUS_IS_OK(status)) {
5847 printf("[12] close 1 failed (%s)\n", nt_errstr(status));
5851 status = cli_nt_delete_on_close(cli1, fnum1, true);
5852 if (!NT_STATUS_IS_OK(status)) {
5853 printf("[12] setting delete_on_close failed (%s)\n", nt_errstr(status));
5857 /* This should fail - no more opens once delete on close set. */
5858 status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
5859 FILE_ATTRIBUTE_NORMAL,
5860 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5861 FILE_OPEN, 0, 0, &fnum2, NULL);
5862 if (NT_STATUS_IS_OK(status)) {
5863 printf("[12] open 3 of %s succeeded - should fail).\n", fname);
5867 status = cli_nt_delete_on_close(cli1, fnum1, false);
5868 if (!NT_STATUS_IS_OK(status)) {
5869 printf("[12] unsetting delete_on_close failed (%s)\n", nt_errstr(status));
5873 status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
5874 FILE_ATTRIBUTE_NORMAL,
5875 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5876 FILE_OPEN, 0, 0, &fnum2, NULL);
5877 if (!NT_STATUS_IS_OK(status)) {
5878 printf("[12] open 4 of %s failed (%s)\n", fname, nt_errstr(status));
5882 status = cli_close(cli1, fnum2);
5883 if (!NT_STATUS_IS_OK(status)) {
5884 printf("[12] close 2 failed (%s)\n", nt_errstr(status));
5888 status = cli_close(cli1, fnum1);
5889 if (!NT_STATUS_IS_OK(status)) {
5890 printf("[12] close 3 failed (%s)\n", nt_errstr(status));
5895 * setting delete on close on the handle does
5896 * not unset the initial delete on close...
5898 status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
5899 FILE_ATTRIBUTE_NORMAL,
5900 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5901 FILE_OPEN, 0, 0, &fnum2, NULL);
5902 if (NT_STATUS_IS_OK(status)) {
5903 printf("[12] open 5 of %s succeeded - should fail).\n", fname);
5905 } else if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
5906 printf("ntcreate returned %s, expected "
5907 "NT_STATUS_OBJECT_NAME_NOT_FOUND\n",
5912 printf("twelfth delete on close test succeeded.\n");
5915 printf("finished delete test\n");
5920 /* FIXME: This will crash if we aborted before cli2 got
5921 * initialized, because these functions don't handle
5922 * uninitialized connections. */
5924 if (fnum1 != (uint16_t)-1) cli_close(cli1, fnum1);
5925 if (fnum2 != (uint16_t)-1) cli_close(cli1, fnum2);
5926 cli_setatr(cli1, fname, 0, 0);
5927 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5929 if (cli1 && !torture_close_connection(cli1)) {
5932 if (cli2 && !torture_close_connection(cli2)) {
5938 struct delete_stream_state {
5942 static void delete_stream_unlinked(struct tevent_req *subreq);
5943 static void delete_stream_closed(struct tevent_req *subreq);
5945 static struct tevent_req *delete_stream_send(
5946 TALLOC_CTX *mem_ctx,
5947 struct tevent_context *ev,
5948 struct cli_state *cli,
5949 const char *base_fname,
5950 uint16_t stream_fnum)
5952 struct tevent_req *req = NULL, *subreq = NULL;
5953 struct delete_stream_state *state = NULL;
5955 req = tevent_req_create(
5956 mem_ctx, &state, struct delete_stream_state);
5961 subreq = cli_unlink_send(
5966 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5967 if (tevent_req_nomem(subreq, req)) {
5968 return tevent_req_post(req, ev);
5970 tevent_req_set_callback(subreq, delete_stream_unlinked, req);
5972 subreq = cli_close_send(state, ev, cli, stream_fnum, 0);
5973 if (tevent_req_nomem(subreq, req)) {
5974 return tevent_req_post(req, ev);
5976 tevent_req_set_callback(subreq, delete_stream_closed, req);
5981 static void delete_stream_unlinked(struct tevent_req *subreq)
5983 struct tevent_req *req = tevent_req_callback_data(
5984 subreq, struct tevent_req);
5985 struct delete_stream_state *state = tevent_req_data(
5986 req, struct delete_stream_state);
5989 status = cli_unlink_recv(subreq);
5990 TALLOC_FREE(subreq);
5991 if (!NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
5992 printf("cli_unlink returned %s\n",
5994 tevent_req_nterror(req, NT_STATUS_UNSUCCESSFUL);
5997 if (!state->closed) {
5998 /* close reply should have come in first */
5999 printf("Not closed\n");
6000 tevent_req_nterror(req, NT_STATUS_UNSUCCESSFUL);
6003 tevent_req_done(req);
6006 static void delete_stream_closed(struct tevent_req *subreq)
6008 struct tevent_req *req = tevent_req_callback_data(
6009 subreq, struct tevent_req);
6010 struct delete_stream_state *state = tevent_req_data(
6011 req, struct delete_stream_state);
6014 status = cli_close_recv(subreq);
6015 TALLOC_FREE(subreq);
6016 if (tevent_req_nterror(req, status)) {
6019 /* also waiting for the unlink to come back */
6020 state->closed = true;
6023 static NTSTATUS delete_stream_recv(struct tevent_req *req)
6025 return tevent_req_simple_recv_ntstatus(req);
6028 static bool run_delete_stream(int dummy)
6030 struct tevent_context *ev = NULL;
6031 struct tevent_req *req = NULL;
6032 struct cli_state *cli = NULL;
6033 const char fname[] = "delete_stream";
6034 const char fname_stream[] = "delete_stream:Zone.Identifier:$DATA";
6035 uint16_t fnum1, fnum2;
6039 printf("Starting stream delete test\n");
6041 ok = torture_open_connection(&cli, 0);
6046 cli_setatr(cli, fname, 0, 0);
6047 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6049 /* Create the file. */
6050 status = cli_ntcreate(
6054 READ_CONTROL_ACCESS,
6056 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6062 if (!NT_STATUS_IS_OK(status)) {
6064 "cli_ntcreate of %s failed (%s)\n",
6069 status = cli_close(cli, fnum1);
6070 if (!NT_STATUS_IS_OK(status)) {
6072 "cli_close of %s failed (%s)\n",
6078 /* Now create the stream. */
6079 status = cli_ntcreate(
6085 FILE_SHARE_READ|FILE_SHARE_WRITE,
6092 if (!NT_STATUS_IS_OK(status)) {
6094 "cli_ntcreate of %s failed (%s)\n",
6100 /* open it a second time */
6102 status = cli_ntcreate(
6108 FILE_SHARE_READ|FILE_SHARE_WRITE,
6115 if (!NT_STATUS_IS_OK(status)) {
6117 "2nd cli_ntcreate of %s failed (%s)\n",
6123 ev = samba_tevent_context_init(talloc_tos());
6125 d_fprintf(stderr, "samba_tevent_context_init failed\n");
6129 req = delete_stream_send(ev, ev, cli, fname, fnum1);
6131 d_fprintf(stderr, "delete_stream_send failed\n");
6135 ok = tevent_req_poll_ntstatus(req, ev, &status);
6138 "tevent_req_poll_ntstatus failed: %s\n",
6143 status = delete_stream_recv(req);
6145 if (!NT_STATUS_IS_OK(status)) {
6147 "delete_stream failed: %s\n",
6152 status = cli_close(cli, fnum2);
6153 if (!NT_STATUS_IS_OK(status)) {
6155 "close failed: %s\n",
6160 status = cli_unlink(
6161 cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6162 if (!NT_STATUS_IS_OK(status)) {
6164 "unlink failed: %s\n",
6173 Exercise delete on close semantics - use on the PRINT1 share in torture
6176 static bool run_delete_print_test(int dummy)
6178 struct cli_state *cli1 = NULL;
6179 const char *fname = "print_delete.file";
6180 uint16_t fnum1 = (uint16_t)-1;
6181 bool correct = false;
6182 const char *buf = "print file data\n";
6185 printf("starting print delete test\n");
6187 if (!torture_open_connection(&cli1, 0)) {
6191 smbXcli_conn_set_sockopt(cli1->conn, sockops);
6193 status = cli_ntcreate(cli1, fname, 0, GENERIC_ALL_ACCESS|DELETE_ACCESS,
6194 FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
6195 0, 0, &fnum1, NULL);
6196 if (!NT_STATUS_IS_OK(status)) {
6197 printf("open of %s failed (%s)\n",
6203 status = cli_writeall(cli1,
6206 (const uint8_t *)buf,
6208 strlen(buf), /* size */
6210 if (!NT_STATUS_IS_OK(status)) {
6211 printf("writing print file data failed (%s)\n",
6216 status = cli_nt_delete_on_close(cli1, fnum1, true);
6217 if (!NT_STATUS_IS_OK(status)) {
6218 printf("setting delete_on_close failed (%s)\n",
6223 status = cli_close(cli1, fnum1);
6224 if (!NT_STATUS_IS_OK(status)) {
6225 printf("close failed (%s)\n", nt_errstr(status));
6229 printf("finished print delete test\n");
6235 if (fnum1 != (uint16_t)-1) {
6236 cli_close(cli1, fnum1);
6239 if (cli1 && !torture_close_connection(cli1)) {
6245 static bool run_deletetest_ln(int dummy)
6247 struct cli_state *cli;
6248 const char *fname = "\\delete1";
6249 const char *fname_ln = "\\delete1_ln";
6253 bool correct = true;
6256 printf("starting deletetest-ln\n");
6258 if (!torture_open_connection(&cli, 0)) {
6262 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6263 cli_unlink(cli, fname_ln, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6265 smbXcli_conn_set_sockopt(cli->conn, sockops);
6267 /* Create the file. */
6268 status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
6269 if (!NT_STATUS_IS_OK(status)) {
6270 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
6274 status = cli_close(cli, fnum);
6275 if (!NT_STATUS_IS_OK(status)) {
6276 printf("close1 failed (%s)\n", nt_errstr(status));
6280 /* Now create a hardlink. */
6281 status = cli_hardlink(cli, fname, fname_ln);
6282 if (!NT_STATUS_IS_OK(status)) {
6283 printf("nt hardlink failed (%s)\n", nt_errstr(status));
6287 /* Open the original file. */
6288 status = cli_ntcreate(cli, fname, 0, FILE_READ_DATA,
6289 FILE_ATTRIBUTE_NORMAL,
6290 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6291 FILE_OPEN_IF, 0, 0, &fnum, NULL);
6292 if (!NT_STATUS_IS_OK(status)) {
6293 printf("ntcreate of %s failed (%s)\n", fname, nt_errstr(status));
6297 /* Unlink the hard link path. */
6298 status = cli_ntcreate(cli, fname_ln, 0, DELETE_ACCESS,
6299 FILE_ATTRIBUTE_NORMAL,
6300 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6301 FILE_OPEN_IF, 0, 0, &fnum1, NULL);
6302 if (!NT_STATUS_IS_OK(status)) {
6303 printf("ntcreate of %s failed (%s)\n", fname_ln, nt_errstr(status));
6306 status = cli_nt_delete_on_close(cli, fnum1, true);
6307 if (!NT_STATUS_IS_OK(status)) {
6308 d_printf("(%s) failed to set delete_on_close %s: %s\n",
6309 __location__, fname_ln, nt_errstr(status));
6313 status = cli_close(cli, fnum1);
6314 if (!NT_STATUS_IS_OK(status)) {
6315 printf("close %s failed (%s)\n",
6316 fname_ln, nt_errstr(status));
6320 status = cli_close(cli, fnum);
6321 if (!NT_STATUS_IS_OK(status)) {
6322 printf("close %s failed (%s)\n",
6323 fname, nt_errstr(status));
6327 /* Ensure the original file is still there. */
6328 status = cli_getatr(cli, fname, NULL, NULL, &t);
6329 if (!NT_STATUS_IS_OK(status)) {
6330 printf("%s getatr on file %s failed (%s)\n",
6337 /* Ensure the link path is gone. */
6338 status = cli_getatr(cli, fname_ln, NULL, NULL, &t);
6339 if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
6340 printf("%s, getatr for file %s returned wrong error code %s "
6341 "- should have been deleted\n",
6343 fname_ln, nt_errstr(status));
6347 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6348 cli_unlink(cli, fname_ln, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6350 if (!torture_close_connection(cli)) {
6354 printf("finished deletetest-ln\n");
6360 print out server properties
6362 static bool run_properties(int dummy)
6364 struct cli_state *cli;
6365 bool correct = True;
6367 printf("starting properties test\n");
6371 if (!torture_open_connection(&cli, 0)) {
6375 smbXcli_conn_set_sockopt(cli->conn, sockops);
6377 d_printf("Capabilities 0x%08x\n", smb1cli_conn_capabilities(cli->conn));
6379 if (!torture_close_connection(cli)) {
6388 /* FIRST_DESIRED_ACCESS 0xf019f */
6389 #define FIRST_DESIRED_ACCESS FILE_READ_DATA|FILE_WRITE_DATA|FILE_APPEND_DATA|\
6390 FILE_READ_EA| /* 0xf */ \
6391 FILE_WRITE_EA|FILE_READ_ATTRIBUTES| /* 0x90 */ \
6392 FILE_WRITE_ATTRIBUTES| /* 0x100 */ \
6393 DELETE_ACCESS|READ_CONTROL_ACCESS|\
6394 WRITE_DAC_ACCESS|WRITE_OWNER_ACCESS /* 0xf0000 */
6395 /* SECOND_DESIRED_ACCESS 0xe0080 */
6396 #define SECOND_DESIRED_ACCESS FILE_READ_ATTRIBUTES| /* 0x80 */ \
6397 READ_CONTROL_ACCESS|WRITE_DAC_ACCESS|\
6398 WRITE_OWNER_ACCESS /* 0xe0000 */
6401 #define THIRD_DESIRED_ACCESS FILE_READ_ATTRIBUTES| /* 0x80 */ \
6402 READ_CONTROL_ACCESS|WRITE_DAC_ACCESS|\
6404 WRITE_OWNER_ACCESS /* */
6408 Test ntcreate calls made by xcopy
6410 static bool run_xcopy(int dummy)
6412 static struct cli_state *cli1;
6413 const char *fname = "\\test.txt";
6414 bool correct = True;
6415 uint16_t fnum1, fnum2;
6418 printf("starting xcopy test\n");
6420 if (!torture_open_connection(&cli1, 0)) {
6424 status = cli_ntcreate(cli1, fname, 0, FIRST_DESIRED_ACCESS,
6425 FILE_ATTRIBUTE_ARCHIVE, FILE_SHARE_NONE,
6426 FILE_OVERWRITE_IF, 0x4044, 0, &fnum1, NULL);
6427 if (!NT_STATUS_IS_OK(status)) {
6428 printf("First open failed - %s\n", nt_errstr(status));
6432 status = cli_ntcreate(cli1, fname, 0, SECOND_DESIRED_ACCESS, 0,
6433 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6434 FILE_OPEN, 0x200000, 0, &fnum2, NULL);
6435 if (!NT_STATUS_IS_OK(status)) {
6436 printf("second open failed - %s\n", nt_errstr(status));
6440 if (!torture_close_connection(cli1)) {
6448 Test rename on files open with share delete and no share delete.
6450 static bool run_rename(int dummy)
6452 static struct cli_state *cli1;
6453 const char *fname = "\\test.txt";
6454 const char *fname1 = "\\test1.txt";
6455 bool correct = True;
6460 printf("starting rename test\n");
6462 if (!torture_open_connection(&cli1, 0)) {
6466 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6467 cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6469 status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
6470 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ,
6471 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
6472 if (!NT_STATUS_IS_OK(status)) {
6473 printf("First open failed - %s\n", nt_errstr(status));
6477 status = cli_rename(cli1, fname, fname1, false);
6478 if (!NT_STATUS_IS_OK(status)) {
6479 printf("First rename failed (SHARE_READ) (this is correct) - %s\n", nt_errstr(status));
6481 printf("First rename succeeded (SHARE_READ) - this should have failed !\n");
6485 status = cli_close(cli1, fnum1);
6486 if (!NT_STATUS_IS_OK(status)) {
6487 printf("close - 1 failed (%s)\n", nt_errstr(status));
6491 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6492 cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6493 status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS, FILE_ATTRIBUTE_NORMAL,
6495 FILE_SHARE_DELETE|FILE_SHARE_NONE,
6497 FILE_SHARE_DELETE|FILE_SHARE_READ,
6499 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
6500 if (!NT_STATUS_IS_OK(status)) {
6501 printf("Second open failed - %s\n", nt_errstr(status));
6505 status = cli_rename(cli1, fname, fname1, false);
6506 if (!NT_STATUS_IS_OK(status)) {
6507 printf("Second rename failed (SHARE_DELETE | SHARE_READ) - this should have succeeded - %s\n", nt_errstr(status));
6510 printf("Second rename succeeded (SHARE_DELETE | SHARE_READ)\n");
6513 status = cli_close(cli1, fnum1);
6514 if (!NT_STATUS_IS_OK(status)) {
6515 printf("close - 2 failed (%s)\n", nt_errstr(status));
6519 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6520 cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6522 status = cli_ntcreate(cli1, fname, 0, READ_CONTROL_ACCESS,
6523 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
6524 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
6525 if (!NT_STATUS_IS_OK(status)) {
6526 printf("Third open failed - %s\n", nt_errstr(status));
6531 status = cli_rename(cli1, fname, fname1, false);
6532 if (!NT_STATUS_IS_OK(status)) {
6533 printf("Third rename failed (SHARE_NONE) - this should have succeeded - %s\n", nt_errstr(status));
6536 printf("Third rename succeeded (SHARE_NONE)\n");
6539 status = cli_close(cli1, fnum1);
6540 if (!NT_STATUS_IS_OK(status)) {
6541 printf("close - 3 failed (%s)\n", nt_errstr(status));
6545 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6546 cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6550 status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
6551 FILE_ATTRIBUTE_NORMAL,
6552 FILE_SHARE_READ | FILE_SHARE_WRITE,
6553 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
6554 if (!NT_STATUS_IS_OK(status)) {
6555 printf("Fourth open failed - %s\n", nt_errstr(status));
6559 status = cli_rename(cli1, fname, fname1, false);
6560 if (!NT_STATUS_IS_OK(status)) {
6561 printf("Fourth rename failed (SHARE_READ | SHARE_WRITE) (this is correct) - %s\n", nt_errstr(status));
6563 printf("Fourth rename succeeded (SHARE_READ | SHARE_WRITE) - this should have failed !\n");
6567 status = cli_close(cli1, fnum1);
6568 if (!NT_STATUS_IS_OK(status)) {
6569 printf("close - 4 failed (%s)\n", nt_errstr(status));
6573 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6574 cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6578 status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
6579 FILE_ATTRIBUTE_NORMAL,
6580 FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
6581 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
6582 if (!NT_STATUS_IS_OK(status)) {
6583 printf("Fifth open failed - %s\n", nt_errstr(status));
6587 status = cli_rename(cli1, fname, fname1, false);
6588 if (!NT_STATUS_IS_OK(status)) {
6589 printf("Fifth rename failed (SHARE_READ | SHARE_WRITE | SHARE_DELETE) - this should have succeeded - %s ! \n", nt_errstr(status));
6592 printf("Fifth rename succeeded (SHARE_READ | SHARE_WRITE | SHARE_DELETE) (this is correct) - %s\n", nt_errstr(status));
6596 status = cli_close(cli1, fnum1);
6597 if (!NT_STATUS_IS_OK(status)) {
6598 printf("close - 5 failed (%s)\n", nt_errstr(status));
6602 /* Check that the renamed file has FILE_ATTRIBUTE_ARCHIVE. */
6603 status = cli_getatr(cli1, fname1, &attr, NULL, NULL);
6604 if (!NT_STATUS_IS_OK(status)) {
6605 printf("getatr on file %s failed - %s ! \n",
6606 fname1, nt_errstr(status));
6609 if (attr != FILE_ATTRIBUTE_ARCHIVE) {
6610 printf("Renamed file %s has wrong attr 0x%x "
6611 "(should be 0x%x)\n",
6614 (unsigned int)FILE_ATTRIBUTE_ARCHIVE);
6617 printf("Renamed file %s has archive bit set\n", fname1);
6621 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6622 cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6624 if (!torture_close_connection(cli1)) {
6632 Test rename into a directory with an ACL denying it.
6634 static bool run_rename_access(int dummy)
6636 static struct cli_state *cli = NULL;
6637 static struct cli_state *posix_cli = NULL;
6638 const char *src = "test.txt";
6639 const char *dname = "dir";
6640 const char *dst = "dir\\test.txt";
6641 const char *dsrc = "test.dir";
6642 const char *ddst = "dir\\test.dir";
6643 uint16_t fnum = (uint16_t)-1;
6644 struct security_descriptor *sd = NULL;
6645 struct security_descriptor *newsd = NULL;
6647 TALLOC_CTX *frame = NULL;
6649 frame = talloc_stackframe();
6650 printf("starting rename access test\n");
6652 /* Windows connection. */
6653 if (!torture_open_connection(&cli, 0)) {
6657 smbXcli_conn_set_sockopt(cli->conn, sockops);
6659 /* Posix connection. */
6660 if (!torture_open_connection(&posix_cli, 0)) {
6664 smbXcli_conn_set_sockopt(posix_cli->conn, sockops);
6666 status = torture_setup_unix_extensions(posix_cli);
6667 if (!NT_STATUS_IS_OK(status)) {
6671 /* Start with a clean slate. */
6672 cli_unlink(cli, src, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6673 cli_unlink(cli, dst, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6674 cli_rmdir(cli, dsrc);
6675 cli_rmdir(cli, ddst);
6676 cli_rmdir(cli, dname);
6679 * Setup the destination directory with a DENY ACE to
6680 * prevent new files within it.
6682 status = cli_ntcreate(cli,
6685 FILE_READ_ATTRIBUTES|READ_CONTROL_ACCESS|
6686 WRITE_DAC_ACCESS|FILE_READ_DATA|
6688 FILE_ATTRIBUTE_DIRECTORY,
6689 FILE_SHARE_READ|FILE_SHARE_WRITE,
6691 FILE_DIRECTORY_FILE,
6695 if (!NT_STATUS_IS_OK(status)) {
6696 printf("Create of %s - %s\n", dname, nt_errstr(status));
6700 status = cli_query_secdesc(cli,
6704 if (!NT_STATUS_IS_OK(status)) {
6705 printf("cli_query_secdesc failed for %s (%s)\n",
6706 dname, nt_errstr(status));
6710 newsd = security_descriptor_dacl_create(frame,
6715 SEC_ACE_TYPE_ACCESS_DENIED,
6716 SEC_DIR_ADD_FILE|SEC_DIR_ADD_SUBDIR,
6719 if (newsd == NULL) {
6722 sd->dacl = security_acl_concatenate(frame,
6725 if (sd->dacl == NULL) {
6728 status = cli_set_secdesc(cli, fnum, sd);
6729 if (!NT_STATUS_IS_OK(status)) {
6730 printf("cli_set_secdesc failed for %s (%s)\n",
6731 dname, nt_errstr(status));
6734 status = cli_close(cli, fnum);
6735 if (!NT_STATUS_IS_OK(status)) {
6736 printf("close failed for %s (%s)\n",
6737 dname, nt_errstr(status));
6740 /* Now go around the back and chmod to 777 via POSIX. */
6741 status = cli_posix_chmod(posix_cli, dname, 0777);
6742 if (!NT_STATUS_IS_OK(status)) {
6743 printf("cli_posix_chmod failed for %s (%s)\n",
6744 dname, nt_errstr(status));
6748 /* Check we can't create a file within dname via Windows. */
6749 status = cli_openx(cli, dst, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
6750 if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
6751 cli_close(posix_cli, fnum);
6752 printf("Create of %s should be ACCESS denied, was %s\n",
6753 dst, nt_errstr(status));
6757 /* Make the sample file/directory. */
6758 status = cli_openx(cli, src, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
6759 if (!NT_STATUS_IS_OK(status)) {
6760 printf("open of %s failed (%s)\n", src, nt_errstr(status));
6763 status = cli_close(cli, fnum);
6764 if (!NT_STATUS_IS_OK(status)) {
6765 printf("cli_close failed (%s)\n", nt_errstr(status));
6769 status = cli_mkdir(cli, dsrc);
6770 if (!NT_STATUS_IS_OK(status)) {
6771 printf("cli_mkdir of %s failed (%s)\n",
6772 dsrc, nt_errstr(status));
6777 * OK - renames of the new file and directory into the
6778 * dst directory should fail.
6781 status = cli_rename(cli, src, dst, false);
6782 if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
6783 printf("rename of %s -> %s should be ACCESS denied, was %s\n",
6784 src, dst, nt_errstr(status));
6787 status = cli_rename(cli, dsrc, ddst, false);
6788 if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
6789 printf("rename of %s -> %s should be ACCESS denied, was %s\n",
6790 src, dst, nt_errstr(status));
6800 torture_close_connection(posix_cli);
6804 if (fnum != (uint16_t)-1) {
6805 cli_close(cli, fnum);
6807 cli_unlink(cli, src,
6808 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6809 cli_unlink(cli, dst,
6810 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6811 cli_rmdir(cli, dsrc);
6812 cli_rmdir(cli, ddst);
6813 cli_rmdir(cli, dname);
6815 torture_close_connection(cli);
6823 Test owner rights ACE.
6825 static bool run_owner_rights(int dummy)
6827 static struct cli_state *cli = NULL;
6828 const char *fname = "owner_rights.txt";
6829 uint16_t fnum = (uint16_t)-1;
6830 struct security_descriptor *sd = NULL;
6831 struct security_descriptor *newsd = NULL;
6833 TALLOC_CTX *frame = NULL;
6835 frame = talloc_stackframe();
6836 printf("starting owner rights test\n");
6838 /* Windows connection. */
6839 if (!torture_open_connection(&cli, 0)) {
6843 smbXcli_conn_set_sockopt(cli->conn, sockops);
6845 /* Start with a clean slate. */
6846 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6848 /* Create the test file. */
6849 /* Now try and open for read and write-dac. */
6850 status = cli_ntcreate(cli,
6854 FILE_ATTRIBUTE_NORMAL,
6855 FILE_SHARE_READ|FILE_SHARE_WRITE|
6862 if (!NT_STATUS_IS_OK(status)) {
6863 printf("Create of %s - %s\n", fname, nt_errstr(status));
6867 /* Get the original SD. */
6868 status = cli_query_secdesc(cli,
6872 if (!NT_STATUS_IS_OK(status)) {
6873 printf("cli_query_secdesc failed for %s (%s)\n",
6874 fname, nt_errstr(status));
6879 * Add an "owner-rights" ACE denying WRITE_DATA,
6880 * and an "owner-rights" ACE allowing READ_DATA.
6883 newsd = security_descriptor_dacl_create(frame,
6888 SEC_ACE_TYPE_ACCESS_DENIED,
6892 SEC_ACE_TYPE_ACCESS_ALLOWED,
6896 if (newsd == NULL) {
6899 sd->dacl = security_acl_concatenate(frame,
6902 if (sd->dacl == NULL) {
6905 status = cli_set_secdesc(cli, fnum, sd);
6906 if (!NT_STATUS_IS_OK(status)) {
6907 printf("cli_set_secdesc failed for %s (%s)\n",
6908 fname, nt_errstr(status));
6911 status = cli_close(cli, fnum);
6912 if (!NT_STATUS_IS_OK(status)) {
6913 printf("close failed for %s (%s)\n",
6914 fname, nt_errstr(status));
6917 fnum = (uint16_t)-1;
6919 /* Try and open for FILE_WRITE_DATA */
6920 status = cli_ntcreate(cli,
6924 FILE_ATTRIBUTE_NORMAL,
6925 FILE_SHARE_READ|FILE_SHARE_WRITE|
6932 if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
6933 printf("Open of %s - %s\n", fname, nt_errstr(status));
6937 /* Now try and open for FILE_READ_DATA */
6938 status = cli_ntcreate(cli,
6942 FILE_ATTRIBUTE_NORMAL,
6943 FILE_SHARE_READ|FILE_SHARE_WRITE|
6950 if (!NT_STATUS_IS_OK(status)) {
6951 printf("Open of %s - %s\n", fname, nt_errstr(status));
6955 status = cli_close(cli, fnum);
6956 if (!NT_STATUS_IS_OK(status)) {
6957 printf("close failed for %s (%s)\n",
6958 fname, nt_errstr(status));
6962 /* Restore clean slate. */
6964 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6966 /* Create the test file. */
6967 status = cli_ntcreate(cli,
6971 FILE_ATTRIBUTE_NORMAL,
6972 FILE_SHARE_READ|FILE_SHARE_WRITE|
6979 if (!NT_STATUS_IS_OK(status)) {
6980 printf("Create of %s - %s\n", fname, nt_errstr(status));
6984 /* Get the original SD. */
6985 status = cli_query_secdesc(cli,
6989 if (!NT_STATUS_IS_OK(status)) {
6990 printf("cli_query_secdesc failed for %s (%s)\n",
6991 fname, nt_errstr(status));
6996 * Add an "owner-rights ACE denying WRITE_DATA,
6997 * and an "owner-rights ACE allowing READ_DATA|WRITE_DATA.
7000 newsd = security_descriptor_dacl_create(frame,
7005 SEC_ACE_TYPE_ACCESS_DENIED,
7009 SEC_ACE_TYPE_ACCESS_ALLOWED,
7010 FILE_READ_DATA|FILE_WRITE_DATA,
7013 if (newsd == NULL) {
7016 sd->dacl = security_acl_concatenate(frame,
7019 if (sd->dacl == NULL) {
7022 status = cli_set_secdesc(cli, fnum, sd);
7023 if (!NT_STATUS_IS_OK(status)) {
7024 printf("cli_set_secdesc failed for %s (%s)\n",
7025 fname, nt_errstr(status));
7028 status = cli_close(cli, fnum);
7029 if (!NT_STATUS_IS_OK(status)) {
7030 printf("close failed for %s (%s)\n",
7031 fname, nt_errstr(status));
7034 fnum = (uint16_t)-1;
7036 /* Try and open for FILE_WRITE_DATA */
7037 status = cli_ntcreate(cli,
7041 FILE_ATTRIBUTE_NORMAL,
7042 FILE_SHARE_READ|FILE_SHARE_WRITE|
7049 if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
7050 printf("Open of %s - %s\n", fname, nt_errstr(status));
7054 /* Now try and open for FILE_READ_DATA */
7055 status = cli_ntcreate(cli,
7059 FILE_ATTRIBUTE_NORMAL,
7060 FILE_SHARE_READ|FILE_SHARE_WRITE|
7067 if (!NT_STATUS_IS_OK(status)) {
7068 printf("Open of %s - %s\n", fname, nt_errstr(status));
7072 status = cli_close(cli, fnum);
7073 if (!NT_STATUS_IS_OK(status)) {
7074 printf("close failed for %s (%s)\n",
7075 fname, nt_errstr(status));
7079 /* Restore clean slate. */
7081 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7084 /* Create the test file. */
7085 status = cli_ntcreate(cli,
7089 FILE_ATTRIBUTE_NORMAL,
7090 FILE_SHARE_READ|FILE_SHARE_WRITE|
7097 if (!NT_STATUS_IS_OK(status)) {
7098 printf("Create of %s - %s\n", fname, nt_errstr(status));
7102 /* Get the original SD. */
7103 status = cli_query_secdesc(cli,
7107 if (!NT_STATUS_IS_OK(status)) {
7108 printf("cli_query_secdesc failed for %s (%s)\n",
7109 fname, nt_errstr(status));
7114 * Add an "authenticated users" ACE allowing READ_DATA,
7115 * add an "owner-rights" denying READ_DATA,
7116 * and an "authenticated users" ACE allowing WRITE_DATA.
7119 newsd = security_descriptor_dacl_create(frame,
7123 SID_NT_AUTHENTICATED_USERS,
7124 SEC_ACE_TYPE_ACCESS_ALLOWED,
7128 SEC_ACE_TYPE_ACCESS_DENIED,
7131 SID_NT_AUTHENTICATED_USERS,
7132 SEC_ACE_TYPE_ACCESS_ALLOWED,
7136 if (newsd == NULL) {
7137 printf("newsd == NULL\n");
7140 sd->dacl = security_acl_concatenate(frame,
7143 if (sd->dacl == NULL) {
7144 printf("sd->dacl == NULL\n");
7147 status = cli_set_secdesc(cli, fnum, sd);
7148 if (!NT_STATUS_IS_OK(status)) {
7149 printf("cli_set_secdesc failed for %s (%s)\n",
7150 fname, nt_errstr(status));
7153 status = cli_close(cli, fnum);
7154 if (!NT_STATUS_IS_OK(status)) {
7155 printf("close failed for %s (%s)\n",
7156 fname, nt_errstr(status));
7159 fnum = (uint16_t)-1;
7161 /* Now try and open for FILE_READ_DATA|FILE_WRITE_DATA */
7162 status = cli_ntcreate(cli,
7165 FILE_READ_DATA|FILE_WRITE_DATA,
7166 FILE_ATTRIBUTE_NORMAL,
7167 FILE_SHARE_READ|FILE_SHARE_WRITE|
7174 if (!NT_STATUS_IS_OK(status)) {
7175 printf("Open of %s - %s\n", fname, nt_errstr(status));
7179 status = cli_close(cli, fnum);
7180 if (!NT_STATUS_IS_OK(status)) {
7181 printf("close failed for %s (%s)\n",
7182 fname, nt_errstr(status));
7186 cli_unlink(cli, fname,
7187 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7195 if (fnum != (uint16_t)-1) {
7196 cli_close(cli, fnum);
7198 cli_unlink(cli, fname,
7199 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7200 torture_close_connection(cli);
7208 * Test SMB1-specific open with SEC_FLAG_SYSTEM_SECURITY.
7209 * Note this test only works with a user with SeSecurityPrivilege set.
7211 * NB. This is also tested in samba3.base.createx_access
7212 * but this makes it very explicit what we're looking for.
7214 static bool run_smb1_system_security(int dummy)
7216 static struct cli_state *cli = NULL;
7217 const char *fname = "system_security.txt";
7218 uint16_t fnum = (uint16_t)-1;
7220 TALLOC_CTX *frame = NULL;
7222 frame = talloc_stackframe();
7223 printf("starting smb1 system security test\n");
7225 /* SMB1 connection - torture_open_connection() forces this. */
7226 if (!torture_open_connection(&cli, 0)) {
7230 smbXcli_conn_set_sockopt(cli->conn, sockops);
7232 /* Start with a clean slate. */
7233 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7235 /* Create the test file. */
7236 status = cli_ntcreate(cli,
7240 FILE_ATTRIBUTE_NORMAL,
7241 FILE_SHARE_READ|FILE_SHARE_WRITE|
7248 if (!NT_STATUS_IS_OK(status)) {
7249 printf("Create of %s - %s\n", fname, nt_errstr(status));
7253 status = cli_close(cli, fnum);
7255 /* Open with SEC_FLAG_SYSTEM_SECURITY only. */
7257 * On SMB1 this succeeds - SMB2 it fails,
7258 * see the SMB2-SACL test.
7260 status = cli_ntcreate(cli,
7263 SEC_FLAG_SYSTEM_SECURITY,
7264 FILE_ATTRIBUTE_NORMAL,
7265 FILE_SHARE_READ|FILE_SHARE_WRITE|
7272 if (!NT_STATUS_IS_OK(status)) {
7273 printf("Open of %s - %s\n", fname, nt_errstr(status));
7277 status = cli_close(cli, fnum);
7279 cli_unlink(cli, fname,
7280 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7282 torture_close_connection(cli);
7289 if (fnum != (uint16_t)-1) {
7290 cli_close(cli, fnum);
7292 cli_unlink(cli, fname,
7293 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7294 torture_close_connection(cli);
7301 static bool run_pipe_number(int dummy)
7303 struct cli_state *cli1;
7304 const char *pipe_name = "\\SPOOLSS";
7309 printf("starting pipenumber test\n");
7310 if (!torture_open_connection(&cli1, 0)) {
7314 smbXcli_conn_set_sockopt(cli1->conn, sockops);
7316 status = cli_ntcreate(cli1, pipe_name, 0, FILE_READ_DATA,
7317 FILE_ATTRIBUTE_NORMAL,
7318 FILE_SHARE_READ|FILE_SHARE_WRITE,
7319 FILE_OPEN_IF, 0, 0, &fnum, NULL);
7320 if (!NT_STATUS_IS_OK(status)) {
7321 printf("Open of pipe %s failed with error (%s)\n", pipe_name, nt_errstr(status));
7325 printf("\r%6d", num_pipes);
7328 printf("pipe_number test - we can open %d %s pipes.\n", num_pipes, pipe_name );
7329 torture_close_connection(cli1);
7334 Test open mode returns on read-only files.
7336 static bool run_opentest(int dummy)
7338 static struct cli_state *cli1;
7339 static struct cli_state *cli2;
7340 const char *fname = "\\readonly.file";
7341 uint16_t fnum1, fnum2;
7344 bool correct = True;
7348 printf("starting open test\n");
7350 if (!torture_open_connection(&cli1, 0)) {
7354 cli_setatr(cli1, fname, 0, 0);
7355 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7357 smbXcli_conn_set_sockopt(cli1->conn, sockops);
7359 status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
7360 if (!NT_STATUS_IS_OK(status)) {
7361 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
7365 status = cli_close(cli1, fnum1);
7366 if (!NT_STATUS_IS_OK(status)) {
7367 printf("close2 failed (%s)\n", nt_errstr(status));
7371 status = cli_setatr(cli1, fname, FILE_ATTRIBUTE_READONLY, 0);
7372 if (!NT_STATUS_IS_OK(status)) {
7373 printf("cli_setatr failed (%s)\n", nt_errstr(status));
7377 status = cli_openx(cli1, fname, O_RDONLY, DENY_WRITE, &fnum1);
7378 if (!NT_STATUS_IS_OK(status)) {
7379 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
7383 /* This will fail - but the error should be ERRnoaccess, not ERRbadshare. */
7384 status = cli_openx(cli1, fname, O_RDWR, DENY_ALL, &fnum2);
7386 if (check_error(__LINE__, status, ERRDOS, ERRnoaccess,
7387 NT_STATUS_ACCESS_DENIED)) {
7388 printf("correct error code ERRDOS/ERRnoaccess returned\n");
7391 printf("finished open test 1\n");
7393 cli_close(cli1, fnum1);
7395 /* Now try not readonly and ensure ERRbadshare is returned. */
7397 cli_setatr(cli1, fname, 0, 0);
7399 status = cli_openx(cli1, fname, O_RDONLY, DENY_WRITE, &fnum1);
7400 if (!NT_STATUS_IS_OK(status)) {
7401 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
7405 /* This will fail - but the error should be ERRshare. */
7406 status = cli_openx(cli1, fname, O_RDWR, DENY_ALL, &fnum2);
7408 if (check_error(__LINE__, status, ERRDOS, ERRbadshare,
7409 NT_STATUS_SHARING_VIOLATION)) {
7410 printf("correct error code ERRDOS/ERRbadshare returned\n");
7413 status = cli_close(cli1, fnum1);
7414 if (!NT_STATUS_IS_OK(status)) {
7415 printf("close2 failed (%s)\n", nt_errstr(status));
7419 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7421 printf("finished open test 2\n");
7423 /* Test truncate open disposition on file opened for read. */
7424 status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
7425 if (!NT_STATUS_IS_OK(status)) {
7426 printf("(3) open (1) of %s failed (%s)\n", fname, nt_errstr(status));
7430 /* write 20 bytes. */
7432 memset(buf, '\0', 20);
7434 status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 0, 20, NULL);
7435 if (!NT_STATUS_IS_OK(status)) {
7436 printf("write failed (%s)\n", nt_errstr(status));
7440 status = cli_close(cli1, fnum1);
7441 if (!NT_STATUS_IS_OK(status)) {
7442 printf("(3) close1 failed (%s)\n", nt_errstr(status));
7446 /* Ensure size == 20. */
7447 status = cli_getatr(cli1, fname, NULL, &fsize, NULL);
7448 if (!NT_STATUS_IS_OK(status)) {
7449 printf("(3) getatr failed (%s)\n", nt_errstr(status));
7454 printf("(3) file size != 20\n");
7458 /* Now test if we can truncate a file opened for readonly. */
7459 status = cli_openx(cli1, fname, O_RDONLY|O_TRUNC, DENY_NONE, &fnum1);
7460 if (!NT_STATUS_IS_OK(status)) {
7461 printf("(3) open (2) of %s failed (%s)\n", fname, nt_errstr(status));
7465 status = cli_close(cli1, fnum1);
7466 if (!NT_STATUS_IS_OK(status)) {
7467 printf("close2 failed (%s)\n", nt_errstr(status));
7471 /* Ensure size == 0. */
7472 status = cli_getatr(cli1, fname, NULL, &fsize, NULL);
7473 if (!NT_STATUS_IS_OK(status)) {
7474 printf("(3) getatr failed (%s)\n", nt_errstr(status));
7479 printf("(3) file size != 0\n");
7482 printf("finished open test 3\n");
7484 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7486 printf("Do ctemp tests\n");
7487 status = cli_ctemp(cli1, talloc_tos(), "\\", &fnum1, &tmp_path);
7488 if (!NT_STATUS_IS_OK(status)) {
7489 printf("ctemp failed (%s)\n", nt_errstr(status));
7493 printf("ctemp gave path %s\n", tmp_path);
7494 status = cli_close(cli1, fnum1);
7495 if (!NT_STATUS_IS_OK(status)) {
7496 printf("close of temp failed (%s)\n", nt_errstr(status));
7499 status = cli_unlink(cli1, tmp_path, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7500 if (!NT_STATUS_IS_OK(status)) {
7501 printf("unlink of temp failed (%s)\n", nt_errstr(status));
7504 /* Test the non-io opens... */
7506 if (!torture_open_connection(&cli2, 1)) {
7510 cli_setatr(cli2, fname, 0, 0);
7511 cli_unlink(cli2, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7513 smbXcli_conn_set_sockopt(cli2->conn, sockops);
7515 printf("TEST #1 testing 2 non-io opens (no delete)\n");
7516 status = cli_ntcreate(cli1, fname, 0, FILE_READ_ATTRIBUTES,
7517 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7518 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
7519 if (!NT_STATUS_IS_OK(status)) {
7520 printf("TEST #1 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
7524 status = cli_ntcreate(cli2, fname, 0, FILE_READ_ATTRIBUTES,
7525 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7526 FILE_OPEN_IF, 0, 0, &fnum2, NULL);
7527 if (!NT_STATUS_IS_OK(status)) {
7528 printf("TEST #1 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
7532 status = cli_close(cli1, fnum1);
7533 if (!NT_STATUS_IS_OK(status)) {
7534 printf("TEST #1 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
7538 status = cli_close(cli2, fnum2);
7539 if (!NT_STATUS_IS_OK(status)) {
7540 printf("TEST #1 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
7544 printf("non-io open test #1 passed.\n");
7546 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7548 printf("TEST #2 testing 2 non-io opens (first with delete)\n");
7550 status = cli_ntcreate(cli1, fname, 0,
7551 DELETE_ACCESS|FILE_READ_ATTRIBUTES,
7552 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7553 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
7554 if (!NT_STATUS_IS_OK(status)) {
7555 printf("TEST #2 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
7559 status = cli_ntcreate(cli2, fname, 0, FILE_READ_ATTRIBUTES,
7560 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7561 FILE_OPEN_IF, 0, 0, &fnum2, NULL);
7562 if (!NT_STATUS_IS_OK(status)) {
7563 printf("TEST #2 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
7567 status = cli_close(cli1, fnum1);
7568 if (!NT_STATUS_IS_OK(status)) {
7569 printf("TEST #2 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
7573 status = cli_close(cli2, fnum2);
7574 if (!NT_STATUS_IS_OK(status)) {
7575 printf("TEST #2 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
7579 printf("non-io open test #2 passed.\n");
7581 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7583 printf("TEST #3 testing 2 non-io opens (second with delete)\n");
7585 status = cli_ntcreate(cli1, fname, 0, FILE_READ_ATTRIBUTES,
7586 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7587 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
7588 if (!NT_STATUS_IS_OK(status)) {
7589 printf("TEST #3 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
7593 status = cli_ntcreate(cli2, fname, 0,
7594 DELETE_ACCESS|FILE_READ_ATTRIBUTES,
7595 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7596 FILE_OPEN_IF, 0, 0, &fnum2, NULL);
7597 if (!NT_STATUS_IS_OK(status)) {
7598 printf("TEST #3 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
7602 status = cli_close(cli1, fnum1);
7603 if (!NT_STATUS_IS_OK(status)) {
7604 printf("TEST #3 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
7608 status = cli_close(cli2, fnum2);
7609 if (!NT_STATUS_IS_OK(status)) {
7610 printf("TEST #3 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
7614 printf("non-io open test #3 passed.\n");
7616 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7618 printf("TEST #4 testing 2 non-io opens (both with delete)\n");
7620 status = cli_ntcreate(cli1, fname, 0,
7621 DELETE_ACCESS|FILE_READ_ATTRIBUTES,
7622 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7623 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
7624 if (!NT_STATUS_IS_OK(status)) {
7625 printf("TEST #4 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
7629 status = cli_ntcreate(cli2, fname, 0,
7630 DELETE_ACCESS|FILE_READ_ATTRIBUTES,
7631 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7632 FILE_OPEN_IF, 0, 0, &fnum2, NULL);
7633 if (NT_STATUS_IS_OK(status)) {
7634 printf("TEST #4 open 2 of %s SUCCEEDED - should have failed (%s)\n", fname, nt_errstr(status));
7638 printf("TEST #4 open 2 of %s gave %s (correct error should be %s)\n", fname, nt_errstr(status), "sharing violation");
7640 status = cli_close(cli1, fnum1);
7641 if (!NT_STATUS_IS_OK(status)) {
7642 printf("TEST #4 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
7646 printf("non-io open test #4 passed.\n");
7648 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7650 printf("TEST #5 testing 2 non-io opens (both with delete - both with file share delete)\n");
7652 status = cli_ntcreate(cli1, fname, 0,
7653 DELETE_ACCESS|FILE_READ_ATTRIBUTES,
7654 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_DELETE,
7655 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
7656 if (!NT_STATUS_IS_OK(status)) {
7657 printf("TEST #5 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
7661 status = cli_ntcreate(cli2, fname, 0,
7662 DELETE_ACCESS|FILE_READ_ATTRIBUTES,
7663 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_DELETE,
7664 FILE_OPEN_IF, 0, 0, &fnum2, NULL);
7665 if (!NT_STATUS_IS_OK(status)) {
7666 printf("TEST #5 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
7670 status = cli_close(cli1, fnum1);
7671 if (!NT_STATUS_IS_OK(status)) {
7672 printf("TEST #5 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
7676 status = cli_close(cli2, fnum2);
7677 if (!NT_STATUS_IS_OK(status)) {
7678 printf("TEST #5 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
7682 printf("non-io open test #5 passed.\n");
7684 printf("TEST #6 testing 1 non-io open, one io open\n");
7686 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7688 status = cli_ntcreate(cli1, fname, 0, FILE_READ_DATA,
7689 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7690 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
7691 if (!NT_STATUS_IS_OK(status)) {
7692 printf("TEST #6 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
7696 status = cli_ntcreate(cli2, fname, 0, FILE_READ_ATTRIBUTES,
7697 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ,
7698 FILE_OPEN_IF, 0, 0, &fnum2, NULL);
7699 if (!NT_STATUS_IS_OK(status)) {
7700 printf("TEST #6 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
7704 status = cli_close(cli1, fnum1);
7705 if (!NT_STATUS_IS_OK(status)) {
7706 printf("TEST #6 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
7710 status = cli_close(cli2, fnum2);
7711 if (!NT_STATUS_IS_OK(status)) {
7712 printf("TEST #6 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
7716 printf("non-io open test #6 passed.\n");
7718 printf("TEST #7 testing 1 non-io open, one io open with delete\n");
7720 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7722 status = cli_ntcreate(cli1, fname, 0, FILE_READ_DATA,
7723 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7724 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
7725 if (!NT_STATUS_IS_OK(status)) {
7726 printf("TEST #7 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
7730 status = cli_ntcreate(cli2, fname, 0,
7731 DELETE_ACCESS|FILE_READ_ATTRIBUTES,
7732 FILE_ATTRIBUTE_NORMAL,
7733 FILE_SHARE_READ|FILE_SHARE_DELETE,
7734 FILE_OPEN_IF, 0, 0, &fnum2, NULL);
7735 if (NT_STATUS_IS_OK(status)) {
7736 printf("TEST #7 open 2 of %s SUCCEEDED - should have failed (%s)\n", fname, nt_errstr(status));
7740 printf("TEST #7 open 2 of %s gave %s (correct error should be %s)\n", fname, nt_errstr(status), "sharing violation");
7742 status = cli_close(cli1, fnum1);
7743 if (!NT_STATUS_IS_OK(status)) {
7744 printf("TEST #7 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
7748 printf("non-io open test #7 passed.\n");
7750 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7752 printf("TEST #8 testing open without WRITE_ATTRIBUTES, updating close write time.\n");
7753 status = cli_ntcreate(cli1, fname, 0, FILE_WRITE_DATA, FILE_ATTRIBUTE_NORMAL,
7754 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
7755 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
7756 if (!NT_STATUS_IS_OK(status)) {
7757 printf("TEST #8 open of %s failed (%s)\n", fname, nt_errstr(status));
7762 /* Write to ensure we have to update the file time. */
7763 status = cli_writeall(cli1, fnum1, 0, (const uint8_t *)"TEST DATA\n", 0, 10,
7765 if (!NT_STATUS_IS_OK(status)) {
7766 printf("TEST #8 cli_write failed: %s\n", nt_errstr(status));
7771 status = cli_close(cli1, fnum1);
7772 if (!NT_STATUS_IS_OK(status)) {
7773 printf("TEST #8 close of %s failed (%s)\n", fname, nt_errstr(status));
7779 if (!torture_close_connection(cli1)) {
7782 if (!torture_close_connection(cli2)) {
7789 NTSTATUS torture_setup_unix_extensions(struct cli_state *cli)
7791 uint16_t major, minor;
7792 uint32_t caplow, caphigh;
7795 if (!SERVER_HAS_UNIX_CIFS(cli)) {
7796 printf("Server doesn't support UNIX CIFS extensions.\n");
7797 return NT_STATUS_NOT_SUPPORTED;
7800 status = cli_unix_extensions_version(cli, &major, &minor, &caplow,
7802 if (!NT_STATUS_IS_OK(status)) {
7803 printf("Server didn't return UNIX CIFS extensions: %s\n",
7808 status = cli_set_unix_extensions_capabilities(cli, major, minor,
7810 if (!NT_STATUS_IS_OK(status)) {
7811 printf("Server doesn't support setting UNIX CIFS extensions: "
7812 "%s.\n", nt_errstr(status));
7816 return NT_STATUS_OK;
7820 Test POSIX open /mkdir calls.
7822 static bool run_simple_posix_open_test(int dummy)
7824 static struct cli_state *cli1;
7825 const char *fname = "posix:file";
7826 const char *hname = "posix:hlink";
7827 const char *sname = "posix:symlink";
7828 const char *dname = "posix:dir";
7830 char *target = NULL;
7831 uint16_t fnum1 = (uint16_t)-1;
7832 SMB_STRUCT_STAT sbuf;
7833 bool correct = false;
7836 const char *fname_windows = "windows_file";
7837 uint16_t fnum2 = (uint16_t)-1;
7840 printf("Starting simple POSIX open test\n");
7842 if (!torture_open_connection(&cli1, 0)) {
7846 smbXcli_conn_set_sockopt(cli1->conn, sockops);
7848 status = torture_setup_unix_extensions(cli1);
7849 if (!NT_STATUS_IS_OK(status)) {
7853 cli_setatr(cli1, fname, 0, 0);
7854 cli_posix_unlink(cli1, fname);
7855 cli_setatr(cli1, dname, 0, 0);
7856 cli_posix_rmdir(cli1, dname);
7857 cli_setatr(cli1, hname, 0, 0);
7858 cli_posix_unlink(cli1, hname);
7859 cli_setatr(cli1, sname, 0, 0);
7860 cli_posix_unlink(cli1, sname);
7861 cli_setatr(cli1, fname_windows, 0, 0);
7862 cli_posix_unlink(cli1, fname_windows);
7864 /* Create a directory. */
7865 status = cli_posix_mkdir(cli1, dname, 0777);
7866 if (!NT_STATUS_IS_OK(status)) {
7867 printf("POSIX mkdir of %s failed (%s)\n", dname, nt_errstr(status));
7871 status = cli_posix_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL,
7873 if (!NT_STATUS_IS_OK(status)) {
7874 printf("POSIX create of %s failed (%s)\n", fname, nt_errstr(status));
7878 /* Test ftruncate - set file size. */
7879 status = cli_ftruncate(cli1, fnum1, 1000);
7880 if (!NT_STATUS_IS_OK(status)) {
7881 printf("ftruncate failed (%s)\n", nt_errstr(status));
7885 /* Ensure st_size == 1000 */
7886 status = cli_posix_stat(cli1, fname, &sbuf);
7887 if (!NT_STATUS_IS_OK(status)) {
7888 printf("stat failed (%s)\n", nt_errstr(status));
7892 if (sbuf.st_ex_size != 1000) {
7893 printf("ftruncate - stat size (%u) != 1000\n", (unsigned int)sbuf.st_ex_size);
7897 /* Ensure st_mode == 0600 */
7898 if ((sbuf.st_ex_mode & 07777) != 0600) {
7899 printf("posix_open - bad permissions 0%o != 0600\n",
7900 (unsigned int)(sbuf.st_ex_mode & 07777));
7904 /* Test ftruncate - set file size back to zero. */
7905 status = cli_ftruncate(cli1, fnum1, 0);
7906 if (!NT_STATUS_IS_OK(status)) {
7907 printf("ftruncate failed (%s)\n", nt_errstr(status));
7911 status = cli_close(cli1, fnum1);
7912 if (!NT_STATUS_IS_OK(status)) {
7913 printf("close failed (%s)\n", nt_errstr(status));
7917 /* Now open the file again for read only. */
7918 status = cli_posix_open(cli1, fname, O_RDONLY, 0, &fnum1);
7919 if (!NT_STATUS_IS_OK(status)) {
7920 printf("POSIX open of %s failed (%s)\n", fname, nt_errstr(status));
7924 /* Now unlink while open. */
7925 status = cli_posix_unlink(cli1, fname);
7926 if (!NT_STATUS_IS_OK(status)) {
7927 printf("POSIX unlink of %s failed (%s)\n", fname, nt_errstr(status));
7931 status = cli_close(cli1, fnum1);
7932 if (!NT_STATUS_IS_OK(status)) {
7933 printf("close(2) failed (%s)\n", nt_errstr(status));
7937 /* Ensure the file has gone. */
7938 status = cli_posix_open(cli1, fname, O_RDONLY, 0, &fnum1);
7939 if (NT_STATUS_IS_OK(status)) {
7940 printf("POSIX open of %s succeeded, should have been deleted.\n", fname);
7944 /* Create again to test open with O_TRUNC. */
7945 status = cli_posix_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL, 0600, &fnum1);
7946 if (!NT_STATUS_IS_OK(status)) {
7947 printf("POSIX create of %s failed (%s)\n", fname, nt_errstr(status));
7951 /* Test ftruncate - set file size. */
7952 status = cli_ftruncate(cli1, fnum1, 1000);
7953 if (!NT_STATUS_IS_OK(status)) {
7954 printf("ftruncate failed (%s)\n", nt_errstr(status));
7958 /* Ensure st_size == 1000 */
7959 status = cli_posix_stat(cli1, fname, &sbuf);
7960 if (!NT_STATUS_IS_OK(status)) {
7961 printf("stat failed (%s)\n", nt_errstr(status));
7965 if (sbuf.st_ex_size != 1000) {
7966 printf("ftruncate - stat size (%u) != 1000\n", (unsigned int)sbuf.st_ex_size);
7970 status = cli_close(cli1, fnum1);
7971 if (!NT_STATUS_IS_OK(status)) {
7972 printf("close(2) failed (%s)\n", nt_errstr(status));
7976 /* Re-open with O_TRUNC. */
7977 status = cli_posix_open(cli1, fname, O_WRONLY|O_TRUNC, 0600, &fnum1);
7978 if (!NT_STATUS_IS_OK(status)) {
7979 printf("POSIX create of %s failed (%s)\n", fname, nt_errstr(status));
7983 /* Ensure st_size == 0 */
7984 status = cli_posix_stat(cli1, fname, &sbuf);
7985 if (!NT_STATUS_IS_OK(status)) {
7986 printf("stat failed (%s)\n", nt_errstr(status));
7990 if (sbuf.st_ex_size != 0) {
7991 printf("O_TRUNC - stat size (%u) != 0\n", (unsigned int)sbuf.st_ex_size);
7995 status = cli_close(cli1, fnum1);
7996 if (!NT_STATUS_IS_OK(status)) {
7997 printf("close failed (%s)\n", nt_errstr(status));
8001 status = cli_posix_unlink(cli1, fname);
8002 if (!NT_STATUS_IS_OK(status)) {
8003 printf("POSIX unlink of %s failed (%s)\n", fname, nt_errstr(status));
8007 status = cli_posix_open(cli1, dname, O_RDONLY, 0, &fnum1);
8008 if (!NT_STATUS_IS_OK(status)) {
8009 printf("POSIX open directory O_RDONLY of %s failed (%s)\n",
8010 dname, nt_errstr(status));
8014 cli_close(cli1, fnum1);
8016 /* What happens when we try and POSIX open a directory for write ? */
8017 status = cli_posix_open(cli1, dname, O_RDWR, 0, &fnum1);
8018 if (NT_STATUS_IS_OK(status)) {
8019 printf("POSIX open of directory %s succeeded, "
8020 "should have failed.\n",
8024 if (!check_both_error(__LINE__, status, ERRDOS, EISDIR,
8025 NT_STATUS_FILE_IS_A_DIRECTORY)) {
8030 /* Create the file. */
8031 status = cli_posix_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL,
8033 if (!NT_STATUS_IS_OK(status)) {
8034 printf("POSIX create of %s failed (%s)\n", fname, nt_errstr(status));
8038 /* Write some data into it. */
8039 status = cli_writeall(cli1, fnum1, 0, (const uint8_t *)"TEST DATA\n", 0, 10,
8041 if (!NT_STATUS_IS_OK(status)) {
8042 printf("cli_write failed: %s\n", nt_errstr(status));
8046 cli_close(cli1, fnum1);
8048 /* Now create a hardlink. */
8049 status = cli_posix_hardlink(cli1, fname, hname);
8050 if (!NT_STATUS_IS_OK(status)) {
8051 printf("POSIX hardlink of %s failed (%s)\n", hname, nt_errstr(status));
8055 /* Now create a symlink. */
8056 status = cli_posix_symlink(cli1, fname, sname);
8057 if (!NT_STATUS_IS_OK(status)) {
8058 printf("POSIX symlink of %s failed (%s)\n", sname, nt_errstr(status));
8062 /* Open the hardlink for read. */
8063 status = cli_posix_open(cli1, hname, O_RDONLY, 0, &fnum1);
8064 if (!NT_STATUS_IS_OK(status)) {
8065 printf("POSIX open of %s failed (%s)\n", hname, nt_errstr(status));
8069 status = cli_read(cli1, fnum1, buf, 0, 10, &nread);
8070 if (!NT_STATUS_IS_OK(status)) {
8071 printf("POSIX read of %s failed (%s)\n", hname,
8074 } else if (nread != 10) {
8075 printf("POSIX read of %s failed. Received %ld, expected %d\n",
8076 hname, (unsigned long)nread, 10);
8080 if (memcmp(buf, "TEST DATA\n", 10)) {
8081 printf("invalid data read from hardlink\n");
8085 /* Do a POSIX lock/unlock. */
8086 status = cli_posix_lock(cli1, fnum1, 0, 100, true, READ_LOCK);
8087 if (!NT_STATUS_IS_OK(status)) {
8088 printf("POSIX lock failed %s\n", nt_errstr(status));
8092 /* Punch a hole in the locked area. */
8093 status = cli_posix_unlock(cli1, fnum1, 10, 80);
8094 if (!NT_STATUS_IS_OK(status)) {
8095 printf("POSIX unlock failed %s\n", nt_errstr(status));
8099 cli_close(cli1, fnum1);
8101 /* Open the symlink for read - this should fail. A POSIX
8102 client should not be doing opens on a symlink. */
8103 status = cli_posix_open(cli1, sname, O_RDONLY, 0, &fnum1);
8104 if (NT_STATUS_IS_OK(status)) {
8105 printf("POSIX open of %s succeeded (should have failed)\n", sname);
8108 ok = check_both_error(
8109 __LINE__, status, ERRDOS, ERRbadpath,
8110 NT_STATUS_OBJECT_NAME_NOT_FOUND);
8112 printf("POSIX open of %s should have failed "
8113 "with NT_STATUS_OBJECT_NAME_NOT_FOUND, "
8114 "failed with %s instead.\n",
8115 sname, nt_errstr(status));
8119 status = cli_readlink(cli1, sname, talloc_tos(), &target, NULL, NULL);
8120 if (!NT_STATUS_IS_OK(status)) {
8121 printf("POSIX readlink on %s failed (%s)\n", sname, nt_errstr(status));
8125 if (strcmp(target, fname) != 0) {
8126 printf("POSIX readlink on %s failed to match name %s (read %s)\n",
8127 sname, fname, target);
8131 status = cli_posix_rmdir(cli1, dname);
8132 if (!NT_STATUS_IS_OK(status)) {
8133 printf("POSIX rmdir failed (%s)\n", nt_errstr(status));
8137 /* Check directory opens with a specific permission. */
8138 status = cli_posix_mkdir(cli1, dname, 0700);
8139 if (!NT_STATUS_IS_OK(status)) {
8140 printf("POSIX mkdir of %s failed (%s)\n", dname, nt_errstr(status));
8144 /* Ensure st_mode == 0700 */
8145 status = cli_posix_stat(cli1, dname, &sbuf);
8146 if (!NT_STATUS_IS_OK(status)) {
8147 printf("stat failed (%s)\n", nt_errstr(status));
8151 if ((sbuf.st_ex_mode & 07777) != 0700) {
8152 printf("posix_mkdir - bad permissions 0%o != 0700\n",
8153 (unsigned int)(sbuf.st_ex_mode & 07777));
8158 * Now create a Windows file, and attempt a POSIX unlink.
8159 * This should fail with a sharing violation but due to:
8161 * [Bug 9571] Unlink after open causes smbd to panic
8163 * ensure we've fixed the lock ordering violation.
8166 status = cli_ntcreate(cli1, fname_windows, 0,
8167 FILE_READ_DATA|FILE_WRITE_DATA, 0,
8168 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
8170 0x0, 0x0, &fnum2, NULL);
8171 if (!NT_STATUS_IS_OK(status)) {
8172 printf("Windows create of %s failed (%s)\n", fname_windows,
8177 /* Now try posix_unlink. */
8178 status = cli_posix_unlink(cli1, fname_windows);
8179 if (!NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
8180 printf("POSIX unlink of %s should fail "
8181 "with NT_STATUS_SHARING_VIOLATION "
8182 "got %s instead !\n",
8188 cli_close(cli1, fnum2);
8190 printf("Simple POSIX open test passed\n");
8195 if (fnum1 != (uint16_t)-1) {
8196 cli_close(cli1, fnum1);
8197 fnum1 = (uint16_t)-1;
8200 if (fnum2 != (uint16_t)-1) {
8201 cli_close(cli1, fnum2);
8202 fnum2 = (uint16_t)-1;
8205 cli_setatr(cli1, sname, 0, 0);
8206 cli_posix_unlink(cli1, sname);
8207 cli_setatr(cli1, hname, 0, 0);
8208 cli_posix_unlink(cli1, hname);
8209 cli_setatr(cli1, fname, 0, 0);
8210 cli_posix_unlink(cli1, fname);
8211 cli_setatr(cli1, dname, 0, 0);
8212 cli_posix_rmdir(cli1, dname);
8213 cli_setatr(cli1, fname_windows, 0, 0);
8214 cli_posix_unlink(cli1, fname_windows);
8216 if (!torture_close_connection(cli1)) {
8224 Test POSIX and Windows ACLs are rejected on symlinks.
8226 static bool run_acl_symlink_test(int dummy)
8228 static struct cli_state *cli;
8229 const char *fname = "posix_file";
8230 const char *sname = "posix_symlink";
8231 uint16_t fnum = (uint16_t)-1;
8232 bool correct = false;
8234 char *posix_acl = NULL;
8235 size_t posix_acl_len = 0;
8236 char *posix_acl_sym = NULL;
8237 size_t posix_acl_len_sym = 0;
8238 struct security_descriptor *sd = NULL;
8239 TALLOC_CTX *frame = NULL;
8241 frame = talloc_stackframe();
8243 printf("Starting acl symlink test\n");
8245 if (!torture_open_connection(&cli, 0)) {
8250 smbXcli_conn_set_sockopt(cli->conn, sockops);
8252 status = torture_setup_unix_extensions(cli);
8253 if (!NT_STATUS_IS_OK(status)) {
8258 cli_setatr(cli, fname, 0, 0);
8259 cli_posix_unlink(cli, fname);
8260 cli_setatr(cli, sname, 0, 0);
8261 cli_posix_unlink(cli, sname);
8263 status = cli_ntcreate(cli,
8266 READ_CONTROL_ACCESS,
8268 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
8275 if (!NT_STATUS_IS_OK(status)) {
8276 printf("cli_ntcreate of %s failed (%s)\n",
8282 /* Get the Windows ACL on the file. */
8283 status = cli_query_secdesc(cli,
8287 if (!NT_STATUS_IS_OK(status)) {
8288 printf("cli_query_secdesc failed (%s)\n",
8293 /* Get the POSIX ACL on the file. */
8294 status = cli_posix_getacl(cli,
8300 if (!NT_STATUS_IS_OK(status)) {
8301 printf("cli_posix_getacl failed (%s)\n",
8306 status = cli_close(cli, fnum);
8307 if (!NT_STATUS_IS_OK(status)) {
8308 printf("close failed (%s)\n", nt_errstr(status));
8311 fnum = (uint16_t)-1;
8313 /* Now create a symlink. */
8314 status = cli_posix_symlink(cli, fname, sname);
8315 if (!NT_STATUS_IS_OK(status)) {
8316 printf("cli_posix_symlink of %s -> %s failed (%s)\n",
8323 /* Open a handle on the symlink for SD set/get should fail. */
8324 status = cli_ntcreate(cli,
8327 READ_CONTROL_ACCESS|SEC_STD_WRITE_DAC,
8329 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
8336 if (NT_STATUS_IS_OK(status)) {
8337 printf("Symlink open for getsd/setsd of %s "
8338 "succeeded (should fail)\n",
8343 /* Try a stat-open on the symlink, should also fail. */
8344 status = cli_ntcreate(cli,
8347 FILE_READ_ATTRIBUTES|FILE_WRITE_ATTRIBUTES,
8349 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
8356 if (NT_STATUS_IS_OK(status)) {
8357 printf("Stat-open of symlink succeeded (should fail)\n");
8361 /* Get the POSIX ACL on the symlink pathname. Should fail. */
8362 status = cli_posix_getacl(cli,
8368 if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
8369 printf("cli_posix_getacl on a symlink gave %s. "
8370 "Should be NT_STATUS_ACCESS_DENIED.\n",
8375 /* Set the POSIX ACL on the symlink pathname. Should fail. */
8376 status = cli_posix_setacl(cli,
8381 if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
8382 printf("cli_posix_setacl on a symlink gave %s. "
8383 "Should be NT_STATUS_ACCESS_DENIED.\n",
8388 printf("ACL symlink test passed\n");
8393 if (fnum != (uint16_t)-1) {
8394 cli_close(cli, fnum);
8395 fnum = (uint16_t)-1;
8398 cli_setatr(cli, sname, 0, 0);
8399 cli_posix_unlink(cli, sname);
8400 cli_setatr(cli, fname, 0, 0);
8401 cli_posix_unlink(cli, fname);
8403 if (!torture_close_connection(cli)) {
8412 Test POSIX can delete a file containing streams.
8414 static bool run_posix_stream_delete(int dummy)
8416 struct cli_state *cli1 = NULL;
8417 struct cli_state *cli2 = NULL;
8418 const char *fname = "streamfile";
8419 const char *stream_fname = "streamfile:Zone.Identifier:$DATA";
8420 uint16_t fnum1 = (uint16_t)-1;
8421 bool correct = false;
8423 TALLOC_CTX *frame = NULL;
8425 frame = talloc_stackframe();
8427 printf("Starting POSIX stream delete test\n");
8429 if (!torture_open_connection(&cli1, 0) ||
8430 !torture_open_connection(&cli2, 1)) {
8435 smbXcli_conn_set_sockopt(cli1->conn, sockops);
8436 smbXcli_conn_set_sockopt(cli2->conn, sockops);
8438 status = torture_setup_unix_extensions(cli2);
8439 if (!NT_STATUS_IS_OK(status)) {
8443 cli_setatr(cli1, fname, 0, 0);
8444 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
8446 /* Create the file. */
8447 status = cli_ntcreate(cli1,
8450 READ_CONTROL_ACCESS,
8452 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
8459 if (!NT_STATUS_IS_OK(status)) {
8460 printf("cli_ntcreate of %s failed (%s)\n",
8466 status = cli_close(cli1, fnum1);
8467 if (!NT_STATUS_IS_OK(status)) {
8468 printf("cli_close of %s failed (%s)\n",
8473 fnum1 = (uint16_t)-1;
8475 /* Now create the stream. */
8476 status = cli_ntcreate(cli1,
8481 FILE_SHARE_READ|FILE_SHARE_WRITE,
8488 if (!NT_STATUS_IS_OK(status)) {
8489 printf("cli_ntcreate of %s failed (%s)\n",
8495 /* Leave the stream handle open... */
8497 /* POSIX unlink should fail. */
8498 status = cli_posix_unlink(cli2, fname);
8499 if (NT_STATUS_IS_OK(status)) {
8500 printf("cli_posix_unlink of %s succeeded, should have failed\n",
8505 if (!NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
8506 printf("cli_posix_unlink of %s failed with (%s) "
8507 "should have been NT_STATUS_SHARING_VIOLATION\n",
8513 /* Close the stream handle. */
8514 status = cli_close(cli1, fnum1);
8515 if (!NT_STATUS_IS_OK(status)) {
8516 printf("cli_close of %s failed (%s)\n",
8521 fnum1 = (uint16_t)-1;
8523 /* POSIX unlink after stream handle closed should succeed. */
8524 status = cli_posix_unlink(cli2, fname);
8525 if (!NT_STATUS_IS_OK(status)) {
8526 printf("cli_posix_unlink of %s failed (%s)\n",
8532 printf("POSIX stream delete test passed\n");
8537 if (fnum1 != (uint16_t)-1) {
8538 cli_close(cli1, fnum1);
8539 fnum1 = (uint16_t)-1;
8542 cli_setatr(cli1, fname, 0, 0);
8543 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
8545 if (!torture_close_connection(cli1)) {
8548 if (!torture_close_connection(cli2)) {
8557 Test setting EA's are rejected on symlinks.
8559 static bool run_ea_symlink_test(int dummy)
8561 static struct cli_state *cli;
8562 const char *fname = "posix_file_ea";
8563 const char *sname = "posix_symlink_ea";
8564 const char *ea_name = "testea_name";
8565 const char *ea_value = "testea_value";
8566 uint16_t fnum = (uint16_t)-1;
8567 bool correct = false;
8570 struct ea_struct *eas = NULL;
8571 TALLOC_CTX *frame = NULL;
8573 frame = talloc_stackframe();
8575 printf("Starting EA symlink test\n");
8577 if (!torture_open_connection(&cli, 0)) {
8582 smbXcli_conn_set_sockopt(cli->conn, sockops);
8584 status = torture_setup_unix_extensions(cli);
8585 if (!NT_STATUS_IS_OK(status)) {
8590 cli_setatr(cli, fname, 0, 0);
8591 cli_posix_unlink(cli, fname);
8592 cli_setatr(cli, sname, 0, 0);
8593 cli_posix_unlink(cli, sname);
8595 status = cli_ntcreate(cli,
8598 READ_CONTROL_ACCESS,
8600 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
8607 if (!NT_STATUS_IS_OK(status)) {
8608 printf("cli_ntcreate of %s failed (%s)\n",
8614 status = cli_close(cli, fnum);
8615 if (!NT_STATUS_IS_OK(status)) {
8616 printf("close failed (%s)\n",
8620 fnum = (uint16_t)-1;
8622 /* Set an EA on the path. */
8623 status = cli_set_ea_path(cli,
8627 strlen(ea_value)+1);
8629 if (!NT_STATUS_IS_OK(status)) {
8630 printf("cli_set_ea_path failed (%s)\n",
8635 /* Now create a symlink. */
8636 status = cli_posix_symlink(cli, fname, sname);
8637 if (!NT_STATUS_IS_OK(status)) {
8638 printf("cli_posix_symlink of %s -> %s failed (%s)\n",
8645 /* Get the EA list on the path. Should return value set. */
8646 status = cli_get_ea_list_path(cli,
8652 if (!NT_STATUS_IS_OK(status)) {
8653 printf("cli_get_ea_list_path failed (%s)\n",
8658 /* Ensure the EA we set is there. */
8659 for (i=0; i<num_eas; i++) {
8660 if (strcmp(eas[i].name, ea_name) == 0 &&
8661 eas[i].value.length == strlen(ea_value)+1 &&
8662 memcmp(eas[i].value.data,
8664 eas[i].value.length) == 0) {
8670 printf("Didn't find EA on pathname %s\n",
8678 /* Get the EA list on the symlink. Should return empty list. */
8679 status = cli_get_ea_list_path(cli,
8685 if (!NT_STATUS_IS_OK(status)) {
8686 printf("cli_get_ea_list_path failed (%s)\n",
8692 printf("cli_get_ea_list_path failed (%s)\n",
8697 /* Set an EA on the symlink. Should fail. */
8698 status = cli_set_ea_path(cli,
8702 strlen(ea_value)+1);
8704 if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
8705 printf("cli_set_ea_path on a symlink gave %s. "
8706 "Should be NT_STATUS_ACCESS_DENIED.\n",
8711 printf("EA symlink test passed\n");
8716 if (fnum != (uint16_t)-1) {
8717 cli_close(cli, fnum);
8718 fnum = (uint16_t)-1;
8721 cli_setatr(cli, sname, 0, 0);
8722 cli_posix_unlink(cli, sname);
8723 cli_setatr(cli, fname, 0, 0);
8724 cli_posix_unlink(cli, fname);
8726 if (!torture_close_connection(cli)) {
8735 Test POSIX locks are OFD-locks.
8737 static bool run_posix_ofd_lock_test(int dummy)
8739 static struct cli_state *cli;
8740 const char *fname = "posix_file";
8741 uint16_t fnum1 = (uint16_t)-1;
8742 uint16_t fnum2 = (uint16_t)-1;
8743 bool correct = false;
8745 TALLOC_CTX *frame = NULL;
8747 frame = talloc_stackframe();
8749 printf("Starting POSIX ofd-lock test\n");
8751 if (!torture_open_connection(&cli, 0)) {
8756 smbXcli_conn_set_sockopt(cli->conn, sockops);
8758 status = torture_setup_unix_extensions(cli);
8759 if (!NT_STATUS_IS_OK(status)) {
8764 cli_setatr(cli, fname, 0, 0);
8765 cli_posix_unlink(cli, fname);
8767 /* Open the file twice. */
8768 status = cli_posix_open(cli, fname, O_RDWR|O_CREAT|O_EXCL,
8770 if (!NT_STATUS_IS_OK(status)) {
8771 printf("First POSIX open of %s failed\n", fname);
8775 status = cli_posix_open(cli, fname, O_RDWR, 0, &fnum2);
8776 if (!NT_STATUS_IS_OK(status)) {
8777 printf("First POSIX open of %s failed\n", fname);
8781 /* Set a 0-50 lock on fnum1. */
8782 status = cli_posix_lock(cli, fnum1, 0, 50, false, WRITE_LOCK);
8783 if (!NT_STATUS_IS_OK(status)) {
8784 printf("POSIX lock (1) failed %s\n", nt_errstr(status));
8788 /* Set a 60-100 lock on fnum2. */
8789 status = cli_posix_lock(cli, fnum2, 60, 100, false, WRITE_LOCK);
8790 if (!NT_STATUS_IS_OK(status)) {
8791 printf("POSIX lock (2) failed %s\n", nt_errstr(status));
8795 /* close fnum1 - 0-50 lock should go away. */
8796 status = cli_close(cli, fnum1);
8797 if (!NT_STATUS_IS_OK(status)) {
8798 printf("close failed (%s)\n",
8802 fnum1 = (uint16_t)-1;
8804 /* Change the lock context. */
8805 cli_setpid(cli, cli_getpid(cli) + 1);
8807 /* Re-open fnum1. */
8808 status = cli_posix_open(cli, fname, O_RDWR, 0, &fnum1);
8809 if (!NT_STATUS_IS_OK(status)) {
8810 printf("Third POSIX open of %s failed\n", fname);
8814 /* 60-100 lock should still be there. */
8815 status = cli_posix_lock(cli, fnum1, 60, 100, false, WRITE_LOCK);
8816 if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
8817 printf("POSIX lock 60-100 not there %s\n", nt_errstr(status));
8821 /* 0-50 lock should be gone. */
8822 status = cli_posix_lock(cli, fnum1, 0, 50, false, WRITE_LOCK);
8823 if (!NT_STATUS_IS_OK(status)) {
8824 printf("POSIX lock 0-50 failed %s\n", nt_errstr(status));
8828 printf("POSIX OFD lock test passed\n");
8833 if (fnum1 != (uint16_t)-1) {
8834 cli_close(cli, fnum1);
8835 fnum1 = (uint16_t)-1;
8837 if (fnum2 != (uint16_t)-1) {
8838 cli_close(cli, fnum2);
8839 fnum2 = (uint16_t)-1;
8842 cli_setatr(cli, fname, 0, 0);
8843 cli_posix_unlink(cli, fname);
8845 if (!torture_close_connection(cli)) {
8853 struct posix_blocking_state {
8854 struct tevent_context *ev;
8855 struct cli_state *cli1;
8857 struct cli_state *cli2;
8863 static void posix_blocking_locked(struct tevent_req *subreq);
8864 static void posix_blocking_gotblocked(struct tevent_req *subreq);
8865 static void posix_blocking_gotecho(struct tevent_req *subreq);
8866 static void posix_blocking_unlocked(struct tevent_req *subreq);
8868 static struct tevent_req *posix_blocking_send(
8869 TALLOC_CTX *mem_ctx,
8870 struct tevent_context *ev,
8871 struct cli_state *cli1,
8873 struct cli_state *cli2,
8876 struct tevent_req *req = NULL, *subreq = NULL;
8877 struct posix_blocking_state *state = NULL;
8879 req = tevent_req_create(mem_ctx, &state, struct posix_blocking_state);
8885 state->fnum1 = fnum1;
8887 state->fnum2 = fnum2;
8889 subreq = cli_posix_lock_send(
8898 if (tevent_req_nomem(subreq, req)) {
8899 return tevent_req_post(req, ev);
8901 tevent_req_set_callback(subreq, posix_blocking_locked, req);
8905 static void posix_blocking_locked(struct tevent_req *subreq)
8907 struct tevent_req *req = tevent_req_callback_data(
8908 subreq, struct tevent_req);
8909 struct posix_blocking_state *state = tevent_req_data(
8910 req, struct posix_blocking_state);
8913 status = cli_posix_lock_recv(subreq);
8914 TALLOC_FREE(subreq);
8915 if (tevent_req_nterror(req, status)) {
8919 subreq = cli_posix_lock_send(
8928 if (tevent_req_nomem(subreq, req)) {
8931 tevent_req_set_callback(subreq, posix_blocking_gotblocked, req);
8933 /* Make sure the blocking request is delivered */
8934 subreq = cli_echo_send(
8939 (DATA_BLOB) { .data = (uint8_t *)state, .length = 1 });
8940 if (tevent_req_nomem(subreq, req)) {
8943 tevent_req_set_callback(subreq, posix_blocking_gotecho, req);
8946 static void posix_blocking_gotblocked(struct tevent_req *subreq)
8948 struct tevent_req *req = tevent_req_callback_data(
8949 subreq, struct tevent_req);
8950 struct posix_blocking_state *state = tevent_req_data(
8951 req, struct posix_blocking_state);
8954 status = cli_posix_lock_recv(subreq);
8955 TALLOC_FREE(subreq);
8956 if (tevent_req_nterror(req, status)) {
8959 if (!state->gotecho) {
8960 printf("blocked req got through before echo\n");
8961 tevent_req_nterror(req, NT_STATUS_INVALID_LOCK_SEQUENCE);
8964 tevent_req_done(req);
8967 static void posix_blocking_gotecho(struct tevent_req *subreq)
8969 struct tevent_req *req = tevent_req_callback_data(
8970 subreq, struct tevent_req);
8971 struct posix_blocking_state *state = tevent_req_data(
8972 req, struct posix_blocking_state);
8975 status = cli_echo_recv(subreq);
8976 TALLOC_FREE(subreq);
8977 if (tevent_req_nterror(req, status)) {
8980 if (state->gotblocked) {
8981 printf("blocked req got through before echo\n");
8982 tevent_req_nterror(req, NT_STATUS_INVALID_LOCK_SEQUENCE);
8985 state->gotecho = true;
8987 subreq = cli_posix_lock_send(
8996 if (tevent_req_nomem(subreq, req)) {
8999 tevent_req_set_callback(subreq, posix_blocking_unlocked, req);
9002 static void posix_blocking_unlocked(struct tevent_req *subreq)
9004 struct tevent_req *req = tevent_req_callback_data(
9005 subreq, struct tevent_req);
9008 status = cli_posix_lock_recv(subreq);
9009 TALLOC_FREE(subreq);
9010 if (tevent_req_nterror(req, status)) {
9013 /* tevent_req_done in posix_blocking_gotlocked */
9016 static NTSTATUS posix_blocking_recv(struct tevent_req *req)
9018 return tevent_req_simple_recv_ntstatus(req);
9021 static bool run_posix_blocking_lock(int dummy)
9023 struct tevent_context *ev = NULL;
9024 struct cli_state *cli1 = NULL, *cli2 = NULL;
9025 const char *fname = "posix_blocking";
9026 uint16_t fnum1 = UINT16_MAX, fnum2 = UINT16_MAX;
9027 struct tevent_req *req = NULL;
9032 printf("Starting posix blocking lock test\n");
9034 ev = samba_tevent_context_init(NULL);
9039 ok = torture_open_connection(&cli1, 0);
9043 ok = torture_open_connection(&cli2, 0);
9048 smbXcli_conn_set_sockopt(cli1->conn, sockops);
9050 status = torture_setup_unix_extensions(cli1);
9051 if (!NT_STATUS_IS_OK(status)) {
9055 status = torture_setup_unix_extensions(cli2);
9056 if (!NT_STATUS_IS_OK(status)) {
9060 cli_setatr(cli1, fname, 0, 0);
9061 cli_posix_unlink(cli1, fname);
9063 status = cli_posix_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL,
9065 if (!NT_STATUS_IS_OK(status)) {
9066 printf("First POSIX open of %s failed: %s\n",
9072 status = cli_posix_open(cli2, fname, O_RDWR, 0600, &fnum2);
9073 if (!NT_STATUS_IS_OK(status)) {
9074 printf("Second POSIX open of %s failed: %s\n",
9080 req = posix_blocking_send(ev, ev, cli1, fnum1, cli2, fnum2);
9082 printf("cli_posix_blocking failed\n");
9086 ok = tevent_req_poll_ntstatus(req, ev, &status);
9088 printf("tevent_req_poll_ntstatus failed: %s\n",
9092 status = posix_blocking_recv(req);
9094 if (!NT_STATUS_IS_OK(status)) {
9095 printf("posix_blocking_recv returned %s\n",
9103 if (fnum1 != UINT16_MAX) {
9104 cli_close(cli1, fnum1);
9107 if (fnum2 != UINT16_MAX) {
9108 cli_close(cli2, fnum2);
9113 cli_setatr(cli1, fname, 0, 0);
9114 cli_posix_unlink(cli1, fname);
9120 ok &= torture_close_connection(cli1);
9124 ok &= torture_close_connection(cli2);
9136 Test POSIX mkdir is case-sensitive.
9138 static bool run_posix_mkdir_test(int dummy)
9140 static struct cli_state *cli;
9141 const char *fname_foo = "POSIX_foo";
9142 const char *fname_foo_Foo = "POSIX_foo/Foo";
9143 const char *fname_foo_foo = "POSIX_foo/foo";
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 bool correct = false;
9149 TALLOC_CTX *frame = NULL;
9150 uint16_t fnum = (uint16_t)-1;
9152 frame = talloc_stackframe();
9154 printf("Starting POSIX mkdir test\n");
9156 if (!torture_open_connection(&cli, 0)) {
9161 smbXcli_conn_set_sockopt(cli->conn, sockops);
9163 status = torture_setup_unix_extensions(cli);
9164 if (!NT_STATUS_IS_OK(status)) {
9169 cli_posix_rmdir(cli, fname_foo_foo);
9170 cli_posix_rmdir(cli, fname_foo_Foo);
9171 cli_posix_rmdir(cli, fname_foo);
9173 cli_posix_rmdir(cli, fname_Foo_foo);
9174 cli_posix_rmdir(cli, fname_Foo_Foo);
9175 cli_posix_rmdir(cli, fname_Foo);
9178 * Create a file POSIX_foo then try
9179 * and use it in a directory path by
9180 * doing mkdir POSIX_foo/bar.
9181 * The mkdir should fail with
9182 * NT_STATUS_OBJECT_PATH_NOT_FOUND
9185 status = cli_posix_open(cli,
9190 if (!NT_STATUS_IS_OK(status)) {
9191 printf("cli_posix_open of %s failed error %s\n",
9197 status = cli_posix_mkdir(cli, fname_foo_foo, 0777);
9198 if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_PATH_NOT_FOUND)) {
9199 printf("cli_posix_mkdir of %s should fail with "
9200 "NT_STATUS_OBJECT_PATH_NOT_FOUND got "
9207 status = cli_close(cli, fnum);
9208 if (!NT_STATUS_IS_OK(status)) {
9209 printf("cli_close failed %s\n", nt_errstr(status));
9212 fnum = (uint16_t)-1;
9214 status = cli_posix_unlink(cli, fname_foo);
9215 if (!NT_STATUS_IS_OK(status)) {
9216 printf("cli_posix_unlink of %s failed error %s\n",
9223 * Now we've deleted everything, posix_mkdir, posix_rmdir,
9224 * posix_open, posix_unlink, on
9225 * POSIX_foo/foo should return NT_STATUS_OBJECT_PATH_NOT_FOUND
9226 * not silently create POSIX_foo/foo.
9229 status = cli_posix_mkdir(cli, fname_foo_foo, 0777);
9230 if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_PATH_NOT_FOUND)) {
9231 printf("cli_posix_mkdir of %s should fail with "
9232 "NT_STATUS_OBJECT_PATH_NOT_FOUND got "
9239 status = cli_posix_rmdir(cli, fname_foo_foo);
9240 if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_PATH_NOT_FOUND)) {
9241 printf("cli_posix_rmdir of %s should fail with "
9242 "NT_STATUS_OBJECT_PATH_NOT_FOUND got "
9249 status = cli_posix_open(cli,
9254 if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_PATH_NOT_FOUND)) {
9255 printf("cli_posix_open of %s should fail with "
9256 "NT_STATUS_OBJECT_PATH_NOT_FOUND got "
9263 status = cli_posix_unlink(cli, fname_foo_foo);
9264 if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_PATH_NOT_FOUND)) {
9265 printf("cli_posix_unlink of %s should fail with "
9266 "NT_STATUS_OBJECT_PATH_NOT_FOUND got "
9273 status = cli_posix_mkdir(cli, fname_foo, 0777);
9274 if (!NT_STATUS_IS_OK(status)) {
9275 printf("cli_posix_mkdir of %s failed\n", fname_foo);
9279 status = cli_posix_mkdir(cli, fname_Foo, 0777);
9280 if (!NT_STATUS_IS_OK(status)) {
9281 printf("cli_posix_mkdir of %s failed\n", fname_Foo);
9285 status = cli_posix_mkdir(cli, fname_foo_foo, 0777);
9286 if (!NT_STATUS_IS_OK(status)) {
9287 printf("cli_posix_mkdir of %s failed\n", fname_foo_foo);
9291 status = cli_posix_mkdir(cli, fname_foo_Foo, 0777);
9292 if (!NT_STATUS_IS_OK(status)) {
9293 printf("cli_posix_mkdir of %s failed\n", fname_foo_Foo);
9297 status = cli_posix_mkdir(cli, fname_Foo_foo, 0777);
9298 if (!NT_STATUS_IS_OK(status)) {
9299 printf("cli_posix_mkdir of %s failed\n", fname_Foo_foo);
9303 status = cli_posix_mkdir(cli, fname_Foo_Foo, 0777);
9304 if (!NT_STATUS_IS_OK(status)) {
9305 printf("cli_posix_mkdir of %s failed\n", fname_Foo_Foo);
9309 printf("POSIX mkdir test passed\n");
9314 if (fnum != (uint16_t)-1) {
9315 cli_close(cli, fnum);
9316 fnum = (uint16_t)-1;
9319 cli_posix_rmdir(cli, fname_foo_foo);
9320 cli_posix_rmdir(cli, fname_foo_Foo);
9321 cli_posix_rmdir(cli, fname_foo);
9323 cli_posix_rmdir(cli, fname_Foo_foo);
9324 cli_posix_rmdir(cli, fname_Foo_Foo);
9325 cli_posix_rmdir(cli, fname_Foo);
9327 if (!torture_close_connection(cli)) {
9335 struct posix_acl_oplock_state {
9336 struct tevent_context *ev;
9337 struct cli_state *cli;
9343 static void posix_acl_oplock_got_break(struct tevent_req *req)
9345 struct posix_acl_oplock_state *state = tevent_req_callback_data(
9346 req, struct posix_acl_oplock_state);
9351 status = cli_smb_oplock_break_waiter_recv(req, &fnum, &level);
9353 if (!NT_STATUS_IS_OK(status)) {
9354 printf("cli_smb_oplock_break_waiter_recv returned %s\n",
9358 *state->got_break = true;
9360 req = cli_oplock_ack_send(state, state->ev, state->cli, fnum,
9363 printf("cli_oplock_ack_send failed\n");
9368 static void posix_acl_oplock_got_acl(struct tevent_req *req)
9370 struct posix_acl_oplock_state *state = tevent_req_callback_data(
9371 req, struct posix_acl_oplock_state);
9372 size_t ret_size = 0;
9373 char *ret_data = NULL;
9375 state->status = cli_posix_getacl_recv(req,
9380 if (!NT_STATUS_IS_OK(state->status)) {
9381 printf("cli_posix_getacl_recv returned %s\n",
9382 nt_errstr(state->status));
9384 *state->acl_ret = true;
9387 static bool run_posix_acl_oplock_test(int dummy)
9389 struct tevent_context *ev;
9390 struct cli_state *cli1, *cli2;
9391 struct tevent_req *oplock_req, *getacl_req;
9392 const char *fname = "posix_acl_oplock";
9394 int saved_use_oplocks = use_oplocks;
9396 bool correct = true;
9397 bool got_break = false;
9398 bool acl_ret = false;
9400 struct posix_acl_oplock_state *state;
9402 printf("starting posix_acl_oplock test\n");
9404 if (!torture_open_connection(&cli1, 0)) {
9405 use_level_II_oplocks = false;
9406 use_oplocks = saved_use_oplocks;
9410 if (!torture_open_connection(&cli2, 1)) {
9411 use_level_II_oplocks = false;
9412 use_oplocks = saved_use_oplocks;
9416 /* Setup posix on cli2 only. */
9417 status = torture_setup_unix_extensions(cli2);
9418 if (!NT_STATUS_IS_OK(status)) {
9422 smbXcli_conn_set_sockopt(cli1->conn, sockops);
9423 smbXcli_conn_set_sockopt(cli2->conn, sockops);
9425 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
9427 /* Create the file on the Windows connection. */
9428 status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
9430 if (!NT_STATUS_IS_OK(status)) {
9431 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
9435 status = cli_close(cli1, fnum);
9436 if (!NT_STATUS_IS_OK(status)) {
9437 printf("close1 failed (%s)\n", nt_errstr(status));
9441 cli1->use_oplocks = true;
9443 /* Open with oplock. */
9444 status = cli_ntcreate(cli1,
9448 FILE_ATTRIBUTE_NORMAL,
9449 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
9456 if (!NT_STATUS_IS_OK(status)) {
9457 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
9461 ev = samba_tevent_context_init(talloc_tos());
9463 printf("tevent_context_init failed\n");
9467 state = talloc_zero(ev, struct posix_acl_oplock_state);
9468 if (state == NULL) {
9469 printf("talloc failed\n");
9474 state->got_break = &got_break;
9475 state->acl_ret = &acl_ret;
9477 oplock_req = cli_smb_oplock_break_waiter_send(
9478 talloc_tos(), ev, cli1);
9479 if (oplock_req == NULL) {
9480 printf("cli_smb_oplock_break_waiter_send failed\n");
9483 tevent_req_set_callback(oplock_req, posix_acl_oplock_got_break, state);
9485 /* Get ACL on POSIX connection - should break oplock. */
9486 getacl_req = cli_posix_getacl_send(talloc_tos(),
9490 if (getacl_req == NULL) {
9491 printf("cli_posix_getacl_send failed\n");
9494 tevent_req_set_callback(getacl_req, posix_acl_oplock_got_acl, state);
9496 while (!got_break || !acl_ret) {
9498 ret = tevent_loop_once(ev);
9500 printf("tevent_loop_once failed: %s\n",
9506 if (!NT_STATUS_IS_OK(state->status)) {
9507 printf("getacl failed (%s)\n", nt_errstr(state->status));
9511 status = cli_close(cli1, fnum);
9512 if (!NT_STATUS_IS_OK(status)) {
9513 printf("close2 failed (%s)\n", nt_errstr(status));
9517 status = cli_unlink(cli1,
9519 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
9520 if (!NT_STATUS_IS_OK(status)) {
9521 printf("unlink failed (%s)\n", nt_errstr(status));
9525 if (!torture_close_connection(cli1)) {
9528 if (!torture_close_connection(cli2)) {
9536 printf("finished posix acl oplock test\n");
9541 static bool run_posix_acl_shareroot_test(int dummy)
9543 struct cli_state *cli;
9545 bool correct = false;
9546 char *posix_acl = NULL;
9547 size_t posix_acl_len = 0;
9548 uint16_t num_file_acls = 0;
9549 uint16_t num_dir_acls = 0;
9551 uint32_t expected_size = 0;
9552 bool got_user = false;
9553 bool got_group = false;
9554 bool got_other = false;
9555 TALLOC_CTX *frame = NULL;
9557 frame = talloc_stackframe();
9559 printf("starting posix_acl_shareroot test\n");
9561 if (!torture_open_connection(&cli, 0)) {
9566 smbXcli_conn_set_sockopt(cli->conn, sockops);
9568 status = torture_setup_unix_extensions(cli);
9569 if (!NT_STATUS_IS_OK(status)) {
9570 printf("Failed to setup unix extensions\n");
9574 /* Get the POSIX ACL on the root of the share. */
9575 status = cli_posix_getacl(cli,
9581 if (!NT_STATUS_IS_OK(status)) {
9582 printf("cli_posix_getacl of '.' failed (%s)\n",
9587 if (posix_acl_len < 6 ||
9588 SVAL(posix_acl,0) != SMB_POSIX_ACL_VERSION) {
9589 printf("getfacl ., unknown POSIX acl version %u.\n",
9590 (unsigned int)CVAL(posix_acl,0) );
9594 num_file_acls = SVAL(posix_acl,2);
9595 num_dir_acls = SVAL(posix_acl,4);
9596 expected_size = SMB_POSIX_ACL_HEADER_SIZE +
9597 SMB_POSIX_ACL_ENTRY_SIZE*
9598 (num_file_acls+num_dir_acls);
9600 if (posix_acl_len != expected_size) {
9601 printf("incorrect POSIX acl buffer size "
9602 "(should be %u, was %u).\n",
9603 (unsigned int)expected_size,
9604 (unsigned int)posix_acl_len);
9609 * We don't need to know what the ACL's are
9610 * we just need to know we have at least 3
9611 * file entries (u,g,o).
9614 for (i = 0; i < num_file_acls; i++) {
9615 unsigned char tagtype =
9617 SMB_POSIX_ACL_HEADER_SIZE+
9618 (i*SMB_POSIX_ACL_ENTRY_SIZE));
9621 case SMB_POSIX_ACL_USER_OBJ:
9624 case SMB_POSIX_ACL_GROUP_OBJ:
9627 case SMB_POSIX_ACL_OTHER:
9636 printf("Missing user entry\n");
9641 printf("Missing group entry\n");
9646 printf("Missing other entry\n");
9654 if (!torture_close_connection(cli)) {
9658 printf("finished posix acl shareroot test\n");
9664 static uint32_t open_attrs_table[] = {
9665 FILE_ATTRIBUTE_NORMAL,
9666 FILE_ATTRIBUTE_ARCHIVE,
9667 FILE_ATTRIBUTE_READONLY,
9668 FILE_ATTRIBUTE_HIDDEN,
9669 FILE_ATTRIBUTE_SYSTEM,
9671 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY,
9672 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN,
9673 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM,
9674 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN,
9675 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM,
9676 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM,
9678 FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN,
9679 FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM,
9680 FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM,
9681 FILE_ATTRIBUTE_HIDDEN,FILE_ATTRIBUTE_SYSTEM,
9684 struct trunc_open_results {
9687 uint32_t trunc_attr;
9688 uint32_t result_attr;
9691 static struct trunc_open_results attr_results[] = {
9692 { 0, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_ARCHIVE },
9693 { 1, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_ARCHIVE },
9694 { 2, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_READONLY, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY },
9695 { 16, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_ARCHIVE },
9696 { 17, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_ARCHIVE },
9697 { 18, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_READONLY, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY },
9698 { 51, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
9699 { 54, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
9700 { 56, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN },
9701 { 68, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
9702 { 71, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
9703 { 73, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM },
9704 { 99, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_HIDDEN,FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
9705 { 102, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
9706 { 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 },
9707 { 116, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
9708 { 119, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
9709 { 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 },
9710 { 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 },
9711 { 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 },
9712 { 227, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
9713 { 230, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
9714 { 232, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN },
9715 { 244, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
9716 { 247, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
9717 { 249, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM }
9720 static bool run_openattrtest(int dummy)
9722 static struct cli_state *cli1;
9723 const char *fname = "\\openattr.file";
9725 bool correct = True;
9727 unsigned int i, j, k, l;
9730 printf("starting open attr test\n");
9732 if (!torture_open_connection(&cli1, 0)) {
9736 smbXcli_conn_set_sockopt(cli1->conn, sockops);
9738 for (k = 0, i = 0; i < sizeof(open_attrs_table)/sizeof(uint32_t); i++) {
9739 cli_setatr(cli1, fname, 0, 0);
9740 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
9742 status = cli_ntcreate(cli1, fname, 0, FILE_WRITE_DATA,
9743 open_attrs_table[i], FILE_SHARE_NONE,
9744 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
9745 if (!NT_STATUS_IS_OK(status)) {
9746 printf("open %d (1) of %s failed (%s)\n", i, fname, nt_errstr(status));
9750 status = cli_close(cli1, fnum1);
9751 if (!NT_STATUS_IS_OK(status)) {
9752 printf("close %d (1) of %s failed (%s)\n", i, fname, nt_errstr(status));
9756 for (j = 0; j < sizeof(open_attrs_table)/sizeof(uint32_t); j++) {
9757 status = cli_ntcreate(cli1, fname, 0,
9758 FILE_READ_DATA|FILE_WRITE_DATA,
9759 open_attrs_table[j],
9760 FILE_SHARE_NONE, FILE_OVERWRITE,
9761 0, 0, &fnum1, NULL);
9762 if (!NT_STATUS_IS_OK(status)) {
9763 for (l = 0; l < sizeof(attr_results)/sizeof(struct trunc_open_results); l++) {
9764 if (attr_results[l].num == k) {
9765 printf("[%d] trunc open 0x%x -> 0x%x of %s failed - should have succeeded !(0x%x:%s)\n",
9766 k, open_attrs_table[i],
9767 open_attrs_table[j],
9768 fname, NT_STATUS_V(status), nt_errstr(status));
9773 if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
9774 printf("[%d] trunc open 0x%x -> 0x%x failed with wrong error code %s\n",
9775 k, open_attrs_table[i], open_attrs_table[j],
9780 printf("[%d] trunc open 0x%x -> 0x%x failed\n", k, open_attrs_table[i], open_attrs_table[j]);
9786 status = cli_close(cli1, fnum1);
9787 if (!NT_STATUS_IS_OK(status)) {
9788 printf("close %d (2) of %s failed (%s)\n", j, fname, nt_errstr(status));
9792 status = cli_getatr(cli1, fname, &attr, NULL, NULL);
9793 if (!NT_STATUS_IS_OK(status)) {
9794 printf("getatr(2) failed (%s)\n", nt_errstr(status));
9799 printf("[%d] getatr check [0x%x] trunc [0x%x] got attr 0x%x\n",
9800 k, open_attrs_table[i], open_attrs_table[j], attr );
9803 for (l = 0; l < sizeof(attr_results)/sizeof(struct trunc_open_results); l++) {
9804 if (attr_results[l].num == k) {
9805 if (attr != attr_results[l].result_attr ||
9806 open_attrs_table[i] != attr_results[l].init_attr ||
9807 open_attrs_table[j] != attr_results[l].trunc_attr) {
9808 printf("getatr check failed. [0x%x] trunc [0x%x] got attr 0x%x, should be 0x%x\n",
9809 open_attrs_table[i],
9810 open_attrs_table[j],
9812 attr_results[l].result_attr);
9822 cli_setatr(cli1, fname, 0, 0);
9823 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
9825 printf("open attr test %s.\n", correct ? "passed" : "failed");
9827 if (!torture_close_connection(cli1)) {
9833 static NTSTATUS list_fn(struct file_info *finfo,
9834 const char *name, void *state)
9836 int *matched = (int *)state;
9837 if (matched != NULL) {
9840 return NT_STATUS_OK;
9844 test directory listing speed
9846 static bool run_dirtest(int dummy)
9849 static struct cli_state *cli;
9851 struct timeval core_start;
9852 bool correct = True;
9855 printf("starting directory test\n");
9857 if (!torture_open_connection(&cli, 0)) {
9861 smbXcli_conn_set_sockopt(cli->conn, sockops);
9864 for (i=0;i<torture_numops;i++) {
9866 slprintf(fname, sizeof(fname), "\\%x", (int)random());
9867 if (!NT_STATUS_IS_OK(cli_openx(cli, fname, O_RDWR|O_CREAT, DENY_NONE, &fnum))) {
9868 fprintf(stderr,"Failed to open %s\n", fname);
9871 cli_close(cli, fnum);
9874 core_start = timeval_current();
9877 cli_list(cli, "a*.*", 0, list_fn, &matched);
9878 printf("Matched %d\n", matched);
9881 cli_list(cli, "b*.*", 0, list_fn, &matched);
9882 printf("Matched %d\n", matched);
9885 cli_list(cli, "xyzabc", 0, list_fn, &matched);
9886 printf("Matched %d\n", matched);
9888 printf("dirtest core %g seconds\n", timeval_elapsed(&core_start));
9891 for (i=0;i<torture_numops;i++) {
9893 slprintf(fname, sizeof(fname), "\\%x", (int)random());
9894 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
9897 if (!torture_close_connection(cli)) {
9901 printf("finished dirtest\n");
9906 static NTSTATUS del_fn(struct file_info *finfo, const char *mask,
9909 struct cli_state *pcli = (struct cli_state *)state;
9911 slprintf(fname, sizeof(fname), "\\LISTDIR\\%s", finfo->name);
9913 if (strcmp(finfo->name, ".") == 0 || strcmp(finfo->name, "..") == 0)
9914 return NT_STATUS_OK;
9916 if (finfo->attr & FILE_ATTRIBUTE_DIRECTORY) {
9917 if (!NT_STATUS_IS_OK(cli_rmdir(pcli, fname)))
9918 printf("del_fn: failed to rmdir %s\n,", fname );
9920 if (!NT_STATUS_IS_OK(cli_unlink(pcli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN)))
9921 printf("del_fn: failed to unlink %s\n,", fname );
9923 return NT_STATUS_OK;
9928 send a raw ioctl - used by the torture code
9930 static NTSTATUS cli_raw_ioctl(struct cli_state *cli,
9938 PUSH_LE_U16(vwv + 0, 0, fnum);
9939 PUSH_LE_U16(vwv + 1, 0, code >> 16);
9940 PUSH_LE_U16(vwv + 2, 0, (code & 0xFFFF));
9942 status = cli_smb(talloc_tos(),
9956 if (!NT_STATUS_IS_OK(status)) {
9959 *blob = data_blob_null;
9960 return NT_STATUS_OK;
9964 sees what IOCTLs are supported
9966 bool torture_ioctl_test(int dummy)
9968 static struct cli_state *cli;
9969 uint16_t device, function;
9971 const char *fname = "\\ioctl.dat";
9975 if (!torture_open_connection(&cli, 0)) {
9979 printf("starting ioctl test\n");
9981 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
9983 status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
9984 if (!NT_STATUS_IS_OK(status)) {
9985 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
9989 status = cli_raw_ioctl(cli, fnum, 0x2d0000 | (0x0420<<2), &blob);
9990 printf("ioctl device info: %s\n", nt_errstr(status));
9992 status = cli_raw_ioctl(cli, fnum, IOCTL_QUERY_JOB_INFO, &blob);
9993 printf("ioctl job info: %s\n", nt_errstr(status));
9995 for (device=0;device<0x100;device++) {
9996 printf("ioctl test with device = 0x%x\n", device);
9997 for (function=0;function<0x100;function++) {
9998 uint32_t code = (device<<16) | function;
10000 status = cli_raw_ioctl(cli, fnum, code, &blob);
10002 if (NT_STATUS_IS_OK(status)) {
10003 printf("ioctl 0x%x OK : %d bytes\n", (int)code,
10005 data_blob_free(&blob);
10010 if (!torture_close_connection(cli)) {
10019 tries variants of chkpath
10021 bool torture_chkpath_test(int dummy)
10023 static struct cli_state *cli;
10028 if (!torture_open_connection(&cli, 0)) {
10032 printf("starting chkpath test\n");
10034 /* cleanup from an old run */
10035 torture_deltree(cli, "\\chkpath.dir");
10037 status = cli_mkdir(cli, "\\chkpath.dir");
10038 if (!NT_STATUS_IS_OK(status)) {
10039 printf("mkdir1 failed : %s\n", nt_errstr(status));
10043 status = cli_mkdir(cli, "\\chkpath.dir\\dir2");
10044 if (!NT_STATUS_IS_OK(status)) {
10045 printf("mkdir2 failed : %s\n", nt_errstr(status));
10049 status = cli_openx(cli, "\\chkpath.dir\\foo.txt", O_RDWR|O_CREAT|O_EXCL,
10051 if (!NT_STATUS_IS_OK(status)) {
10052 printf("open1 failed (%s)\n", nt_errstr(status));
10055 cli_close(cli, fnum);
10057 status = cli_chkpath(cli, "\\chkpath.dir");
10058 if (!NT_STATUS_IS_OK(status)) {
10059 printf("chkpath1 failed: %s\n", nt_errstr(status));
10063 status = cli_chkpath(cli, "\\chkpath.dir\\dir2");
10064 if (!NT_STATUS_IS_OK(status)) {
10065 printf("chkpath2 failed: %s\n", nt_errstr(status));
10069 status = cli_chkpath(cli, "\\chkpath.dir\\foo.txt");
10070 if (!NT_STATUS_IS_OK(status)) {
10071 ret = check_error(__LINE__, status, ERRDOS, ERRbadpath,
10072 NT_STATUS_NOT_A_DIRECTORY);
10074 printf("* chkpath on a file should fail\n");
10078 status = cli_chkpath(cli, "\\chkpath.dir\\bar.txt");
10079 if (!NT_STATUS_IS_OK(status)) {
10080 ret = check_error(__LINE__, status, ERRDOS, ERRbadfile,
10081 NT_STATUS_OBJECT_NAME_NOT_FOUND);
10083 printf("* chkpath on a non existent file should fail\n");
10087 status = cli_chkpath(cli, "\\chkpath.dir\\dirxx\\bar.txt");
10088 if (!NT_STATUS_IS_OK(status)) {
10089 ret = check_error(__LINE__, status, ERRDOS, ERRbadpath,
10090 NT_STATUS_OBJECT_PATH_NOT_FOUND);
10092 printf("* chkpath on a non existent component should fail\n");
10096 torture_deltree(cli, "\\chkpath.dir");
10098 if (!torture_close_connection(cli)) {
10105 static bool run_eatest(int dummy)
10107 static struct cli_state *cli;
10108 const char *fname = "\\eatest.txt";
10109 bool correct = True;
10112 struct ea_struct *ea_list = NULL;
10113 TALLOC_CTX *mem_ctx = talloc_init("eatest");
10116 printf("starting eatest\n");
10118 if (!torture_open_connection(&cli, 0)) {
10119 talloc_destroy(mem_ctx);
10123 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
10125 status = cli_ntcreate(cli, fname, 0,
10126 FIRST_DESIRED_ACCESS, FILE_ATTRIBUTE_ARCHIVE,
10127 FILE_SHARE_NONE, FILE_OVERWRITE_IF,
10128 0x4044, 0, &fnum, NULL);
10129 if (!NT_STATUS_IS_OK(status)) {
10130 printf("open failed - %s\n", nt_errstr(status));
10131 talloc_destroy(mem_ctx);
10135 for (i = 0; i < 10; i++) {
10136 fstring ea_name, ea_val;
10138 slprintf(ea_name, sizeof(ea_name), "EA_%zu", i);
10139 memset(ea_val, (char)i+1, i+1);
10140 status = cli_set_ea_fnum(cli, fnum, ea_name, ea_val, i+1);
10141 if (!NT_STATUS_IS_OK(status)) {
10142 printf("ea_set of name %s failed - %s\n", ea_name,
10143 nt_errstr(status));
10144 talloc_destroy(mem_ctx);
10149 cli_close(cli, fnum);
10150 for (i = 0; i < 10; i++) {
10151 fstring ea_name, ea_val;
10153 slprintf(ea_name, sizeof(ea_name), "EA_%zu", i+10);
10154 memset(ea_val, (char)i+1, i+1);
10155 status = cli_set_ea_path(cli, fname, ea_name, ea_val, i+1);
10156 if (!NT_STATUS_IS_OK(status)) {
10157 printf("ea_set of name %s failed - %s\n", ea_name,
10158 nt_errstr(status));
10159 talloc_destroy(mem_ctx);
10164 status = cli_get_ea_list_path(cli, fname, mem_ctx, &num_eas, &ea_list);
10165 if (!NT_STATUS_IS_OK(status)) {
10166 printf("ea_get list failed - %s\n", nt_errstr(status));
10170 printf("num_eas = %d\n", (int)num_eas);
10172 if (num_eas != 20) {
10173 printf("Should be 20 EA's stored... failing.\n");
10177 for (i = 0; i < num_eas; i++) {
10178 printf("%zu: ea_name = %s. Val = ", i, ea_list[i].name);
10179 dump_data(0, ea_list[i].value.data,
10180 ea_list[i].value.length);
10183 /* Setting EA's to zero length deletes them. Test this */
10184 printf("Now deleting all EA's - case independent....\n");
10187 cli_set_ea_path(cli, fname, "", "", 0);
10189 for (i = 0; i < 20; i++) {
10191 slprintf(ea_name, sizeof(ea_name), "ea_%d", i);
10192 status = cli_set_ea_path(cli, fname, ea_name, "", 0);
10193 if (!NT_STATUS_IS_OK(status)) {
10194 printf("ea_set of name %s failed - %s\n", ea_name,
10195 nt_errstr(status));
10196 talloc_destroy(mem_ctx);
10202 status = cli_get_ea_list_path(cli, fname, mem_ctx, &num_eas, &ea_list);
10203 if (!NT_STATUS_IS_OK(status)) {
10204 printf("ea_get list failed - %s\n", nt_errstr(status));
10208 printf("num_eas = %d\n", (int)num_eas);
10209 for (i = 0; i < num_eas; i++) {
10210 printf("%zu: ea_name = %s. Val = ", i, ea_list[i].name);
10211 dump_data(0, ea_list[i].value.data,
10212 ea_list[i].value.length);
10215 if (num_eas != 0) {
10216 printf("deleting EA's failed.\n");
10220 /* Try and delete a non existent EA. */
10221 status = cli_set_ea_path(cli, fname, "foo", "", 0);
10222 if (!NT_STATUS_IS_OK(status)) {
10223 printf("deleting non-existent EA 'foo' should succeed. %s\n",
10224 nt_errstr(status));
10228 talloc_destroy(mem_ctx);
10229 if (!torture_close_connection(cli)) {
10236 static bool run_dirtest1(int dummy)
10239 static struct cli_state *cli;
10242 bool correct = True;
10244 printf("starting directory test\n");
10246 if (!torture_open_connection(&cli, 0)) {
10250 smbXcli_conn_set_sockopt(cli->conn, sockops);
10252 cli_list(cli, "\\LISTDIR\\*", 0, del_fn, cli);
10253 cli_list(cli, "\\LISTDIR\\*", FILE_ATTRIBUTE_DIRECTORY, del_fn, cli);
10254 cli_rmdir(cli, "\\LISTDIR");
10255 cli_mkdir(cli, "\\LISTDIR");
10257 /* Create 1000 files and 1000 directories. */
10258 for (i=0;i<1000;i++) {
10260 slprintf(fname, sizeof(fname), "\\LISTDIR\\f%d", i);
10261 if (!NT_STATUS_IS_OK(cli_ntcreate(cli, fname, 0, GENERIC_ALL_ACCESS, FILE_ATTRIBUTE_ARCHIVE,
10262 FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OVERWRITE_IF,
10263 0, 0, &fnum, NULL))) {
10264 fprintf(stderr,"Failed to open %s\n", fname);
10267 cli_close(cli, fnum);
10269 for (i=0;i<1000;i++) {
10271 slprintf(fname, sizeof(fname), "\\LISTDIR\\d%d", i);
10272 if (!NT_STATUS_IS_OK(cli_mkdir(cli, fname))) {
10273 fprintf(stderr,"Failed to open %s\n", fname);
10278 /* Now ensure that doing an old list sees both files and directories. */
10280 cli_list_old(cli, "\\LISTDIR\\*", FILE_ATTRIBUTE_DIRECTORY, list_fn, &num_seen);
10281 printf("num_seen = %d\n", num_seen );
10282 /* We should see 100 files + 1000 directories + . and .. */
10283 if (num_seen != 2002)
10286 /* Ensure if we have the "must have" bits we only see the
10287 * relevant entries.
10290 cli_list_old(cli, "\\LISTDIR\\*", (FILE_ATTRIBUTE_DIRECTORY<<8)|FILE_ATTRIBUTE_DIRECTORY, list_fn, &num_seen);
10291 printf("num_seen = %d\n", num_seen );
10292 if (num_seen != 1002)
10296 cli_list_old(cli, "\\LISTDIR\\*", (FILE_ATTRIBUTE_ARCHIVE<<8)|FILE_ATTRIBUTE_DIRECTORY, list_fn, &num_seen);
10297 printf("num_seen = %d\n", num_seen );
10298 if (num_seen != 1000)
10301 /* Delete everything. */
10302 cli_list(cli, "\\LISTDIR\\*", 0, del_fn, cli);
10303 cli_list(cli, "\\LISTDIR\\*", FILE_ATTRIBUTE_DIRECTORY, del_fn, cli);
10304 cli_rmdir(cli, "\\LISTDIR");
10307 printf("Matched %d\n", cli_list(cli, "a*.*", 0, list_fn, NULL));
10308 printf("Matched %d\n", cli_list(cli, "b*.*", 0, list_fn, NULL));
10309 printf("Matched %d\n", cli_list(cli, "xyzabc", 0, list_fn, NULL));
10312 if (!torture_close_connection(cli)) {
10316 printf("finished dirtest1\n");
10321 static bool run_error_map_extract(int dummy) {
10323 static struct cli_state *c_dos;
10324 static struct cli_state *c_nt;
10332 NTSTATUS nt_status;
10336 /* NT-Error connection */
10338 disable_spnego = true;
10339 if (!(c_nt = open_nbt_connection())) {
10340 disable_spnego = false;
10343 disable_spnego = false;
10345 status = smbXcli_negprot(c_nt->conn,
10353 if (!NT_STATUS_IS_OK(status)) {
10354 printf("%s rejected the NT-error negprot (%s)\n", host,
10355 nt_errstr(status));
10356 cli_shutdown(c_nt);
10360 status = cli_session_setup_anon(c_nt);
10361 if (!NT_STATUS_IS_OK(status)) {
10362 printf("%s rejected the NT-error initial session setup (%s)\n",host, nt_errstr(status));
10366 /* DOS-Error connection */
10368 disable_spnego = true;
10369 force_dos_errors = true;
10370 if (!(c_dos = open_nbt_connection())) {
10371 disable_spnego = false;
10372 force_dos_errors = false;
10375 disable_spnego = false;
10376 force_dos_errors = false;
10378 status = smbXcli_negprot(c_dos->conn,
10385 if (!NT_STATUS_IS_OK(status)) {
10386 printf("%s rejected the DOS-error negprot (%s)\n", host,
10387 nt_errstr(status));
10388 cli_shutdown(c_dos);
10392 status = cli_session_setup_anon(c_dos);
10393 if (!NT_STATUS_IS_OK(status)) {
10394 printf("%s rejected the DOS-error initial session setup (%s)\n",
10395 host, nt_errstr(status));
10399 c_nt->map_dos_errors = false;
10400 c_dos->map_dos_errors = false;
10402 for (error=(0xc0000000 | 0x1); error < (0xc0000000| 0xFFF); error++) {
10403 struct cli_credentials *user_creds = NULL;
10405 fstr_sprintf(user, "%X", error);
10407 user_creds = cli_session_creds_init(talloc_tos(),
10412 false, /* use_kerberos */
10413 false, /* fallback_after_kerberos */
10414 false, /* use_ccache */
10415 false); /* password_is_nt_hash */
10416 if (user_creds == NULL) {
10417 printf("cli_session_creds_init(%s) failed\n", user);
10421 status = cli_session_setup_creds(c_nt, user_creds);
10422 if (NT_STATUS_IS_OK(status)) {
10423 printf("/** Session setup succeeded. This shouldn't happen...*/\n");
10426 /* Case #1: 32-bit NT errors */
10427 if (!NT_STATUS_IS_DOS(status)) {
10428 nt_status = status;
10430 printf("/** Dos error on NT connection! (%s) */\n",
10431 nt_errstr(status));
10432 nt_status = NT_STATUS(0xc0000000);
10435 status = cli_session_setup_creds(c_dos, user_creds);
10436 if (NT_STATUS_IS_OK(status)) {
10437 printf("/** Session setup succeeded. This shouldn't happen...*/\n");
10440 /* Case #1: 32-bit NT errors */
10441 if (NT_STATUS_IS_DOS(status)) {
10442 printf("/** NT error on DOS connection! (%s) */\n",
10443 nt_errstr(status));
10444 errnum = errclass = 0;
10446 errclass = NT_STATUS_DOS_CLASS(status);
10447 errnum = NT_STATUS_DOS_CODE(status);
10450 if (NT_STATUS_V(nt_status) != error) {
10451 printf("/*\t{ This NT error code was 'sqashed'\n\t from %s to %s \n\t during the session setup }\n*/\n",
10452 get_nt_error_c_code(talloc_tos(), NT_STATUS(error)),
10453 get_nt_error_c_code(talloc_tos(), nt_status));
10456 printf("\t{%s,\t%s,\t%s},\n",
10457 smb_dos_err_class(errclass),
10458 smb_dos_err_name(errclass, errnum),
10459 get_nt_error_c_code(talloc_tos(), NT_STATUS(error)));
10461 TALLOC_FREE(user_creds);
10466 static bool run_sesssetup_bench(int dummy)
10468 static struct cli_state *c;
10469 const char *fname = "\\file.dat";
10474 if (!torture_open_connection(&c, 0)) {
10478 status = cli_ntcreate(c, fname, 0, GENERIC_ALL_ACCESS|DELETE_ACCESS,
10479 FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
10480 FILE_DELETE_ON_CLOSE, 0, &fnum, NULL);
10481 if (!NT_STATUS_IS_OK(status)) {
10482 d_printf("open %s failed: %s\n", fname, nt_errstr(status));
10486 for (i=0; i<torture_numops; i++) {
10487 status = cli_session_setup_creds(c, torture_creds);
10488 if (!NT_STATUS_IS_OK(status)) {
10489 d_printf("(%s) cli_session_setup_creds failed: %s\n",
10490 __location__, nt_errstr(status));
10494 d_printf("\r%d ", (int)cli_state_get_uid(c));
10496 status = cli_ulogoff(c);
10497 if (!NT_STATUS_IS_OK(status)) {
10498 d_printf("(%s) cli_ulogoff failed: %s\n",
10499 __location__, nt_errstr(status));
10507 static bool subst_test(const char *str, const char *user, const char *domain,
10508 uid_t uid, gid_t gid, const char *expected)
10511 bool result = true;
10513 subst = talloc_sub_specified(talloc_tos(), str, user, NULL, domain, uid, gid);
10515 if (strcmp(subst, expected) != 0) {
10516 printf("sub_specified(%s, %s, %s, %d, %d) returned [%s], expected "
10517 "[%s]\n", str, user, domain, (int)uid, (int)gid, subst,
10522 TALLOC_FREE(subst);
10526 static void chain1_open_completion(struct tevent_req *req)
10530 status = cli_openx_recv(req, &fnum);
10533 d_printf("cli_openx_recv returned %s: %d\n",
10535 NT_STATUS_IS_OK(status) ? fnum : -1);
10538 static void chain1_write_completion(struct tevent_req *req)
10542 status = cli_write_andx_recv(req, &written);
10545 d_printf("cli_write_andx_recv returned %s: %d\n",
10547 NT_STATUS_IS_OK(status) ? (int)written : -1);
10550 static void chain1_close_completion(struct tevent_req *req)
10553 bool *done = (bool *)tevent_req_callback_data_void(req);
10555 status = cli_close_recv(req);
10560 d_printf("cli_close returned %s\n", nt_errstr(status));
10563 static bool run_chain1(int dummy)
10565 struct cli_state *cli1;
10566 struct tevent_context *evt = samba_tevent_context_init(NULL);
10567 struct tevent_req *reqs[3], *smbreqs[3];
10569 const char *str = "foobar";
10570 const char *fname = "\\test_chain";
10573 printf("starting chain1 test\n");
10574 if (!torture_open_connection(&cli1, 0)) {
10578 smbXcli_conn_set_sockopt(cli1->conn, sockops);
10580 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
10582 reqs[0] = cli_openx_create(talloc_tos(), evt, cli1, fname,
10583 O_CREAT|O_RDWR, 0, &smbreqs[0]);
10584 if (reqs[0] == NULL) return false;
10585 tevent_req_set_callback(reqs[0], chain1_open_completion, NULL);
10588 reqs[1] = cli_write_andx_create(talloc_tos(), evt, cli1, 0, 0,
10589 (const uint8_t *)str, 0, strlen(str)+1,
10590 smbreqs, 1, &smbreqs[1]);
10591 if (reqs[1] == NULL) return false;
10592 tevent_req_set_callback(reqs[1], chain1_write_completion, NULL);
10594 reqs[2] = cli_smb1_close_create(talloc_tos(), evt, cli1, 0, &smbreqs[2]);
10595 if (reqs[2] == NULL) return false;
10596 tevent_req_set_callback(reqs[2], chain1_close_completion, &done);
10598 status = smb1cli_req_chain_submit(smbreqs, ARRAY_SIZE(smbreqs));
10599 if (!NT_STATUS_IS_OK(status)) {
10604 tevent_loop_once(evt);
10607 torture_close_connection(cli1);
10611 static void chain2_sesssetup_completion(struct tevent_req *req)
10614 status = cli_session_setup_guest_recv(req);
10615 d_printf("sesssetup returned %s\n", nt_errstr(status));
10618 static void chain2_tcon_completion(struct tevent_req *req)
10620 bool *done = (bool *)tevent_req_callback_data_void(req);
10622 status = cli_tcon_andx_recv(req);
10623 d_printf("tcon_and_x returned %s\n", nt_errstr(status));
10627 static bool run_chain2(int dummy)
10629 struct cli_state *cli1;
10630 struct tevent_context *evt = samba_tevent_context_init(NULL);
10631 struct tevent_req *reqs[2], *smbreqs[2];
10634 int flags = CLI_FULL_CONNECTION_FORCE_SMB1;
10636 printf("starting chain2 test\n");
10637 status = cli_start_connection(&cli1, lp_netbios_name(), host, NULL,
10638 port_to_use, SMB_SIGNING_DEFAULT, flags);
10639 if (!NT_STATUS_IS_OK(status)) {
10643 smbXcli_conn_set_sockopt(cli1->conn, sockops);
10645 reqs[0] = cli_session_setup_guest_create(talloc_tos(), evt, cli1,
10647 if (reqs[0] == NULL) return false;
10648 tevent_req_set_callback(reqs[0], chain2_sesssetup_completion, NULL);
10650 reqs[1] = cli_tcon_andx_create(talloc_tos(), evt, cli1, "IPC$",
10651 "?????", NULL, 0, &smbreqs[1]);
10652 if (reqs[1] == NULL) return false;
10653 tevent_req_set_callback(reqs[1], chain2_tcon_completion, &done);
10655 status = smb1cli_req_chain_submit(smbreqs, ARRAY_SIZE(smbreqs));
10656 if (!NT_STATUS_IS_OK(status)) {
10661 tevent_loop_once(evt);
10664 torture_close_connection(cli1);
10669 struct torture_createdel_state {
10670 struct tevent_context *ev;
10671 struct cli_state *cli;
10674 static void torture_createdel_created(struct tevent_req *subreq);
10675 static void torture_createdel_closed(struct tevent_req *subreq);
10677 static struct tevent_req *torture_createdel_send(TALLOC_CTX *mem_ctx,
10678 struct tevent_context *ev,
10679 struct cli_state *cli,
10682 struct tevent_req *req, *subreq;
10683 struct torture_createdel_state *state;
10685 req = tevent_req_create(mem_ctx, &state,
10686 struct torture_createdel_state);
10693 subreq = cli_ntcreate_send(
10694 state, ev, cli, name, 0,
10695 FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
10696 FILE_ATTRIBUTE_NORMAL,
10697 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
10698 FILE_OPEN_IF, FILE_DELETE_ON_CLOSE,
10699 SMB2_IMPERSONATION_IMPERSONATION, 0);
10701 if (tevent_req_nomem(subreq, req)) {
10702 return tevent_req_post(req, ev);
10704 tevent_req_set_callback(subreq, torture_createdel_created, req);
10708 static void torture_createdel_created(struct tevent_req *subreq)
10710 struct tevent_req *req = tevent_req_callback_data(
10711 subreq, struct tevent_req);
10712 struct torture_createdel_state *state = tevent_req_data(
10713 req, struct torture_createdel_state);
10717 status = cli_ntcreate_recv(subreq, &fnum, NULL);
10718 TALLOC_FREE(subreq);
10719 if (tevent_req_nterror(req, status)) {
10720 DEBUG(10, ("cli_ntcreate_recv returned %s\n",
10721 nt_errstr(status)));
10725 subreq = cli_close_send(state, state->ev, state->cli, fnum, 0);
10726 if (tevent_req_nomem(subreq, req)) {
10729 tevent_req_set_callback(subreq, torture_createdel_closed, req);
10732 static void torture_createdel_closed(struct tevent_req *subreq)
10734 struct tevent_req *req = tevent_req_callback_data(
10735 subreq, struct tevent_req);
10738 status = cli_close_recv(subreq);
10739 if (tevent_req_nterror(req, status)) {
10740 DEBUG(10, ("cli_close_recv returned %s\n", nt_errstr(status)));
10743 tevent_req_done(req);
10746 static NTSTATUS torture_createdel_recv(struct tevent_req *req)
10748 return tevent_req_simple_recv_ntstatus(req);
10751 struct torture_createdels_state {
10752 struct tevent_context *ev;
10753 struct cli_state *cli;
10754 const char *base_name;
10758 struct tevent_req **reqs;
10761 static void torture_createdels_done(struct tevent_req *subreq);
10763 static struct tevent_req *torture_createdels_send(TALLOC_CTX *mem_ctx,
10764 struct tevent_context *ev,
10765 struct cli_state *cli,
10766 const char *base_name,
10770 struct tevent_req *req;
10771 struct torture_createdels_state *state;
10774 req = tevent_req_create(mem_ctx, &state,
10775 struct torture_createdels_state);
10781 state->base_name = talloc_strdup(state, base_name);
10782 if (tevent_req_nomem(state->base_name, req)) {
10783 return tevent_req_post(req, ev);
10785 state->num_files = MAX(num_parallel, num_files);
10787 state->received = 0;
10789 state->reqs = talloc_array(state, struct tevent_req *, num_parallel);
10790 if (tevent_req_nomem(state->reqs, req)) {
10791 return tevent_req_post(req, ev);
10794 for (i=0; i<num_parallel; i++) {
10797 name = talloc_asprintf(state, "%s%8.8d", state->base_name,
10799 if (tevent_req_nomem(name, req)) {
10800 return tevent_req_post(req, ev);
10802 state->reqs[i] = torture_createdel_send(
10803 state->reqs, state->ev, state->cli, name);
10804 if (tevent_req_nomem(state->reqs[i], req)) {
10805 return tevent_req_post(req, ev);
10807 name = talloc_move(state->reqs[i], &name);
10808 tevent_req_set_callback(state->reqs[i],
10809 torture_createdels_done, req);
10815 static void torture_createdels_done(struct tevent_req *subreq)
10817 struct tevent_req *req = tevent_req_callback_data(
10818 subreq, struct tevent_req);
10819 struct torture_createdels_state *state = tevent_req_data(
10820 req, struct torture_createdels_state);
10821 size_t i, num_parallel = talloc_array_length(state->reqs);
10825 status = torture_createdel_recv(subreq);
10826 if (!NT_STATUS_IS_OK(status)){
10827 DEBUG(10, ("torture_createdel_recv returned %s\n",
10828 nt_errstr(status)));
10829 TALLOC_FREE(subreq);
10830 tevent_req_nterror(req, status);
10834 for (i=0; i<num_parallel; i++) {
10835 if (subreq == state->reqs[i]) {
10839 if (i == num_parallel) {
10840 DEBUG(10, ("received something we did not send\n"));
10841 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
10844 TALLOC_FREE(state->reqs[i]);
10846 if (state->sent >= state->num_files) {
10847 tevent_req_done(req);
10851 name = talloc_asprintf(state, "%s%8.8d", state->base_name,
10853 if (tevent_req_nomem(name, req)) {
10856 state->reqs[i] = torture_createdel_send(state->reqs, state->ev,
10858 if (tevent_req_nomem(state->reqs[i], req)) {
10861 name = talloc_move(state->reqs[i], &name);
10862 tevent_req_set_callback(state->reqs[i], torture_createdels_done, req);
10866 static NTSTATUS torture_createdels_recv(struct tevent_req *req)
10868 return tevent_req_simple_recv_ntstatus(req);
10871 struct swallow_notify_state {
10872 struct tevent_context *ev;
10873 struct cli_state *cli;
10875 uint32_t completion_filter;
10877 bool (*fn)(uint32_t action, const char *name, void *priv);
10881 static void swallow_notify_done(struct tevent_req *subreq);
10883 static struct tevent_req *swallow_notify_send(TALLOC_CTX *mem_ctx,
10884 struct tevent_context *ev,
10885 struct cli_state *cli,
10887 uint32_t completion_filter,
10889 bool (*fn)(uint32_t action,
10894 struct tevent_req *req, *subreq;
10895 struct swallow_notify_state *state;
10897 req = tevent_req_create(mem_ctx, &state,
10898 struct swallow_notify_state);
10904 state->fnum = fnum;
10905 state->completion_filter = completion_filter;
10906 state->recursive = recursive;
10908 state->priv = priv;
10910 subreq = cli_notify_send(state, state->ev, state->cli, state->fnum,
10911 0xffff, state->completion_filter,
10913 if (tevent_req_nomem(subreq, req)) {
10914 return tevent_req_post(req, ev);
10916 tevent_req_set_callback(subreq, swallow_notify_done, req);
10920 static void swallow_notify_done(struct tevent_req *subreq)
10922 struct tevent_req *req = tevent_req_callback_data(
10923 subreq, struct tevent_req);
10924 struct swallow_notify_state *state = tevent_req_data(
10925 req, struct swallow_notify_state);
10927 uint32_t i, num_changes;
10928 struct notify_change *changes;
10930 status = cli_notify_recv(subreq, state, &num_changes, &changes);
10931 TALLOC_FREE(subreq);
10932 if (!NT_STATUS_IS_OK(status)) {
10933 DEBUG(10, ("cli_notify_recv returned %s\n",
10934 nt_errstr(status)));
10935 tevent_req_nterror(req, status);
10939 for (i=0; i<num_changes; i++) {
10940 state->fn(changes[i].action, changes[i].name, state->priv);
10942 TALLOC_FREE(changes);
10944 subreq = cli_notify_send(state, state->ev, state->cli, state->fnum,
10945 0xffff, state->completion_filter,
10947 if (tevent_req_nomem(subreq, req)) {
10950 tevent_req_set_callback(subreq, swallow_notify_done, req);
10953 static bool print_notifies(uint32_t action, const char *name, void *priv)
10955 if (DEBUGLEVEL > 5) {
10956 d_printf("%d %s\n", (int)action, name);
10961 static void notify_bench_done(struct tevent_req *req)
10963 int *num_finished = (int *)tevent_req_callback_data_void(req);
10964 *num_finished += 1;
10967 static bool run_notify_bench(int dummy)
10969 const char *dname = "\\notify-bench";
10970 struct tevent_context *ev;
10973 struct tevent_req *req1;
10974 struct tevent_req *req2 = NULL;
10975 int i, num_unc_names;
10976 int num_finished = 0;
10978 printf("starting notify-bench test\n");
10980 if (use_multishare_conn) {
10982 unc_list = file_lines_load(multishare_conn_fname,
10983 &num_unc_names, 0, NULL);
10984 if (!unc_list || num_unc_names <= 0) {
10985 d_printf("Failed to load unc names list from '%s'\n",
10986 multishare_conn_fname);
10989 TALLOC_FREE(unc_list);
10994 ev = samba_tevent_context_init(talloc_tos());
10996 d_printf("tevent_context_init failed\n");
11000 for (i=0; i<num_unc_names; i++) {
11001 struct cli_state *cli;
11004 base_fname = talloc_asprintf(talloc_tos(), "%s\\file%3.3d.",
11006 if (base_fname == NULL) {
11010 if (!torture_open_connection(&cli, i)) {
11014 status = cli_ntcreate(cli, dname, 0,
11015 MAXIMUM_ALLOWED_ACCESS,
11016 0, FILE_SHARE_READ|FILE_SHARE_WRITE|
11018 FILE_OPEN_IF, FILE_DIRECTORY_FILE, 0,
11021 if (!NT_STATUS_IS_OK(status)) {
11022 d_printf("Could not create %s: %s\n", dname,
11023 nt_errstr(status));
11027 req1 = swallow_notify_send(talloc_tos(), ev, cli, dnum,
11028 FILE_NOTIFY_CHANGE_FILE_NAME |
11029 FILE_NOTIFY_CHANGE_DIR_NAME |
11030 FILE_NOTIFY_CHANGE_ATTRIBUTES |
11031 FILE_NOTIFY_CHANGE_LAST_WRITE,
11032 false, print_notifies, NULL);
11033 if (req1 == NULL) {
11034 d_printf("Could not create notify request\n");
11038 req2 = torture_createdels_send(talloc_tos(), ev, cli,
11039 base_fname, 10, torture_numops);
11040 if (req2 == NULL) {
11041 d_printf("Could not create createdels request\n");
11044 TALLOC_FREE(base_fname);
11046 tevent_req_set_callback(req2, notify_bench_done,
11050 while (num_finished < num_unc_names) {
11052 ret = tevent_loop_once(ev);
11054 d_printf("tevent_loop_once failed\n");
11059 if (!tevent_req_poll(req2, ev)) {
11060 d_printf("tevent_req_poll failed\n");
11063 status = torture_createdels_recv(req2);
11064 d_printf("torture_createdels_recv returned %s\n", nt_errstr(status));
11069 static bool run_mangle1(int dummy)
11071 struct cli_state *cli;
11072 const char *fname = "this_is_a_long_fname_to_be_mangled.txt";
11077 printf("starting mangle1 test\n");
11078 if (!torture_open_connection(&cli, 0)) {
11082 smbXcli_conn_set_sockopt(cli->conn, sockops);
11084 status = cli_ntcreate(cli, fname, 0, GENERIC_ALL_ACCESS|DELETE_ACCESS,
11085 FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
11086 0, 0, &fnum, NULL);
11087 if (!NT_STATUS_IS_OK(status)) {
11088 d_printf("open %s failed: %s\n", fname, nt_errstr(status));
11091 cli_close(cli, fnum);
11093 status = cli_qpathinfo_alt_name(cli, fname, alt_name);
11094 if (!NT_STATUS_IS_OK(status)) {
11095 d_printf("cli_qpathinfo_alt_name failed: %s\n",
11096 nt_errstr(status));
11099 d_printf("alt_name: %s\n", alt_name);
11101 status = cli_openx(cli, alt_name, O_RDONLY, DENY_NONE, &fnum);
11102 if (!NT_STATUS_IS_OK(status)) {
11103 d_printf("cli_openx(%s) failed: %s\n", alt_name,
11104 nt_errstr(status));
11107 cli_close(cli, fnum);
11109 status = cli_qpathinfo1(cli, alt_name, NULL, NULL, NULL, NULL, NULL);
11110 if (!NT_STATUS_IS_OK(status)) {
11111 d_printf("cli_qpathinfo1(%s) failed: %s\n", alt_name,
11112 nt_errstr(status));
11119 static NTSTATUS mangle_illegal_list_shortname_fn(struct file_info *f,
11123 if (f->short_name == NULL) {
11124 return NT_STATUS_OK;
11127 if (strlen(f->short_name) == 0) {
11128 return NT_STATUS_OK;
11131 printf("unexpected shortname: %s\n", f->short_name);
11133 return NT_STATUS_OBJECT_NAME_INVALID;
11136 static NTSTATUS mangle_illegal_list_name_fn(struct file_info *f,
11140 char *name = state;
11142 printf("name: %s\n", f->name);
11143 fstrcpy(name, f->name);
11144 return NT_STATUS_OK;
11147 static bool run_mangle_illegal(int dummy)
11149 struct cli_state *cli = NULL;
11150 struct cli_state *cli_posix = NULL;
11151 const char *fname = "\\MANGLE_ILLEGAL\\this_is_a_long_fname_to_be_mangled.txt";
11152 const char *illegal_fname = "MANGLE_ILLEGAL/foo:bar";
11153 char *mangled_path = NULL;
11159 printf("starting mangle-illegal test\n");
11161 if (!torture_open_connection(&cli, 0)) {
11165 smbXcli_conn_set_sockopt(cli->conn, sockops);
11167 if (!torture_open_connection(&cli_posix, 0)) {
11171 smbXcli_conn_set_sockopt(cli_posix->conn, sockops);
11173 status = torture_setup_unix_extensions(cli_posix);
11174 if (!NT_STATUS_IS_OK(status)) {
11178 cli_rmdir(cli, "\\MANGLE_ILLEGAL");
11179 status = cli_mkdir(cli, "\\MANGLE_ILLEGAL");
11180 if (!NT_STATUS_IS_OK(status)) {
11181 printf("mkdir1 failed : %s\n", nt_errstr(status));
11186 * Create a file with illegal NTFS characters and test that we
11187 * get a usable mangled name
11190 cli_setatr(cli_posix, illegal_fname, 0, 0);
11191 cli_posix_unlink(cli_posix, illegal_fname);
11193 status = cli_posix_open(cli_posix, illegal_fname, O_RDWR|O_CREAT|O_EXCL,
11195 if (!NT_STATUS_IS_OK(status)) {
11196 printf("POSIX create of %s failed (%s)\n",
11197 illegal_fname, nt_errstr(status));
11201 status = cli_close(cli_posix, fnum);
11202 if (!NT_STATUS_IS_OK(status)) {
11203 printf("close failed (%s)\n", nt_errstr(status));
11207 status = cli_list(cli, "\\MANGLE_ILLEGAL\\*", 0, mangle_illegal_list_name_fn, &name);
11208 if (!NT_STATUS_IS_OK(status)) {
11209 d_printf("cli_list failed: %s\n", nt_errstr(status));
11213 mangled_path = talloc_asprintf(talloc_tos(), "\\MANGLE_ILLEGAL\\%s", name);
11214 if (mangled_path == NULL) {
11218 status = cli_openx(cli, mangled_path, O_RDONLY, DENY_NONE, &fnum);
11219 if (!NT_STATUS_IS_OK(status)) {
11220 d_printf("cli_openx(%s) failed: %s\n", mangled_path, nt_errstr(status));
11221 TALLOC_FREE(mangled_path);
11224 TALLOC_FREE(mangled_path);
11225 cli_close(cli, fnum);
11227 cli_setatr(cli_posix, illegal_fname, 0, 0);
11228 cli_posix_unlink(cli_posix, illegal_fname);
11231 * Create a file with a long name and check that we got *no* short name.
11234 status = cli_ntcreate(cli, fname, 0, GENERIC_ALL_ACCESS|DELETE_ACCESS,
11235 FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
11236 0, 0, &fnum, NULL);
11237 if (!NT_STATUS_IS_OK(status)) {
11238 d_printf("open %s failed: %s\n", fname, nt_errstr(status));
11241 cli_close(cli, fnum);
11243 status = cli_list(cli, fname, 0, mangle_illegal_list_shortname_fn, &alt_name);
11244 if (!NT_STATUS_IS_OK(status)) {
11245 d_printf("cli_list failed\n");
11249 cli_unlink(cli, fname, 0);
11250 cli_rmdir(cli, "\\MANGLE_ILLEGAL");
11252 if (!torture_close_connection(cli_posix)) {
11256 if (!torture_close_connection(cli)) {
11263 static size_t null_source(uint8_t *buf, size_t n, void *priv)
11265 size_t *to_pull = (size_t *)priv;
11266 size_t thistime = *to_pull;
11268 thistime = MIN(thistime, n);
11269 if (thistime == 0) {
11273 memset(buf, 0, thistime);
11274 *to_pull -= thistime;
11278 static bool run_windows_write(int dummy)
11280 struct cli_state *cli1;
11284 const char *fname = "\\writetest.txt";
11285 struct timeval start_time;
11290 printf("starting windows_write test\n");
11291 if (!torture_open_connection(&cli1, 0)) {
11295 status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
11296 if (!NT_STATUS_IS_OK(status)) {
11297 printf("open failed (%s)\n", nt_errstr(status));
11301 smbXcli_conn_set_sockopt(cli1->conn, sockops);
11303 start_time = timeval_current();
11305 for (i=0; i<torture_numops; i++) {
11307 off_t start = i * torture_blocksize;
11308 size_t to_pull = torture_blocksize - 1;
11310 status = cli_writeall(cli1, fnum, 0, &c,
11311 start + torture_blocksize - 1, 1, NULL);
11312 if (!NT_STATUS_IS_OK(status)) {
11313 printf("cli_write failed: %s\n", nt_errstr(status));
11317 status = cli_push(cli1, fnum, 0, i * torture_blocksize, torture_blocksize,
11318 null_source, &to_pull);
11319 if (!NT_STATUS_IS_OK(status)) {
11320 printf("cli_push returned: %s\n", nt_errstr(status));
11325 seconds = timeval_elapsed(&start_time);
11326 kbytes = (double)torture_blocksize * torture_numops;
11329 printf("Wrote %d kbytes in %.2f seconds: %d kb/sec\n", (int)kbytes,
11330 (double)seconds, (int)(kbytes/seconds));
11334 cli_close(cli1, fnum);
11335 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
11336 torture_close_connection(cli1);
11340 static size_t calc_expected_return(struct cli_state *cli, size_t len_requested)
11342 size_t max_pdu = 0x1FFFF;
11344 if (cli->server_posix_capabilities & CIFS_UNIX_LARGE_READ_CAP) {
11345 max_pdu = 0xFFFFFF;
11348 if (smb1cli_conn_signing_is_active(cli->conn)) {
11352 if (smb1cli_conn_encryption_on(cli->conn)) {
11353 max_pdu = CLI_BUFFER_SIZE;
11356 if ((len_requested & 0xFFFF0000) == 0xFFFF0000) {
11357 len_requested &= 0xFFFF;
11360 return MIN(len_requested,
11361 max_pdu - (MIN_SMB_SIZE + VWV(12) + 1 /* padding byte */));
11364 static bool check_read_call(struct cli_state *cli,
11367 size_t len_requested)
11370 struct tevent_req *subreq = NULL;
11371 ssize_t len_read = 0;
11372 size_t len_expected = 0;
11373 struct tevent_context *ev = NULL;
11375 ev = samba_tevent_context_init(talloc_tos());
11380 subreq = cli_read_andx_send(talloc_tos(),
11387 if (!tevent_req_poll_ntstatus(subreq, ev, &status)) {
11391 status = cli_read_andx_recv(subreq, &len_read, &buf);
11392 if (!NT_STATUS_IS_OK(status)) {
11393 d_printf("cli_read_andx_recv failed: %s\n", nt_errstr(status));
11397 TALLOC_FREE(subreq);
11400 len_expected = calc_expected_return(cli, len_requested);
11402 if (len_expected > 0x10000 && len_read == 0x10000) {
11403 /* Windows servers only return a max of 0x10000,
11404 doesn't matter if you set CAP_LARGE_READX in
11405 the client sessionsetupX call or not. */
11406 d_printf("Windows server - returned 0x10000 on a read of 0x%x\n",
11407 (unsigned int)len_requested);
11408 } else if (len_read != len_expected) {
11409 d_printf("read of 0x%x failed: got 0x%x, expected 0x%x\n",
11410 (unsigned int)len_requested,
11411 (unsigned int)len_read,
11412 (unsigned int)len_expected);
11415 d_printf("Correct read reply.\n");
11421 /* Test large readX variants. */
11422 static bool large_readx_tests(struct cli_state *cli,
11426 /* A read of 0xFFFF0001 should *always* return 1 byte. */
11427 if (check_read_call(cli, fnum, buf, 0xFFFF0001) == false) {
11430 /* A read of 0x10000 should return 0x10000 bytes. */
11431 if (check_read_call(cli, fnum, buf, 0x10000) == false) {
11434 /* A read of 0x10000 should return 0x10001 bytes. */
11435 if (check_read_call(cli, fnum, buf, 0x10001) == false) {
11438 /* A read of 0x1FFFF - (MIN_SMB_SIZE + VWV(12) should return
11439 the requested number of bytes. */
11440 if (check_read_call(cli, fnum, buf, 0x1FFFF - (MIN_SMB_SIZE + VWV(12))) == false) {
11443 /* A read of 1MB should return 1MB bytes (on Samba). */
11444 if (check_read_call(cli, fnum, buf, 0x100000) == false) {
11448 if (check_read_call(cli, fnum, buf, 0x20001) == false) {
11451 if (check_read_call(cli, fnum, buf, 0x22000001) == false) {
11454 if (check_read_call(cli, fnum, buf, 0xFFFE0001) == false) {
11460 static bool run_large_readx(int dummy)
11462 uint8_t *buf = NULL;
11463 struct cli_state *cli1 = NULL;
11464 struct cli_state *cli2 = NULL;
11465 bool correct = false;
11466 const char *fname = "\\large_readx.dat";
11468 uint16_t fnum1 = UINT16_MAX;
11469 uint32_t normal_caps = 0;
11470 size_t file_size = 20*1024*1024;
11471 TALLOC_CTX *frame = talloc_stackframe();
11475 enum smb_signing_setting signing_setting;
11476 enum protocol_types protocol;
11480 .signing_setting = SMB_SIGNING_IF_REQUIRED,
11481 .protocol = PROTOCOL_NT1,
11483 .name = "NT1 - SIGNING_REQUIRED",
11484 .signing_setting = SMB_SIGNING_REQUIRED,
11485 .protocol = PROTOCOL_NT1,
11489 printf("starting large_readx test\n");
11491 if (!torture_open_connection(&cli1, 0)) {
11495 normal_caps = smb1cli_conn_capabilities(cli1->conn);
11497 if (!(normal_caps & CAP_LARGE_READX)) {
11498 d_printf("Server doesn't have CAP_LARGE_READX 0x%x\n",
11499 (unsigned int)normal_caps);
11503 /* Create a file of size 4MB. */
11504 status = cli_ntcreate(cli1, fname, 0, GENERIC_ALL_ACCESS,
11505 FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
11506 0, 0, &fnum1, NULL);
11508 if (!NT_STATUS_IS_OK(status)) {
11509 d_printf("open %s failed: %s\n", fname, nt_errstr(status));
11513 /* Write file_size bytes. */
11514 buf = talloc_zero_array(frame, uint8_t, file_size);
11519 status = cli_writeall(cli1,
11526 if (!NT_STATUS_IS_OK(status)) {
11527 d_printf("cli_writeall failed: %s\n", nt_errstr(status));
11531 status = cli_close(cli1, fnum1);
11532 if (!NT_STATUS_IS_OK(status)) {
11533 d_printf("cli_close failed: %s\n", nt_errstr(status));
11537 fnum1 = UINT16_MAX;
11539 for (i=0; i < ARRAY_SIZE(runs); i++) {
11540 enum smb_signing_setting saved_signing_setting = signing_state;
11541 uint16_t fnum2 = -1;
11544 (runs[i].signing_setting == SMB_SIGNING_REQUIRED))
11546 d_printf("skip[%u] - %s\n", (unsigned)i, runs[i].name);
11550 d_printf("run[%u] - %s\n", (unsigned)i, runs[i].name);
11552 signing_state = runs[i].signing_setting;
11553 cli2 = open_nbt_connection();
11554 signing_state = saved_signing_setting;
11555 if (cli2 == NULL) {
11559 status = smbXcli_negprot(cli2->conn,
11566 if (!NT_STATUS_IS_OK(status)) {
11570 status = cli_session_setup_creds(cli2, torture_creds);
11571 if (!NT_STATUS_IS_OK(status)) {
11575 status = cli_tree_connect(cli2,
11579 if (!NT_STATUS_IS_OK(status)) {
11583 cli_set_timeout(cli2, 120000); /* set a really long timeout (2 minutes) */
11585 normal_caps = smb1cli_conn_capabilities(cli2->conn);
11587 if (!(normal_caps & CAP_LARGE_READX)) {
11588 d_printf("Server doesn't have CAP_LARGE_READX 0x%x\n",
11589 (unsigned int)normal_caps);
11594 if (force_cli_encryption(cli2, share) == false) {
11597 } else if (SERVER_HAS_UNIX_CIFS(cli2)) {
11598 uint16_t major, minor;
11599 uint32_t caplow, caphigh;
11601 status = cli_unix_extensions_version(cli2,
11603 &caplow, &caphigh);
11604 if (!NT_STATUS_IS_OK(status)) {
11609 status = cli_ntcreate(cli2, fname, 0, FILE_READ_DATA,
11610 FILE_ATTRIBUTE_NORMAL, 0, FILE_OPEN,
11611 0, 0, &fnum2, NULL);
11612 if (!NT_STATUS_IS_OK(status)) {
11613 d_printf("Second open %s failed: %s\n", fname, nt_errstr(status));
11617 /* All reads must return less than file_size bytes. */
11618 if (!large_readx_tests(cli2, fnum2, buf)) {
11622 status = cli_close(cli2, fnum2);
11623 if (!NT_STATUS_IS_OK(status)) {
11624 d_printf("cli_close failed: %s\n", nt_errstr(status));
11629 if (!torture_close_connection(cli2)) {
11636 printf("Success on large_readx test\n");
11641 if (!torture_close_connection(cli2)) {
11647 if (fnum1 != UINT16_MAX) {
11648 status = cli_close(cli1, fnum1);
11649 if (!NT_STATUS_IS_OK(status)) {
11650 d_printf("cli_close failed: %s\n", nt_errstr(status));
11652 fnum1 = UINT16_MAX;
11655 status = cli_unlink(cli1, fname,
11656 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
11657 if (!NT_STATUS_IS_OK(status)) {
11658 printf("unlink failed (%s)\n", nt_errstr(status));
11661 if (!torture_close_connection(cli1)) {
11666 TALLOC_FREE(frame);
11668 printf("finished large_readx test\n");
11672 static NTSTATUS msdfs_attribute_list_fn(struct file_info *finfo,
11674 void *private_data)
11676 uint32_t *p_attr = (uint32_t *)private_data;
11678 if (strequal(finfo->name, test_filename)) {
11679 *p_attr = finfo->attr;
11682 return NT_STATUS_OK;
11685 static bool run_msdfs_attribute(int dummy)
11687 static struct cli_state *cli;
11688 bool correct = false;
11692 printf("Starting MSDFS-ATTRIBUTE test\n");
11694 if (test_filename == NULL || test_filename[0] == '\0') {
11695 printf("MSDFS-ATTRIBUTE test "
11696 "needs -f filename-of-msdfs-link\n");
11701 * NB. We use torture_open_connection_flags() not
11702 * torture_open_connection() as the latter forces
11705 if (!torture_open_connection_flags(&cli, 0, 0)) {
11709 smbXcli_conn_set_sockopt(cli->conn, sockops);
11711 status = cli_list(cli,
11713 FILE_ATTRIBUTE_DIRECTORY,
11714 msdfs_attribute_list_fn,
11717 if (!NT_STATUS_IS_OK(status)) {
11718 printf("cli_list failed with %s\n",
11719 nt_errstr(status));
11722 if ((attr & FILE_ATTRIBUTE_REPARSE_POINT) == 0) {
11723 printf("file %s should have "
11724 "FILE_ATTRIBUTE_REPARSE_POINT set. attr = 0x%x\n",
11726 (unsigned int)attr);
11730 if ((attr & FILE_ATTRIBUTE_DIRECTORY) == 0) {
11731 printf("file %s should have "
11732 "FILE_ATTRIBUTE_DIRECTORY set. attr = 0x%x\n",
11734 (unsigned int)attr);
11742 torture_close_connection(cli);
11746 static bool run_cli_echo(int dummy)
11748 struct cli_state *cli;
11751 printf("starting cli_echo test\n");
11752 if (!torture_open_connection(&cli, 0)) {
11755 smbXcli_conn_set_sockopt(cli->conn, sockops);
11757 status = cli_echo(cli, 5, data_blob_const("hello", 5));
11759 d_printf("cli_echo returned %s\n", nt_errstr(status));
11761 torture_close_connection(cli);
11762 return NT_STATUS_IS_OK(status);
11765 static int splice_status(off_t written, void *priv)
11770 static bool run_cli_splice(int dummy)
11772 uint8_t *buf = NULL;
11773 struct cli_state *cli1 = NULL;
11774 bool correct = false;
11775 const char *fname_src = "\\splice_src.dat";
11776 const char *fname_dst = "\\splice_dst.dat";
11778 uint16_t fnum1 = UINT16_MAX;
11779 uint16_t fnum2 = UINT16_MAX;
11780 size_t file_size = 2*1024*1024;
11781 size_t splice_size = 1*1024*1024 + 713;
11782 uint8_t digest1[16], digest2[16];
11785 TALLOC_CTX *frame = talloc_stackframe();
11787 printf("starting cli_splice test\n");
11789 if (!torture_open_connection(&cli1, 0)) {
11793 cli_unlink(cli1, fname_src,
11794 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
11795 cli_unlink(cli1, fname_dst,
11796 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
11798 /* Create a file */
11799 status = cli_ntcreate(cli1, fname_src, 0, GENERIC_ALL_ACCESS,
11800 FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
11801 0, 0, &fnum1, NULL);
11803 if (!NT_STATUS_IS_OK(status)) {
11804 d_printf("open %s failed: %s\n", fname_src, nt_errstr(status));
11808 /* Write file_size bytes - must be bigger than splice_size. */
11809 buf = talloc_zero_array(frame, uint8_t, file_size);
11811 d_printf("talloc_fail\n");
11815 /* Fill it with random numbers. */
11816 generate_random_buffer(buf, file_size);
11818 /* MD5 the first 1MB + 713 bytes. */
11819 gnutls_hash_fast(GNUTLS_DIG_MD5,
11824 status = cli_writeall(cli1,
11831 if (!NT_STATUS_IS_OK(status)) {
11832 d_printf("cli_writeall failed: %s\n", nt_errstr(status));
11836 status = cli_ntcreate(cli1, fname_dst, 0, GENERIC_ALL_ACCESS,
11837 FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
11838 0, 0, &fnum2, NULL);
11840 if (!NT_STATUS_IS_OK(status)) {
11841 d_printf("open %s failed: %s\n", fname_dst, nt_errstr(status));
11845 /* Now splice 1MB + 713 bytes. */
11846 status = cli_splice(cli1,
11857 if (!NT_STATUS_IS_OK(status)) {
11858 d_printf("cli_splice failed: %s\n", nt_errstr(status));
11862 /* Clear the old buffer. */
11863 memset(buf, '\0', file_size);
11865 /* Read the new file. */
11866 status = cli_read(cli1, fnum2, (char *)buf, 0, splice_size, &nread);
11867 if (!NT_STATUS_IS_OK(status)) {
11868 d_printf("cli_read failed: %s\n", nt_errstr(status));
11871 if (nread != splice_size) {
11872 d_printf("bad read of 0x%x, should be 0x%x\n",
11873 (unsigned int)nread,
11874 (unsigned int)splice_size);
11878 /* MD5 the first 1MB + 713 bytes. */
11879 gnutls_hash_fast(GNUTLS_DIG_MD5,
11884 /* Must be the same. */
11885 if (memcmp(digest1, digest2, 16) != 0) {
11886 d_printf("bad MD5 compare\n");
11891 printf("Success on cli_splice test\n");
11896 if (fnum1 != UINT16_MAX) {
11897 cli_close(cli1, fnum1);
11899 if (fnum2 != UINT16_MAX) {
11900 cli_close(cli1, fnum2);
11903 cli_unlink(cli1, fname_src,
11904 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
11905 cli_unlink(cli1, fname_dst,
11906 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
11908 if (!torture_close_connection(cli1)) {
11913 TALLOC_FREE(frame);
11917 static bool run_uid_regression_test(int dummy)
11919 static struct cli_state *cli;
11922 bool correct = True;
11923 struct smbXcli_tcon *tcon_copy = NULL;
11926 printf("starting uid regression test\n");
11928 if (!torture_open_connection(&cli, 0)) {
11932 smbXcli_conn_set_sockopt(cli->conn, sockops);
11934 /* Ok - now save then logoff our current user. */
11935 old_vuid = cli_state_get_uid(cli);
11937 status = cli_ulogoff(cli);
11938 if (!NT_STATUS_IS_OK(status)) {
11939 d_printf("(%s) cli_ulogoff failed: %s\n",
11940 __location__, nt_errstr(status));
11945 cli_state_set_uid(cli, old_vuid);
11947 /* Try an operation. */
11948 status = cli_mkdir(cli, "\\uid_reg_test");
11949 if (NT_STATUS_IS_OK(status)) {
11950 d_printf("(%s) cli_mkdir succeeded\n",
11955 /* Should be bad uid. */
11956 if (!check_error(__LINE__, status, ERRSRV, ERRbaduid,
11957 NT_STATUS_USER_SESSION_DELETED)) {
11963 old_cnum = cli_state_get_tid(cli);
11965 * This is an SMB1-only test.
11966 * Copy the tcon, not "save/restore".
11968 * In SMB1 the cli_tdis() below frees
11969 * cli->smb1.tcon so we need a copy
11970 * of the struct to put back for the
11971 * second tdis call with invalid vuid.
11973 * This is a test-only hack. Real client code
11974 * uses cli_state_save_tcon_share()/cli_state_restore_tcon_share().
11976 tcon_copy = smbXcli_tcon_copy(cli, cli->smb1.tcon);
11977 if (tcon_copy == NULL) {
11982 /* Now try a SMBtdis with the invalid vuid set to zero. */
11983 cli_state_set_uid(cli, 0);
11985 /* This should succeed. */
11986 status = cli_tdis(cli);
11988 if (NT_STATUS_IS_OK(status)) {
11989 d_printf("First tdis with invalid vuid should succeed.\n");
11991 d_printf("First tdis failed (%s)\n", nt_errstr(status));
11993 cli->smb1.tcon = tcon_copy;
11997 cli->smb1.tcon = tcon_copy;
11998 cli_state_set_uid(cli, old_vuid);
11999 cli_state_set_tid(cli, old_cnum);
12001 /* This should fail. */
12002 status = cli_tdis(cli);
12003 if (NT_STATUS_IS_OK(status)) {
12004 d_printf("Second tdis with invalid vuid should fail - succeeded instead !.\n");
12008 /* Should be bad tid. */
12009 if (!check_error(__LINE__, status, ERRSRV, ERRinvnid,
12010 NT_STATUS_NETWORK_NAME_DELETED)) {
12016 cli_rmdir(cli, "\\uid_reg_test");
12025 static const char *illegal_chars = "*\\/?<>|\":";
12026 static char force_shortname_chars[] = " +,.[];=\177";
12028 static NTSTATUS shortname_del_fn(struct file_info *finfo,
12029 const char *mask, void *state)
12031 struct cli_state *pcli = (struct cli_state *)state;
12033 NTSTATUS status = NT_STATUS_OK;
12035 slprintf(fname, sizeof(fname), "\\shortname\\%s", finfo->name);
12037 if (strcmp(finfo->name, ".") == 0 || strcmp(finfo->name, "..") == 0)
12038 return NT_STATUS_OK;
12040 if (finfo->attr & FILE_ATTRIBUTE_DIRECTORY) {
12041 status = cli_rmdir(pcli, fname);
12042 if (!NT_STATUS_IS_OK(status)) {
12043 printf("del_fn: failed to rmdir %s\n,", fname );
12046 status = cli_unlink(pcli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
12047 if (!NT_STATUS_IS_OK(status)) {
12048 printf("del_fn: failed to unlink %s\n,", fname );
12060 static NTSTATUS shortname_list_fn(struct file_info *finfo,
12061 const char *name, void *state)
12063 struct sn_state *s = (struct sn_state *)state;
12067 printf("shortname list: i = %d, name = |%s|, shortname = |%s|\n",
12068 i, finfo->name, finfo->short_name);
12071 if (strchr(force_shortname_chars, i)) {
12072 if (!finfo->short_name) {
12073 /* Shortname not created when it should be. */
12074 d_printf("(%s) ERROR: Shortname was not created for file %s containing %d\n",
12075 __location__, finfo->name, i);
12078 } else if (finfo->short_name){
12079 /* Shortname created when it should not be. */
12080 d_printf("(%s) ERROR: Shortname %s was created for file %s\n",
12081 __location__, finfo->short_name, finfo->name);
12085 return NT_STATUS_OK;
12088 static bool run_shortname_test(int dummy)
12090 static struct cli_state *cli;
12091 bool correct = True;
12097 printf("starting shortname test\n");
12099 if (!torture_open_connection(&cli, 0)) {
12103 smbXcli_conn_set_sockopt(cli->conn, sockops);
12105 cli_list(cli, "\\shortname\\*", 0, shortname_del_fn, cli);
12106 cli_list(cli, "\\shortname\\*", FILE_ATTRIBUTE_DIRECTORY, shortname_del_fn, cli);
12107 cli_rmdir(cli, "\\shortname");
12109 status = cli_mkdir(cli, "\\shortname");
12110 if (!NT_STATUS_IS_OK(status)) {
12111 d_printf("(%s) cli_mkdir of \\shortname failed: %s\n",
12112 __location__, nt_errstr(status));
12117 if (strlcpy(fname, "\\shortname\\", sizeof(fname)) >= sizeof(fname)) {
12121 if (strlcat(fname, "test .txt", sizeof(fname)) >= sizeof(fname)) {
12128 for (i = 32; i < 128; i++) {
12129 uint16_t fnum = (uint16_t)-1;
12133 if (strchr(illegal_chars, i)) {
12138 status = cli_ntcreate(cli, fname, 0, GENERIC_ALL_ACCESS, FILE_ATTRIBUTE_NORMAL,
12139 FILE_SHARE_READ|FILE_SHARE_WRITE,
12140 FILE_OVERWRITE_IF, 0, 0, &fnum, NULL);
12141 if (!NT_STATUS_IS_OK(status)) {
12142 d_printf("(%s) cli_nt_create of %s failed: %s\n",
12143 __location__, fname, nt_errstr(status));
12147 cli_close(cli, fnum);
12150 status = cli_list(cli, "\\shortname\\test*.*", 0,
12151 shortname_list_fn, &s);
12152 if (s.matched != 1) {
12153 d_printf("(%s) failed to list %s: %s\n",
12154 __location__, fname, nt_errstr(status));
12159 status = cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
12160 if (!NT_STATUS_IS_OK(status)) {
12161 d_printf("(%s) failed to delete %s: %s\n",
12162 __location__, fname, nt_errstr(status));
12175 cli_list(cli, "\\shortname\\*", 0, shortname_del_fn, cli);
12176 cli_list(cli, "\\shortname\\*", FILE_ATTRIBUTE_DIRECTORY, shortname_del_fn, cli);
12177 cli_rmdir(cli, "\\shortname");
12178 torture_close_connection(cli);
12182 TLDAPRC callback_code;
12184 static void pagedsearch_cb(struct tevent_req *req)
12187 struct tldap_message *msg;
12190 rc = tldap_search_paged_recv(req, talloc_tos(), &msg);
12191 if (!TLDAP_RC_IS_SUCCESS(rc)) {
12192 d_printf("tldap_search_paged_recv failed: %s\n",
12193 tldap_rc2string(rc));
12194 callback_code = rc;
12197 if (tldap_msg_type(msg) != TLDAP_RES_SEARCH_ENTRY) {
12201 if (!tldap_entry_dn(msg, &dn)) {
12202 d_printf("tldap_entry_dn failed\n");
12205 d_printf("%s\n", dn);
12209 enum tldap_extended_val {
12216 * Construct an extended dn control with either no value, 0 or 1
12218 * No value and 0 are equivalent (non-hyphenated GUID)
12219 * 1 has the hyphenated GUID
12221 static struct tldap_control *
12222 tldap_build_extended_control(enum tldap_extended_val val)
12224 struct tldap_control empty_control;
12225 struct asn1_data *data;
12227 ZERO_STRUCT(empty_control);
12229 if (val != EXTENDED_NONE) {
12230 data = asn1_init(talloc_tos(), ASN1_MAX_TREE_DEPTH);
12236 if (!asn1_push_tag(data, ASN1_SEQUENCE(0))) {
12240 if (!asn1_write_Integer(data, (int)val)) {
12244 if (!asn1_pop_tag(data)) {
12248 if (!asn1_blob(data, &empty_control.value)) {
12253 empty_control.oid = "1.2.840.113556.1.4.529";
12254 empty_control.critical = true;
12256 return tldap_add_control(talloc_tos(), NULL, 0, &empty_control);
12260 static bool tldap_test_dn_guid_format(struct tldap_context *ld, const char *basedn,
12261 enum tldap_extended_val control_val)
12263 struct tldap_control *control = tldap_build_extended_control(control_val);
12265 struct tldap_message **msg;
12268 rc = tldap_search(ld, basedn, TLDAP_SCOPE_BASE,
12269 "(objectClass=*)", NULL, 0, 0,
12271 0, 0, 0, 0, talloc_tos(), &msg);
12272 if (!TLDAP_RC_IS_SUCCESS(rc)) {
12273 d_printf("tldap_search for domain DN failed: %s\n",
12274 tldap_errstr(talloc_tos(), ld, rc));
12278 if (!tldap_entry_dn(msg[0], &dn)) {
12279 d_printf("tldap_search domain DN fetch failed: %s\n",
12280 tldap_errstr(talloc_tos(), ld, rc));
12284 d_printf("%s\n", dn);
12287 uint32_t time_mid, time_hi_and_version;
12288 uint32_t clock_seq[2];
12292 switch (control_val) {
12293 case EXTENDED_NONE:
12294 case EXTENDED_ZERO:
12296 * When reading GUIDs with hyphens, scanf will treat
12297 * hyphen as a hex character (and counts as part of the
12298 * width). This creates leftover GUID string which we
12299 * check will for with 'next' and closing '>'.
12301 if (12 == sscanf(dn, "<GUID=%08x%04x%04x%02x%02x%02x%02x%02x%02x%02x%02x>%c",
12302 &time_low, &time_mid,
12303 &time_hi_and_version, &clock_seq[0],
12304 &clock_seq[1], &node[0], &node[1],
12305 &node[2], &node[3], &node[4],
12306 &node[5], &next)) {
12307 /* This GUID is good */
12309 d_printf("GUID format in control (no hyphens) doesn't match output\n");
12315 if (12 == sscanf(dn,
12316 "<GUID=%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x>%c",
12317 &time_low, &time_mid,
12318 &time_hi_and_version, &clock_seq[0],
12319 &clock_seq[1], &node[0], &node[1],
12320 &node[2], &node[3], &node[4],
12321 &node[5], &next)) {
12322 /* This GUID is good */
12324 d_printf("GUID format in control (with hyphens) doesn't match output\n");
12337 static bool run_tldap(int dummy)
12339 struct tldap_context *ld;
12343 struct sockaddr_storage addr;
12344 struct tevent_context *ev;
12345 struct tevent_req *req;
12347 const char *filter;
12349 if (!resolve_name(host, &addr, 0, false)) {
12350 d_printf("could not find host %s\n", host);
12353 status = open_socket_out(&addr, 389, 9999, &fd);
12354 if (!NT_STATUS_IS_OK(status)) {
12355 d_printf("open_socket_out failed: %s\n", nt_errstr(status));
12359 ld = tldap_context_create(talloc_tos(), fd);
12362 d_printf("tldap_context_create failed\n");
12366 rc = tldap_fetch_rootdse(ld);
12367 if (!TLDAP_RC_IS_SUCCESS(rc)) {
12368 d_printf("tldap_fetch_rootdse failed: %s\n",
12369 tldap_errstr(talloc_tos(), ld, rc));
12373 basedn = tldap_talloc_single_attribute(
12374 tldap_rootdse(ld), "defaultNamingContext", talloc_tos());
12375 if (basedn == NULL) {
12376 d_printf("no defaultNamingContext\n");
12379 d_printf("defaultNamingContext: %s\n", basedn);
12381 ev = samba_tevent_context_init(talloc_tos());
12383 d_printf("tevent_context_init failed\n");
12387 rc = tldap_gensec_bind(ld, torture_creds, "ldap", host, NULL,
12388 loadparm_init_s3(talloc_tos(),
12389 loadparm_s3_helpers()),
12390 GENSEC_FEATURE_SIGN | GENSEC_FEATURE_SEAL);
12392 if (!TLDAP_RC_IS_SUCCESS(rc)) {
12393 d_printf("tldap_gensec_bind failed\n");
12397 callback_code = TLDAP_SUCCESS;
12399 req = tldap_search_paged_send(talloc_tos(), ev, ld, basedn,
12400 TLDAP_SCOPE_SUB, "(objectclass=*)",
12402 NULL, 0, NULL, 0, 0, 0, 0, 5);
12404 d_printf("tldap_search_paged_send failed\n");
12407 tevent_req_set_callback(req, pagedsearch_cb, NULL);
12409 tevent_req_poll(req, ev);
12413 rc = callback_code;
12415 if (!TLDAP_RC_IS_SUCCESS(rc)) {
12416 d_printf("tldap_search with paging failed: %s\n",
12417 tldap_errstr(talloc_tos(), ld, rc));
12421 /* test search filters against rootDSE */
12422 filter = "(&(|(name=samba)(nextRid<=10000000)(usnChanged>=10)(samba~=ambas)(!(name=s*m*a)))"
12423 "(|(name:=samba)(name:dn:2.5.13.5:=samba)(:dn:2.5.13.5:=samba)(!(name=*samba))))";
12425 rc = tldap_search(ld, "", TLDAP_SCOPE_BASE, filter,
12426 NULL, 0, 0, NULL, 0, NULL, 0, 0, 0, 0,
12427 talloc_tos(), NULL);
12428 if (!TLDAP_RC_IS_SUCCESS(rc)) {
12429 d_printf("tldap_search with complex filter failed: %s\n",
12430 tldap_errstr(talloc_tos(), ld, rc));
12435 * Tests to check for regression of:
12437 * https://bugzilla.samba.org/show_bug.cgi?id=14029
12439 * TLDAP used here to pick apart the original string DN (with GUID)
12441 if (!tldap_test_dn_guid_format(ld, basedn, EXTENDED_NONE)) {
12442 d_printf("tldap_search with extended dn (no val) failed: %s\n",
12443 tldap_errstr(talloc_tos(), ld, rc));
12446 if (!tldap_test_dn_guid_format(ld, basedn, EXTENDED_ZERO)) {
12447 d_printf("tldap_search with extended dn (0) failed: %s\n",
12448 tldap_errstr(talloc_tos(), ld, rc));
12451 if (!tldap_test_dn_guid_format(ld, basedn, EXTENDED_ONE)) {
12452 d_printf("tldap_search with extended dn (1) failed: %s\n",
12453 tldap_errstr(talloc_tos(), ld, rc));
12461 /* Torture test to ensure no regression of :
12462 https://bugzilla.samba.org/show_bug.cgi?id=7084
12465 static bool run_dir_createtime(int dummy)
12467 struct cli_state *cli;
12468 const char *dname = "\\testdir_createtime";
12469 const char *fname = "\\testdir_createtime\\testfile";
12471 struct timespec create_time;
12472 struct timespec create_time1;
12477 if (!torture_open_connection(&cli, 0)) {
12481 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
12482 /* Ensure ino is zero, SMB2 gets a real one. */
12485 /* Ensure ino is -1, SMB1 never gets a real one. */
12486 ino = (uint64_t)-1;
12489 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
12490 cli_rmdir(cli, dname);
12492 status = cli_mkdir(cli, dname);
12493 if (!NT_STATUS_IS_OK(status)) {
12494 printf("mkdir failed: %s\n", nt_errstr(status));
12498 status = cli_qpathinfo2(cli,
12508 if (!NT_STATUS_IS_OK(status)) {
12509 printf("cli_qpathinfo2 returned %s\n",
12510 nt_errstr(status));
12514 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
12515 /* SMB2 should always return an inode. */
12517 printf("SMB2 bad inode (0)\n");
12521 /* SMB1 must always return zero here. */
12523 printf("SMB1 bad inode (!0)\n");
12528 /* Sleep 3 seconds, then create a file. */
12531 status = cli_openx(cli, fname, O_RDWR | O_CREAT | O_EXCL,
12533 if (!NT_STATUS_IS_OK(status)) {
12534 printf("cli_openx failed: %s\n", nt_errstr(status));
12538 status = cli_qpathinfo2(cli,
12548 if (!NT_STATUS_IS_OK(status)) {
12549 printf("cli_qpathinfo2 (2) returned %s\n",
12550 nt_errstr(status));
12554 if (timespec_compare(&create_time1, &create_time)) {
12555 printf("run_dir_createtime: create time was updated (error)\n");
12557 printf("run_dir_createtime: create time was not updated (correct)\n");
12563 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
12564 cli_rmdir(cli, dname);
12565 if (!torture_close_connection(cli)) {
12572 static bool run_streamerror(int dummy)
12574 struct cli_state *cli;
12575 const char *dname = "\\testdir_streamerror";
12576 const char *streamname =
12577 "testdir_streamerror:{4c8cc155-6c1e-11d1-8e41-00c04fb9386d}:$DATA";
12579 time_t change_time, access_time, write_time;
12585 if (!torture_open_connection(&cli, 0)) {
12589 torture_deltree(cli, dname);
12591 status = cli_mkdir(cli, dname);
12592 if (!NT_STATUS_IS_OK(status)) {
12593 printf("mkdir failed: %s\n", nt_errstr(status));
12597 status = cli_qpathinfo1(cli, streamname, &change_time, &access_time,
12598 &write_time, &size, &attr);
12599 if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
12600 printf("pathinfo returned %s, expected "
12601 "NT_STATUS_OBJECT_NAME_NOT_FOUND\n",
12602 nt_errstr(status));
12606 status = cli_ntcreate(cli, streamname, 0x16,
12607 FILE_READ_DATA|FILE_READ_EA|
12608 FILE_READ_ATTRIBUTES|READ_CONTROL_ACCESS,
12609 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ,
12610 FILE_OPEN, 0, 0, &fnum, NULL);
12612 if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
12613 printf("ntcreate returned %s, expected "
12614 "NT_STATUS_OBJECT_NAME_NOT_FOUND\n",
12615 nt_errstr(status));
12620 cli_rmdir(cli, dname);
12624 struct pidtest_state {
12630 static void pid_echo_done(struct tevent_req *subreq);
12632 static struct tevent_req *pid_echo_send(TALLOC_CTX *mem_ctx,
12633 struct tevent_context *ev,
12634 struct cli_state *cli)
12636 struct tevent_req *req, *subreq;
12637 struct pidtest_state *state;
12639 req = tevent_req_create(mem_ctx, &state, struct pidtest_state);
12644 SSVAL(state->vwv, 0, 1);
12645 state->data = data_blob_const("hello", 5);
12647 subreq = smb1cli_req_send(state,
12651 0, 0, /* *_flags */
12652 0, 0, /* *_flags2 */
12654 0xDEADBEEF, /* pid */
12656 NULL, /* session */
12657 ARRAY_SIZE(state->vwv), state->vwv,
12658 state->data.length, state->data.data);
12660 if (tevent_req_nomem(subreq, req)) {
12661 return tevent_req_post(req, ev);
12663 tevent_req_set_callback(subreq, pid_echo_done, req);
12667 static void pid_echo_done(struct tevent_req *subreq)
12669 struct tevent_req *req = tevent_req_callback_data(
12670 subreq, struct tevent_req);
12671 struct pidtest_state *state = tevent_req_data(
12672 req, struct pidtest_state);
12674 uint32_t num_bytes;
12675 uint8_t *bytes = NULL;
12676 struct iovec *recv_iov = NULL;
12677 uint8_t *phdr = NULL;
12678 uint16_t pidlow = 0;
12679 uint16_t pidhigh = 0;
12680 struct smb1cli_req_expected_response expected[] = {
12682 .status = NT_STATUS_OK,
12687 status = smb1cli_req_recv(subreq, state,
12692 NULL, /* pvwv_offset */
12695 NULL, /* pbytes_offset */
12697 expected, ARRAY_SIZE(expected));
12699 TALLOC_FREE(subreq);
12701 if (!NT_STATUS_IS_OK(status)) {
12702 tevent_req_nterror(req, status);
12706 if (num_bytes != state->data.length) {
12707 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
12711 if (memcmp(bytes, state->data.data, num_bytes) != 0) {
12712 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
12716 /* Check pid low/high == DEADBEEF */
12717 pidlow = SVAL(phdr, HDR_PID);
12718 if (pidlow != 0xBEEF){
12719 printf("Incorrect pidlow 0x%x, should be 0xBEEF\n",
12720 (unsigned int)pidlow);
12721 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
12724 pidhigh = SVAL(phdr, HDR_PIDHIGH);
12725 if (pidhigh != 0xDEAD){
12726 printf("Incorrect pidhigh 0x%x, should be 0xDEAD\n",
12727 (unsigned int)pidhigh);
12728 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
12732 tevent_req_done(req);
12735 static NTSTATUS pid_echo_recv(struct tevent_req *req)
12737 return tevent_req_simple_recv_ntstatus(req);
12740 static bool run_pidhigh(int dummy)
12742 bool success = false;
12743 struct cli_state *cli = NULL;
12745 struct tevent_context *ev = NULL;
12746 struct tevent_req *req = NULL;
12747 TALLOC_CTX *frame = talloc_stackframe();
12749 printf("starting pid high test\n");
12750 if (!torture_open_connection(&cli, 0)) {
12753 smbXcli_conn_set_sockopt(cli->conn, sockops);
12755 ev = samba_tevent_context_init(frame);
12760 req = pid_echo_send(frame, ev, cli);
12765 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
12769 status = pid_echo_recv(req);
12770 if (NT_STATUS_IS_OK(status)) {
12771 printf("pid high test ok\n");
12777 TALLOC_FREE(frame);
12778 torture_close_connection(cli);
12783 Test Windows open on a bad POSIX symlink.
12785 static bool run_symlink_open_test(int dummy)
12787 static struct cli_state *cli;
12788 const char *fname = "non_existant_file";
12789 const char *sname = "dangling_symlink";
12790 uint16_t fnum = (uint16_t)-1;
12791 bool correct = false;
12793 TALLOC_CTX *frame = NULL;
12795 frame = talloc_stackframe();
12797 printf("Starting Windows bad symlink open test\n");
12799 if (!torture_open_connection(&cli, 0)) {
12800 TALLOC_FREE(frame);
12804 smbXcli_conn_set_sockopt(cli->conn, sockops);
12806 status = torture_setup_unix_extensions(cli);
12807 if (!NT_STATUS_IS_OK(status)) {
12808 TALLOC_FREE(frame);
12812 /* Ensure nothing exists. */
12813 cli_setatr(cli, fname, 0, 0);
12814 cli_posix_unlink(cli, fname);
12815 cli_setatr(cli, sname, 0, 0);
12816 cli_posix_unlink(cli, sname);
12818 /* Create a symlink pointing nowhere. */
12819 status = cli_posix_symlink(cli, fname, sname);
12820 if (!NT_STATUS_IS_OK(status)) {
12821 printf("cli_posix_symlink of %s -> %s failed (%s)\n",
12824 nt_errstr(status));
12828 /* Now ensure that a Windows open doesn't hang. */
12829 status = cli_ntcreate(cli,
12832 FILE_READ_DATA|FILE_WRITE_DATA,
12834 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
12842 * We get either NT_STATUS_OBJECT_NAME_NOT_FOUND or
12843 * NT_STATUS_OBJECT_PATH_NOT_FOUND depending on if
12844 * we use O_NOFOLLOW on the server or not.
12846 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND) ||
12847 NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_PATH_NOT_FOUND))
12851 printf("cli_ntcreate of %s returned %s - should return"
12852 " either (%s) or (%s)\n",
12855 nt_errstr(NT_STATUS_OBJECT_NAME_NOT_FOUND),
12856 nt_errstr(NT_STATUS_OBJECT_PATH_NOT_FOUND));
12864 if (fnum != (uint16_t)-1) {
12865 cli_close(cli, fnum);
12866 fnum = (uint16_t)-1;
12869 cli_setatr(cli, sname, 0, 0);
12870 cli_posix_unlink(cli, sname);
12871 cli_setatr(cli, fname, 0, 0);
12872 cli_posix_unlink(cli, fname);
12874 if (!torture_close_connection(cli)) {
12878 TALLOC_FREE(frame);
12882 static NTSTATUS smb1_wild_mangle_list_fn(struct file_info *finfo,
12886 char **mangled_name_return = (char **)state;
12887 bool is_mangled = strchr(finfo->name, '~');
12890 *mangled_name_return = talloc_strdup(NULL, finfo->name);
12891 if (*mangled_name_return == NULL) {
12892 return NT_STATUS_NO_MEMORY;
12895 return NT_STATUS_OK;
12898 static bool run_smb1_wild_mangle_unlink_test(int dummy)
12900 static struct cli_state *cli_posix = NULL;
12901 static struct cli_state *cli = NULL;
12902 uint16_t fnum = (uint16_t)-1;
12903 bool correct = false;
12904 const char *dname = "smb1_wild_mangle_unlink";
12905 const char *aname = "smb1_wild_mangle_unlink/a";
12906 const char *star_name = "smb1_wild_mangle_unlink/*";
12907 char *windows_unlink_name = NULL;
12908 char *mangled_name = NULL;
12911 printf("Starting SMB1 wild mangle unlink test\n");
12913 /* Open a Windows connection. */
12914 if (!torture_open_connection(&cli, 0)) {
12918 smbXcli_conn_set_sockopt(cli->conn, sockops);
12920 /* Open a POSIX connection. */
12921 if (!torture_open_connection(&cli_posix, 0)) {
12925 smbXcli_conn_set_sockopt(cli_posix->conn, sockops);
12927 status = torture_setup_unix_extensions(cli_posix);
12928 if (!NT_STATUS_IS_OK(status)) {
12929 printf("server doesn't support POSIX\n");
12934 torture_deltree(cli, dname);
12937 * Create two files - 'a' and '*'.
12938 * We need POSIX extensions for this as '*'
12939 * is not a valid Windows name.
12942 status = cli_mkdir(cli, dname);
12943 if (!NT_STATUS_IS_OK(status)) {
12944 printf("cli_mkdir of %s returned %s\n",
12946 nt_errstr(status));
12950 status = cli_posix_open(cli_posix,
12952 O_RDWR|O_CREAT|O_EXCL,
12955 if (!NT_STATUS_IS_OK(status)) {
12956 printf("cli_posix_open (create) of %s returned %s\n",
12958 nt_errstr(status));
12961 status = cli_close(cli_posix, fnum);
12962 if (!NT_STATUS_IS_OK(status)) {
12965 status = cli_posix_open(cli_posix,
12967 O_RDWR|O_CREAT|O_EXCL,
12970 if (!NT_STATUS_IS_OK(status)) {
12971 printf("cli_posix_open (create) of %s returned %s\n",
12973 nt_errstr(status));
12976 status = cli_close(cli_posix, fnum);
12977 if (!NT_STATUS_IS_OK(status)) {
12981 status = cli_list(cli,
12984 smb1_wild_mangle_list_fn,
12986 if (!NT_STATUS_IS_OK(status)) {
12987 printf("cli_list of %s returned %s\n",
12989 nt_errstr(status));
12993 if (mangled_name == NULL) {
12997 printf("mangled_name = %s\n",
13001 * Try a Windows unlink with the mangled name.
13002 * This should *NOT* unlink the 'a' name.
13005 windows_unlink_name = talloc_asprintf(cli_posix,
13010 status = cli_unlink(cli, windows_unlink_name, 0);
13011 if (!NT_STATUS_IS_OK(status)) {
13012 printf("cli_unlink of %s returned %s\n",
13013 windows_unlink_name,
13014 nt_errstr(status));
13018 /* Does 'a' still exist ? */
13019 status = cli_posix_open(cli_posix,
13024 if (!NT_STATUS_IS_OK(status)) {
13025 printf("cli_posix_open O_RNONLY of %s returned %s\n",
13027 nt_errstr(status));
13031 status = cli_close(cli_posix, fnum);
13032 if (!NT_STATUS_IS_OK(status)) {
13040 TALLOC_FREE(windows_unlink_name);
13041 TALLOC_FREE(mangled_name);
13044 torture_deltree(cli, dname);
13045 torture_close_connection(cli);
13048 if (cli_posix != NULL) {
13049 torture_close_connection(cli_posix);
13055 static bool run_smb1_wild_mangle_rename_test(int dummy)
13057 static struct cli_state *cli_posix = NULL;
13058 static struct cli_state *cli = NULL;
13059 uint16_t fnum = (uint16_t)-1;
13060 bool correct = false;
13061 const char *dname = "smb1_wild_mangle_rename";
13062 const char *fooname = "smb1_wild_mangle_rename/foo";
13063 const char *foostar_name = "smb1_wild_mangle_rename/fo*";
13064 const char *wild_name = "smb1_wild_mangle_rename/*";
13065 char *windows_rename_src = NULL;
13066 const char *windows_rename_dst = "smb1_wild_mangle_rename\\bar";
13067 char *mangled_name = NULL;
13070 printf("Starting SMB1 wild mangle rename test\n");
13072 if (!torture_open_connection(&cli_posix, 0)) {
13076 smbXcli_conn_set_sockopt(cli_posix->conn, sockops);
13078 status = torture_setup_unix_extensions(cli_posix);
13079 if (!NT_STATUS_IS_OK(status)) {
13080 printf("server doesn't support POSIX\n");
13084 /* Open a Windows connection. */
13085 if (!torture_open_connection(&cli, 0)) {
13089 smbXcli_conn_set_sockopt(cli->conn, sockops);
13091 /* Ensure we start from fresh. */
13092 torture_deltree(cli, dname);
13095 * Create two files - 'foo' and 'fo*'.
13096 * We need POSIX extensions for this as 'fo*'
13097 * is not a valid Windows name.
13100 status = cli_posix_mkdir(cli_posix, dname, 0770);
13101 if (!NT_STATUS_IS_OK(status)) {
13102 printf("cli_posix_mkdir of %s returned %s\n",
13104 nt_errstr(status));
13108 status = cli_posix_open(cli_posix,
13110 O_RDWR|O_CREAT|O_EXCL,
13113 if (!NT_STATUS_IS_OK(status)) {
13114 printf("cli_posix_open (create) of %s returned %s\n",
13116 nt_errstr(status));
13119 status = cli_close(cli_posix, fnum);
13120 if (!NT_STATUS_IS_OK(status)) {
13123 status = cli_posix_open(cli_posix,
13125 O_RDWR|O_CREAT|O_EXCL,
13128 if (!NT_STATUS_IS_OK(status)) {
13129 printf("cli_posix_open (create) of %s returned %s\n",
13131 nt_errstr(status));
13134 status = cli_close(cli_posix, fnum);
13135 if (!NT_STATUS_IS_OK(status)) {
13140 * Get the mangled name. We can re-use the
13141 * previous smb1_wild_mangle_list_fn for this.
13144 status = cli_list(cli,
13147 smb1_wild_mangle_list_fn,
13149 if (!NT_STATUS_IS_OK(status)) {
13150 printf("cli_list of %s returned %s\n",
13152 nt_errstr(status));
13156 if (mangled_name == NULL) {
13160 printf("mangled_name = %s\n",
13164 * Try a Windows rename with the mangled name.
13165 * This should *NOT* rename the 'foo' name.
13168 windows_rename_src = talloc_asprintf(cli_posix,
13173 status = cli_rename(cli,
13174 windows_rename_src,
13175 windows_rename_dst,
13177 if (!NT_STATUS_IS_OK(status)) {
13178 printf("cli_rename of %s -> %s returned %s\n",
13179 windows_rename_src,
13180 windows_rename_dst,
13181 nt_errstr(status));
13185 /* Does 'foo' still exist ? */
13186 status = cli_posix_open(cli_posix,
13191 if (!NT_STATUS_IS_OK(status)) {
13192 printf("cli_posix_open O_RNONLY of %s returned %s\n",
13194 nt_errstr(status));
13198 status = cli_close(cli_posix, fnum);
13199 if (!NT_STATUS_IS_OK(status)) {
13207 TALLOC_FREE(mangled_name);
13208 TALLOC_FREE(windows_rename_src);
13211 torture_deltree(cli, dname);
13212 torture_close_connection(cli);
13215 torture_close_connection(cli_posix);
13221 * Only testing minimal time strings, as the others
13222 * need (locale-dependent) guessing at what strftime does and
13223 * even may differ in builds.
13225 static bool timesubst_test(void)
13227 TALLOC_CTX *ctx = NULL;
13228 /* Sa 23. Dez 04:33:20 CET 2017 */
13229 const struct timeval tv = { 1514000000, 123 };
13230 const char* expect_minimal = "20171223_033320";
13231 const char* expect_minus = "20171223_033320_000123";
13233 char *env_tz, *orig_tz = NULL;
13234 bool result = true;
13236 ctx = talloc_new(NULL);
13238 env_tz = getenv("TZ");
13240 orig_tz = talloc_strdup(ctx, env_tz);
13242 setenv("TZ", "UTC", 1);
13244 s = minimal_timeval_string(ctx, &tv, false);
13246 if(!s || strcmp(s, expect_minimal)) {
13247 printf("minimal_timeval_string(ctx, tv, false) returned [%s], expected "
13248 "[%s]\n", s ? s : "<nil>", expect_minimal);
13252 s = minimal_timeval_string(ctx, &tv, true);
13253 if(!s || strcmp(s, expect_minus)) {
13254 printf("minimal_timeval_string(ctx, tv, true) returned [%s], expected "
13255 "[%s]\n", s ? s : "<nil>", expect_minus);
13261 setenv("TZ", orig_tz, 1);
13268 static bool run_local_substitute(int dummy)
13272 ok &= subst_test("%U", "bla", "", -1, -1, "bla");
13273 ok &= subst_test("%u%U", "bla", "", -1, -1, "blabla");
13274 ok &= subst_test("%g", "", "", -1, -1, "NO_GROUP");
13275 ok &= subst_test("%G", "", "", -1, -1, "NO_GROUP");
13276 ok &= subst_test("%g", "", "", -1, 0, gidtoname(0));
13277 ok &= subst_test("%G", "", "", -1, 0, gidtoname(0));
13278 ok &= subst_test("%D%u", "u", "dom", -1, 0, "domu");
13279 ok &= subst_test("%i %I", "", "", -1, -1, "0.0.0.0 0.0.0.0");
13280 ok &= subst_test("%j %J", "", "", -1, -1, "0_0_0_0 0_0_0_0");
13281 /* Substitution depends on current time, so better test the underlying
13282 formatting function. At least covers %t. */
13283 ok &= timesubst_test();
13285 /* Different captialization rules in sub_basic... */
13287 ok &= (strcmp(talloc_sub_basic(talloc_tos(), "BLA", "dom", "%U%D"),
13293 static bool run_local_base64(int dummy)
13298 for (i=1; i<2000; i++) {
13299 DATA_BLOB blob1, blob2;
13302 blob1.data = talloc_array(talloc_tos(), uint8_t, i);
13304 generate_random_buffer(blob1.data, blob1.length);
13306 b64 = base64_encode_data_blob(talloc_tos(), blob1);
13308 d_fprintf(stderr, "base64_encode_data_blob failed "
13309 "for %d bytes\n", i);
13312 blob2 = base64_decode_data_blob(b64);
13315 if (data_blob_cmp(&blob1, &blob2)) {
13316 d_fprintf(stderr, "data_blob_cmp failed for %d "
13320 TALLOC_FREE(blob1.data);
13321 data_blob_free(&blob2);
13326 static void parse_fn(const struct gencache_timeout *t,
13328 void *private_data)
13333 static bool run_local_gencache(int dummy)
13339 struct memcache *mem;
13342 mem = memcache_init(NULL, 0);
13344 d_printf("%s: memcache_init failed\n", __location__);
13347 memcache_set_global(mem);
13349 if (!gencache_set("foo", "bar", time(NULL) + 1000)) {
13350 d_printf("%s: gencache_set() failed\n", __location__);
13354 if (!gencache_get("foo", NULL, NULL, NULL)) {
13355 d_printf("%s: gencache_get() failed\n", __location__);
13359 for (i=0; i<1000000; i++) {
13360 gencache_parse("foo", parse_fn, NULL);
13363 if (!gencache_get("foo", talloc_tos(), &val, &tm)) {
13364 d_printf("%s: gencache_get() failed\n", __location__);
13369 if (!gencache_get("foo", talloc_tos(), &val, &tm)) {
13370 d_printf("%s: gencache_get() failed\n", __location__);
13374 if (strcmp(val, "bar") != 0) {
13375 d_printf("%s: gencache_get() returned %s, expected %s\n",
13376 __location__, val, "bar");
13383 if (!gencache_del("foo")) {
13384 d_printf("%s: gencache_del() failed\n", __location__);
13387 if (gencache_del("foo")) {
13388 d_printf("%s: second gencache_del() succeeded\n",
13393 if (gencache_get("foo", talloc_tos(), &val, &tm)) {
13394 d_printf("%s: gencache_get() on deleted entry "
13395 "succeeded\n", __location__);
13399 blob = data_blob_string_const_null("bar");
13400 tm = time(NULL) + 60;
13402 if (!gencache_set_data_blob("foo", blob, tm)) {
13403 d_printf("%s: gencache_set_data_blob() failed\n", __location__);
13407 if (!gencache_get_data_blob("foo", talloc_tos(), &blob, NULL, NULL)) {
13408 d_printf("%s: gencache_get_data_blob() failed\n", __location__);
13412 if (strcmp((const char *)blob.data, "bar") != 0) {
13413 d_printf("%s: gencache_get_data_blob() returned %s, expected %s\n",
13414 __location__, (const char *)blob.data, "bar");
13415 data_blob_free(&blob);
13419 data_blob_free(&blob);
13421 if (!gencache_del("foo")) {
13422 d_printf("%s: gencache_del() failed\n", __location__);
13425 if (gencache_del("foo")) {
13426 d_printf("%s: second gencache_del() succeeded\n",
13431 if (gencache_get_data_blob("foo", talloc_tos(), &blob, NULL, NULL)) {
13432 d_printf("%s: gencache_get_data_blob() on deleted entry "
13433 "succeeded\n", __location__);
13438 blob.data = (uint8_t *)&v;
13439 blob.length = sizeof(v);
13441 if (!gencache_set_data_blob("blob", blob, tm)) {
13442 d_printf("%s: gencache_set_data_blob() failed\n",
13446 if (gencache_get("blob", talloc_tos(), &val, &tm)) {
13447 d_printf("%s: gencache_get succeeded\n", __location__);
13454 static bool rbt_testflags(struct db_context *db, const char *key,
13459 struct db_record *rec;
13461 rec = dbwrap_fetch_locked(db, db, string_tdb_data(key));
13463 d_fprintf(stderr, "fetch_locked failed\n");
13467 status = dbwrap_record_store(rec, string_tdb_data(value), TDB_MODIFY);
13468 if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
13469 d_fprintf(stderr, "store TDB_MODIFY unexpected status: %s\n",
13470 nt_errstr(status));
13474 status = dbwrap_record_store(rec, string_tdb_data("overwriteme"),
13476 if (!NT_STATUS_IS_OK(status)) {
13477 d_fprintf(stderr, "store TDB_INSERT failed: %s\n",
13478 nt_errstr(status));
13482 status = dbwrap_record_store(rec, string_tdb_data(value), TDB_INSERT);
13483 if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_COLLISION)) {
13484 d_fprintf(stderr, "store TDB_INSERT unexpected status: %s\n",
13485 nt_errstr(status));
13489 status = dbwrap_record_store(rec, string_tdb_data(value), TDB_MODIFY);
13490 if (!NT_STATUS_IS_OK(status)) {
13491 d_fprintf(stderr, "store TDB_MODIFY failed: %s\n",
13492 nt_errstr(status));
13502 static bool rbt_testval(struct db_context *db, const char *key,
13505 struct db_record *rec;
13506 TDB_DATA data = string_tdb_data(value);
13511 rec = dbwrap_fetch_locked(db, db, string_tdb_data(key));
13513 d_fprintf(stderr, "fetch_locked failed\n");
13516 status = dbwrap_record_store(rec, data, 0);
13517 if (!NT_STATUS_IS_OK(status)) {
13518 d_fprintf(stderr, "store failed: %s\n", nt_errstr(status));
13523 rec = dbwrap_fetch_locked(db, db, string_tdb_data(key));
13525 d_fprintf(stderr, "second fetch_locked failed\n");
13529 dbvalue = dbwrap_record_get_value(rec);
13530 if ((dbvalue.dsize != data.dsize)
13531 || (memcmp(dbvalue.dptr, data.dptr, data.dsize) != 0)) {
13532 d_fprintf(stderr, "Got wrong data back\n");
13542 static int local_rbtree_traverse_read(struct db_record *rec, void *private_data)
13544 int *count2 = (int *)private_data;
13549 static int local_rbtree_traverse_delete(struct db_record *rec, void *private_data)
13551 int *count2 = (int *)private_data;
13553 dbwrap_record_delete(rec);
13557 static bool run_local_rbtree(int dummy)
13559 struct db_context *db;
13566 db = db_open_rbt(NULL);
13569 d_fprintf(stderr, "db_open_rbt failed\n");
13573 if (!rbt_testflags(db, "firstkey", "firstval")) {
13577 for (i = 0; i < 999; i++) {
13578 char key[sizeof("key-9223372036854775807")];
13579 char value[sizeof("value-9223372036854775807")];
13581 snprintf(key, sizeof(key), "key%ld", random());
13582 snprintf(value, sizeof(value) ,"value%ld", random());
13584 if (!rbt_testval(db, key, value)) {
13588 snprintf(value, sizeof(value) ,"value%ld", random());
13590 if (!rbt_testval(db, key, value)) {
13596 count = 0; count2 = 0;
13597 status = dbwrap_traverse_read(db, local_rbtree_traverse_read,
13599 printf("%s: read1: %d %d, %s\n", __func__, count, count2, nt_errstr(status));
13600 if ((count != count2) || (count != 1000)) {
13603 count = 0; count2 = 0;
13604 status = dbwrap_traverse(db, local_rbtree_traverse_delete,
13606 printf("%s: delete: %d %d, %s\n", __func__, count, count2, nt_errstr(status));
13607 if ((count != count2) || (count != 1000)) {
13610 count = 0; count2 = 0;
13611 status = dbwrap_traverse_read(db, local_rbtree_traverse_read,
13613 printf("%s: read2: %d %d, %s\n", __func__, count, count2, nt_errstr(status));
13614 if ((count != count2) || (count != 0)) {
13625 local test for character set functions
13627 This is a very simple test for the functionality in convert_string_error()
13629 static bool run_local_convert_string(int dummy)
13631 TALLOC_CTX *tmp_ctx = talloc_new(NULL);
13632 const char *test_strings[2] = { "March", "M\303\244rz" };
13636 for (i=0; i<2; i++) {
13637 const char *str = test_strings[i];
13638 int len = strlen(str);
13639 size_t converted_size;
13642 memset(dst, 'X', sizeof(dst));
13644 /* first try with real source length */
13645 ret = convert_string_error(CH_UNIX, CH_UTF8,
13650 d_fprintf(stderr, "Failed to convert '%s' to CH_DISPLAY\n", str);
13654 if (converted_size != len) {
13655 d_fprintf(stderr, "Converted size of '%s' should be %d - got %d\n",
13656 str, len, (int)converted_size);
13660 if (strncmp(str, dst, converted_size) != 0) {
13661 d_fprintf(stderr, "Expected '%s' to match '%s'\n", str, dst);
13665 if (strlen(str) != converted_size) {
13666 d_fprintf(stderr, "Expected '%s' length %d - got %d\n", str,
13667 (int)strlen(str), (int)converted_size);
13671 if (dst[converted_size] != 'X') {
13672 d_fprintf(stderr, "Expected no termination of '%s'\n", dst);
13676 /* now with srclen==-1, this causes the nul to be
13678 ret = convert_string_error(CH_UNIX, CH_UTF8,
13683 d_fprintf(stderr, "Failed to convert '%s' to CH_DISPLAY\n", str);
13687 if (converted_size != len+1) {
13688 d_fprintf(stderr, "Converted size of '%s' should be %d - got %d\n",
13689 str, len, (int)converted_size);
13693 if (strncmp(str, dst, converted_size) != 0) {
13694 d_fprintf(stderr, "Expected '%s' to match '%s'\n", str, dst);
13698 if (len+1 != converted_size) {
13699 d_fprintf(stderr, "Expected '%s' length %d - got %d\n", str,
13700 len+1, (int)converted_size);
13704 if (dst[converted_size] != 'X') {
13705 d_fprintf(stderr, "Expected no termination of '%s'\n", dst);
13712 TALLOC_FREE(tmp_ctx);
13715 TALLOC_FREE(tmp_ctx);
13719 static bool run_local_string_to_sid(int dummy) {
13720 struct dom_sid sid;
13722 if (string_to_sid(&sid, "S--1-5-32-545")) {
13723 printf("allowing S--1-5-32-545\n");
13726 if (string_to_sid(&sid, "S-1-5-32-+545")) {
13727 printf("allowing S-1-5-32-+545\n");
13730 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")) {
13731 printf("allowing S-1-2-3-4-5-6-7-8-9-0-1-2-3-4-5-6-7-8-9-0\n");
13734 if (string_to_sid(&sid, "S-1-5-32-545-abc")) {
13735 printf("allowing S-1-5-32-545-abc\n");
13738 if (string_to_sid(&sid, "S-300-5-32-545")) {
13739 printf("allowing S-300-5-32-545\n");
13742 if (string_to_sid(&sid, "S-1-0xfffffffffffffe-32-545")) {
13743 printf("allowing S-1-0xfffffffffffffe-32-545\n");
13746 if (string_to_sid(&sid, "S-1-0xffffffffffff-5294967297-545")) {
13747 printf("allowing S-1-0xffffffffffff-5294967297-545\n");
13750 if (!string_to_sid(&sid, "S-1-0xfffffffffffe-32-545")) {
13751 printf("could not parse S-1-0xfffffffffffe-32-545\n");
13754 if (!string_to_sid(&sid, "S-1-5-32-545")) {
13755 printf("could not parse S-1-5-32-545\n");
13758 if (!dom_sid_equal(&sid, &global_sid_Builtin_Users)) {
13759 struct dom_sid_buf buf;
13760 printf("mis-parsed S-1-5-32-545 as %s\n",
13761 dom_sid_str_buf(&sid, &buf));
13767 static bool sid_to_string_test(const char *expected) {
13770 struct dom_sid sid;
13772 if (!string_to_sid(&sid, expected)) {
13773 printf("could not parse %s\n", expected);
13777 str = dom_sid_string(NULL, &sid);
13778 if (strcmp(str, expected)) {
13779 printf("Comparison failed (%s != %s)\n", str, expected);
13786 static bool run_local_sid_to_string(int dummy) {
13787 if (!sid_to_string_test("S-1-0xffffffffffff-1-1-1-1-1-1-1-1-1-1-1-1"))
13789 if (!sid_to_string_test("S-1-545"))
13791 if (!sid_to_string_test("S-255-3840-1-1-1-1"))
13796 static bool run_local_binary_to_sid(int dummy) {
13798 struct dom_sid *sid = talloc(NULL, struct dom_sid);
13799 static const uint8_t good_binary_sid[] = {
13800 0x1, /* revision number */
13801 15, /* num auths */
13802 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, /* id_auth */
13803 0x1, 0x1, 0x1, 0x1, /* auth[0] */
13804 0x1, 0x1, 0x1, 0x1, /* auth[1] */
13805 0x1, 0x1, 0x1, 0x1, /* auth[2] */
13806 0x1, 0x1, 0x1, 0x1, /* auth[3] */
13807 0x1, 0x1, 0x1, 0x1, /* auth[4] */
13808 0x1, 0x1, 0x1, 0x1, /* auth[5] */
13809 0x1, 0x1, 0x1, 0x1, /* auth[6] */
13810 0x1, 0x1, 0x1, 0x1, /* auth[7] */
13811 0x1, 0x1, 0x1, 0x1, /* auth[8] */
13812 0x1, 0x1, 0x1, 0x1, /* auth[9] */
13813 0x1, 0x1, 0x1, 0x1, /* auth[10] */
13814 0x1, 0x1, 0x1, 0x1, /* auth[11] */
13815 0x1, 0x1, 0x1, 0x1, /* auth[12] */
13816 0x1, 0x1, 0x1, 0x1, /* auth[13] */
13817 0x1, 0x1, 0x1, 0x1, /* auth[14] */
13820 static const uint8_t long_binary_sid[] = {
13821 0x1, /* revision number */
13822 15, /* num auths */
13823 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, /* id_auth */
13824 0x1, 0x1, 0x1, 0x1, /* auth[0] */
13825 0x1, 0x1, 0x1, 0x1, /* auth[1] */
13826 0x1, 0x1, 0x1, 0x1, /* auth[2] */
13827 0x1, 0x1, 0x1, 0x1, /* auth[3] */
13828 0x1, 0x1, 0x1, 0x1, /* auth[4] */
13829 0x1, 0x1, 0x1, 0x1, /* auth[5] */
13830 0x1, 0x1, 0x1, 0x1, /* auth[6] */
13831 0x1, 0x1, 0x1, 0x1, /* auth[7] */
13832 0x1, 0x1, 0x1, 0x1, /* auth[8] */
13833 0x1, 0x1, 0x1, 0x1, /* auth[9] */
13834 0x1, 0x1, 0x1, 0x1, /* auth[10] */
13835 0x1, 0x1, 0x1, 0x1, /* auth[11] */
13836 0x1, 0x1, 0x1, 0x1, /* auth[12] */
13837 0x1, 0x1, 0x1, 0x1, /* auth[13] */
13838 0x1, 0x1, 0x1, 0x1, /* auth[14] */
13839 0x1, 0x1, 0x1, 0x1, /* auth[15] */
13840 0x1, 0x1, 0x1, 0x1, /* auth[16] */
13841 0x1, 0x1, 0x1, 0x1, /* auth[17] */
13844 static const uint8_t long_binary_sid2[] = {
13845 0x1, /* revision number */
13846 32, /* num auths */
13847 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, /* id_auth */
13848 0x1, 0x1, 0x1, 0x1, /* auth[0] */
13849 0x1, 0x1, 0x1, 0x1, /* auth[1] */
13850 0x1, 0x1, 0x1, 0x1, /* auth[2] */
13851 0x1, 0x1, 0x1, 0x1, /* auth[3] */
13852 0x1, 0x1, 0x1, 0x1, /* auth[4] */
13853 0x1, 0x1, 0x1, 0x1, /* auth[5] */
13854 0x1, 0x1, 0x1, 0x1, /* auth[6] */
13855 0x1, 0x1, 0x1, 0x1, /* auth[7] */
13856 0x1, 0x1, 0x1, 0x1, /* auth[8] */
13857 0x1, 0x1, 0x1, 0x1, /* auth[9] */
13858 0x1, 0x1, 0x1, 0x1, /* auth[10] */
13859 0x1, 0x1, 0x1, 0x1, /* auth[11] */
13860 0x1, 0x1, 0x1, 0x1, /* auth[12] */
13861 0x1, 0x1, 0x1, 0x1, /* auth[13] */
13862 0x1, 0x1, 0x1, 0x1, /* auth[14] */
13863 0x1, 0x1, 0x1, 0x1, /* auth[15] */
13864 0x1, 0x1, 0x1, 0x1, /* auth[16] */
13865 0x1, 0x1, 0x1, 0x1, /* auth[17] */
13866 0x1, 0x1, 0x1, 0x1, /* auth[18] */
13867 0x1, 0x1, 0x1, 0x1, /* auth[19] */
13868 0x1, 0x1, 0x1, 0x1, /* auth[20] */
13869 0x1, 0x1, 0x1, 0x1, /* auth[21] */
13870 0x1, 0x1, 0x1, 0x1, /* auth[22] */
13871 0x1, 0x1, 0x1, 0x1, /* auth[23] */
13872 0x1, 0x1, 0x1, 0x1, /* auth[24] */
13873 0x1, 0x1, 0x1, 0x1, /* auth[25] */
13874 0x1, 0x1, 0x1, 0x1, /* auth[26] */
13875 0x1, 0x1, 0x1, 0x1, /* auth[27] */
13876 0x1, 0x1, 0x1, 0x1, /* auth[28] */
13877 0x1, 0x1, 0x1, 0x1, /* auth[29] */
13878 0x1, 0x1, 0x1, 0x1, /* auth[30] */
13879 0x1, 0x1, 0x1, 0x1, /* auth[31] */
13882 ret = sid_parse(good_binary_sid, sizeof(good_binary_sid), sid);
13886 ret = sid_parse(long_binary_sid2, sizeof(long_binary_sid2), sid);
13890 ret = sid_parse(long_binary_sid, sizeof(long_binary_sid), sid);
13897 /* Split a path name into filename and stream name components. Canonicalise
13898 * such that an implicit $DATA token is always explicit.
13900 * The "specification" of this function can be found in the
13901 * run_local_stream_name() function in torture.c, I've tried those
13902 * combinations against a W2k3 server.
13905 static NTSTATUS split_ntfs_stream_name(TALLOC_CTX *mem_ctx, const char *fname,
13906 char **pbase, char **pstream)
13909 char *stream = NULL;
13910 char *sname; /* stream name */
13911 const char *stype; /* stream type */
13913 DEBUG(10, ("split_ntfs_stream_name called for [%s]\n", fname));
13915 sname = strchr_m(fname, ':');
13917 if (sname == NULL) {
13918 if (pbase != NULL) {
13919 base = talloc_strdup(mem_ctx, fname);
13920 NT_STATUS_HAVE_NO_MEMORY(base);
13925 if (pbase != NULL) {
13926 base = talloc_strndup(mem_ctx, fname, PTR_DIFF(sname, fname));
13927 NT_STATUS_HAVE_NO_MEMORY(base);
13932 stype = strchr_m(sname, ':');
13934 if (stype == NULL) {
13935 sname = talloc_strdup(mem_ctx, sname);
13939 if (strcasecmp_m(stype, ":$DATA") != 0) {
13941 * If there is an explicit stream type, so far we only
13942 * allow $DATA. Is there anything else allowed? -- vl
13944 DEBUG(10, ("[%s] is an invalid stream type\n", stype));
13946 return NT_STATUS_OBJECT_NAME_INVALID;
13948 sname = talloc_strndup(mem_ctx, sname, PTR_DIFF(stype, sname));
13952 if (sname == NULL) {
13954 return NT_STATUS_NO_MEMORY;
13957 if (sname[0] == '\0') {
13959 * no stream name, so no stream
13964 if (pstream != NULL) {
13965 stream = talloc_asprintf(mem_ctx, "%s:%s", sname, stype);
13966 if (stream == NULL) {
13967 TALLOC_FREE(sname);
13969 return NT_STATUS_NO_MEMORY;
13972 * upper-case the type field
13974 (void)strupper_m(strchr_m(stream, ':')+1);
13978 if (pbase != NULL) {
13981 if (pstream != NULL) {
13984 return NT_STATUS_OK;
13987 static bool test_stream_name(const char *fname, const char *expected_base,
13988 const char *expected_stream,
13989 NTSTATUS expected_status)
13993 char *stream = NULL;
13995 status = split_ntfs_stream_name(talloc_tos(), fname, &base, &stream);
13996 if (!NT_STATUS_EQUAL(status, expected_status)) {
14000 if (!NT_STATUS_IS_OK(status)) {
14004 if (base == NULL) goto error;
14006 if (strcmp(expected_base, base) != 0) goto error;
14008 if ((expected_stream != NULL) && (stream == NULL)) goto error;
14009 if ((expected_stream == NULL) && (stream != NULL)) goto error;
14011 if ((stream != NULL) && (strcmp(expected_stream, stream) != 0))
14015 TALLOC_FREE(stream);
14019 d_fprintf(stderr, "Do test_stream(%s, %s, %s, %s)\n",
14020 fname, expected_base ? expected_base : "<NULL>",
14021 expected_stream ? expected_stream : "<NULL>",
14022 nt_errstr(expected_status));
14023 d_fprintf(stderr, "-> base=%s, stream=%s, status=%s\n",
14024 base ? base : "<NULL>", stream ? stream : "<NULL>",
14025 nt_errstr(status));
14027 TALLOC_FREE(stream);
14031 static bool run_local_stream_name(int dummy)
14035 ret &= test_stream_name(
14036 "bla", "bla", NULL, NT_STATUS_OK);
14037 ret &= test_stream_name(
14038 "bla::$DATA", "bla", NULL, NT_STATUS_OK);
14039 ret &= test_stream_name(
14040 "bla:blub:", "bla", NULL, NT_STATUS_OBJECT_NAME_INVALID);
14041 ret &= test_stream_name(
14042 "bla::", NULL, NULL, NT_STATUS_OBJECT_NAME_INVALID);
14043 ret &= test_stream_name(
14044 "bla::123", "bla", NULL, NT_STATUS_OBJECT_NAME_INVALID);
14045 ret &= test_stream_name(
14046 "bla:$DATA", "bla", "$DATA:$DATA", NT_STATUS_OK);
14047 ret &= test_stream_name(
14048 "bla:x:$DATA", "bla", "x:$DATA", NT_STATUS_OK);
14049 ret &= test_stream_name(
14050 "bla:x", "bla", "x:$DATA", NT_STATUS_OK);
14055 static bool data_blob_equal(DATA_BLOB a, DATA_BLOB b)
14057 if (a.length != b.length) {
14058 printf("a.length=%d != b.length=%d\n",
14059 (int)a.length, (int)b.length);
14062 if (memcmp(a.data, b.data, a.length) != 0) {
14063 printf("a.data and b.data differ\n");
14069 static bool run_local_memcache(int dummy)
14071 struct memcache *cache;
14072 DATA_BLOB k1, k2, k3, k4, k5;
14076 TALLOC_CTX *mem_ctx;
14082 size_t size1, size2;
14085 mem_ctx = talloc_init("foo");
14086 if (mem_ctx == NULL) {
14090 /* STAT_CACHE TESTS */
14092 cache = memcache_init(NULL, sizeof(void *) == 8 ? 200 : 100);
14094 if (cache == NULL) {
14095 printf("memcache_init failed\n");
14099 d1 = data_blob_const("d1", 2);
14100 d3 = data_blob_const("d3", 2);
14102 k1 = data_blob_const("d1", 2);
14103 k2 = data_blob_const("d2", 2);
14104 k3 = data_blob_const("d3", 2);
14105 k4 = data_blob_const("d4", 2);
14106 k5 = data_blob_const("d5", 2);
14108 memcache_add(cache, STAT_CACHE, k1, d1);
14110 if (!memcache_lookup(cache, STAT_CACHE, k1, &v1)) {
14111 printf("could not find k1\n");
14114 if (!data_blob_equal(d1, v1)) {
14118 memcache_add(cache, STAT_CACHE, k1, d3);
14120 if (!memcache_lookup(cache, STAT_CACHE, k1, &v3)) {
14121 printf("could not find replaced k1\n");
14124 if (!data_blob_equal(d3, v3)) {
14128 TALLOC_FREE(cache);
14130 /* GETWD_CACHE TESTS */
14131 str1 = talloc_strdup(mem_ctx, "string1");
14132 if (str1 == NULL) {
14135 ptr2 = str1; /* Keep an alias for comparison. */
14137 str2 = talloc_strdup(mem_ctx, "string2");
14138 if (str2 == NULL) {
14142 cache = memcache_init(NULL, sizeof(void *) == 8 ? 200 : 100);
14143 if (cache == NULL) {
14144 printf("memcache_init failed\n");
14148 memcache_add_talloc(cache, GETWD_CACHE, k2, &str1);
14149 /* str1 == NULL now. */
14150 ptr1 = memcache_lookup_talloc(cache, GETWD_CACHE, k2);
14151 if (ptr1 == NULL) {
14152 printf("could not find k2\n");
14155 if (ptr1 != ptr2) {
14156 printf("fetch of k2 got wrong string\n");
14160 /* Add a blob to ensure k2 gets purged. */
14161 d3 = data_blob_talloc_zero(mem_ctx, 180);
14162 memcache_add(cache, STAT_CACHE, k3, d3);
14164 ptr2 = memcache_lookup_talloc(cache, GETWD_CACHE, k2);
14165 if (ptr2 != NULL) {
14166 printf("Did find k2, should have been purged\n");
14171 * Test that talloc size also is accounted in memcache and
14172 * causes purge of other object.
14175 str1 = talloc_zero_size(mem_ctx, 100);
14176 str2 = talloc_zero_size(mem_ctx, 100);
14178 memcache_add_talloc(cache, GETWD_CACHE, k4, &str1);
14179 memcache_add_talloc(cache, GETWD_CACHE, k5, &str1);
14181 ptr3 = memcache_lookup_talloc(cache, GETWD_CACHE, k4);
14182 if (ptr3 != NULL) {
14183 printf("Did find k4, should have been purged\n");
14188 * Test that adding a duplicate non-talloced
14189 * key/value on top of a talloced key/value takes account
14190 * of the talloc_freed value size.
14192 TALLOC_FREE(cache);
14193 TALLOC_FREE(mem_ctx);
14195 mem_ctx = talloc_init("key_replace");
14196 if (mem_ctx == NULL) {
14200 cache = memcache_init(NULL, sizeof(void *) == 8 ? 200 : 100);
14201 if (cache == NULL) {
14206 * Add a 100 byte talloced string. This will
14207 * store a (4 or 8 byte) pointer and record the
14208 * total talloced size.
14210 str1 = talloc_zero_size(mem_ctx, 100);
14211 memcache_add_talloc(cache, GETWD_CACHE, k4, &str1);
14213 * Now overwrite with a small talloced
14214 * value. This should fit in the existing size
14215 * and the total talloced size should be removed
14216 * from the cache size.
14218 str1 = talloc_zero_size(mem_ctx, 2);
14219 memcache_add_talloc(cache, GETWD_CACHE, k4, &str1);
14221 * Now store a 20 byte string. If the
14222 * total talloced size wasn't accounted for
14223 * and removed in the overwrite, then this
14226 str2 = talloc_zero_size(mem_ctx, 20);
14227 memcache_add_talloc(cache, GETWD_CACHE, k5, &str2);
14229 ptr3 = memcache_lookup_talloc(cache, GETWD_CACHE, k4);
14230 if (ptr3 == NULL) {
14231 printf("Did not find k4, should not have been purged\n");
14235 TALLOC_FREE(cache);
14236 TALLOC_FREE(mem_ctx);
14238 mem_ctx = talloc_init("foo");
14239 if (mem_ctx == NULL) {
14243 cache = memcache_init(NULL, 0);
14244 if (cache == NULL) {
14248 str1 = talloc_strdup(mem_ctx, "string1");
14249 if (str1 == NULL) {
14252 str2 = talloc_strdup(mem_ctx, "string2");
14253 if (str2 == NULL) {
14256 memcache_add_talloc(cache, SINGLETON_CACHE_TALLOC,
14257 data_blob_string_const("torture"), &str1);
14258 size1 = talloc_total_size(cache);
14260 memcache_add_talloc(cache, SINGLETON_CACHE_TALLOC,
14261 data_blob_string_const("torture"), &str2);
14262 size2 = talloc_total_size(cache);
14264 printf("size1=%d, size2=%d\n", (int)size1, (int)size2);
14266 if (size2 > size1) {
14267 printf("memcache leaks memory!\n");
14273 TALLOC_FREE(cache);
14277 static void wbclient_done(struct tevent_req *req)
14280 struct winbindd_response *wb_resp;
14281 int *i = (int *)tevent_req_callback_data_void(req);
14283 wbc_err = wb_trans_recv(req, req, &wb_resp);
14286 d_printf("wb_trans_recv %d returned %s\n", *i, wbcErrorString(wbc_err));
14289 static bool run_wbclient_multi_ping(int dummy)
14291 struct tevent_context *ev;
14292 struct wb_context **wb_ctx;
14293 struct winbindd_request wb_req;
14294 bool result = false;
14297 BlockSignals(True, SIGPIPE);
14299 ev = tevent_context_init(talloc_tos());
14304 wb_ctx = talloc_array(ev, struct wb_context *, torture_nprocs);
14305 if (wb_ctx == NULL) {
14309 ZERO_STRUCT(wb_req);
14310 wb_req.cmd = WINBINDD_PING;
14312 d_printf("torture_nprocs=%d, numops=%d\n", (int)torture_nprocs, (int)torture_numops);
14314 for (i=0; i<torture_nprocs; i++) {
14315 wb_ctx[i] = wb_context_init(ev, NULL);
14316 if (wb_ctx[i] == NULL) {
14319 for (j=0; j<torture_numops; j++) {
14320 struct tevent_req *req;
14321 req = wb_trans_send(ev, ev, wb_ctx[i],
14322 (j % 2) == 0, &wb_req);
14326 tevent_req_set_callback(req, wbclient_done, &i);
14332 while (i < torture_nprocs * torture_numops) {
14333 tevent_loop_once(ev);
14342 static bool dbtrans_inc(struct db_context *db)
14344 struct db_record *rec;
14350 rec = dbwrap_fetch_locked(db, db, string_term_tdb_data("transtest"));
14352 printf(__location__ "fetch_lock failed\n");
14356 value = dbwrap_record_get_value(rec);
14358 if (value.dsize != sizeof(uint32_t)) {
14359 printf(__location__ "value.dsize = %d\n",
14364 memcpy(&val, value.dptr, sizeof(val));
14367 status = dbwrap_record_store(
14368 rec, make_tdb_data((uint8_t *)&val, sizeof(val)), 0);
14369 if (!NT_STATUS_IS_OK(status)) {
14370 printf(__location__ "store failed: %s\n",
14371 nt_errstr(status));
14381 static bool run_local_dbtrans(int dummy)
14383 struct db_context *db;
14384 struct db_record *rec;
14390 db = db_open(talloc_tos(), "transtest.tdb", 0, TDB_DEFAULT,
14391 O_RDWR|O_CREAT, 0600, DBWRAP_LOCK_ORDER_1,
14394 printf("Could not open transtest.db\n");
14398 res = dbwrap_transaction_start(db);
14400 printf(__location__ "transaction_start failed\n");
14404 rec = dbwrap_fetch_locked(db, db, string_term_tdb_data("transtest"));
14406 printf(__location__ "fetch_lock failed\n");
14410 value = dbwrap_record_get_value(rec);
14412 if (value.dptr == NULL) {
14414 status = dbwrap_record_store(
14415 rec, make_tdb_data((uint8_t *)&initial,
14418 if (!NT_STATUS_IS_OK(status)) {
14419 printf(__location__ "store returned %s\n",
14420 nt_errstr(status));
14427 res = dbwrap_transaction_commit(db);
14429 printf(__location__ "transaction_commit failed\n");
14434 uint32_t val, val2;
14437 res = dbwrap_transaction_start(db);
14439 printf(__location__ "transaction_start failed\n");
14443 status = dbwrap_fetch_uint32_bystring(db, "transtest", &val);
14444 if (!NT_STATUS_IS_OK(status)) {
14445 printf(__location__ "dbwrap_fetch_uint32 failed: %s\n",
14446 nt_errstr(status));
14450 for (i=0; i<10; i++) {
14451 if (!dbtrans_inc(db)) {
14456 status = dbwrap_fetch_uint32_bystring(db, "transtest", &val2);
14457 if (!NT_STATUS_IS_OK(status)) {
14458 printf(__location__ "dbwrap_fetch_uint32 failed: %s\n",
14459 nt_errstr(status));
14463 if (val2 != val + 10) {
14464 printf(__location__ "val=%d, val2=%d\n",
14465 (int)val, (int)val2);
14469 printf("val2=%d\r", val2);
14471 res = dbwrap_transaction_commit(db);
14473 printf(__location__ "transaction_commit failed\n");
14483 * Just a dummy test to be run under a debugger. There's no real way
14484 * to inspect the tevent_poll specific function from outside of
14488 static bool run_local_tevent_poll(int dummy)
14490 struct tevent_context *ev;
14491 struct tevent_fd *fd1, *fd2;
14492 bool result = false;
14494 ev = tevent_context_init_byname(NULL, "poll");
14496 d_fprintf(stderr, "tevent_context_init_byname failed\n");
14500 fd1 = tevent_add_fd(ev, ev, 2, 0, NULL, NULL);
14502 d_fprintf(stderr, "tevent_add_fd failed\n");
14505 fd2 = tevent_add_fd(ev, ev, 3, 0, NULL, NULL);
14507 d_fprintf(stderr, "tevent_add_fd failed\n");
14512 fd2 = tevent_add_fd(ev, ev, 1, 0, NULL, NULL);
14514 d_fprintf(stderr, "tevent_add_fd failed\n");
14524 static bool run_local_hex_encode_buf(int dummy)
14530 for (i=0; i<sizeof(src); i++) {
14533 hex_encode_buf(buf, src, sizeof(src));
14534 if (strcmp(buf, "0001020304050607") != 0) {
14537 hex_encode_buf(buf, NULL, 0);
14538 if (buf[0] != '\0') {
14544 static const char *remove_duplicate_addrs2_test_strings_vector[] = {
14566 "1001:1111:1111:1000:0:1111:1111:1111",
14575 static const char *remove_duplicate_addrs2_test_strings_result[] = {
14589 "1001:1111:1111:1000:0:1111:1111:1111"
14592 static bool run_local_remove_duplicate_addrs2(int dummy)
14594 struct samba_sockaddr test_vector[28];
14597 /* Construct the sockaddr_storage test vector. */
14598 for (i = 0; i < 28; i++) {
14599 struct addrinfo hints;
14600 struct addrinfo *res = NULL;
14603 memset(&hints, '\0', sizeof(hints));
14604 hints.ai_flags = AI_NUMERICHOST;
14605 ret = getaddrinfo(remove_duplicate_addrs2_test_strings_vector[i],
14610 fprintf(stderr, "getaddrinfo failed on [%s]\n",
14611 remove_duplicate_addrs2_test_strings_vector[i]);
14614 memset(&test_vector[i], '\0', sizeof(test_vector[i]));
14615 memcpy(&test_vector[i].u.ss,
14621 count = remove_duplicate_addrs2(test_vector, i);
14624 fprintf(stderr, "count wrong (%zu) should be 14\n",
14629 for (i = 0; i < count; i++) {
14630 char addr[INET6_ADDRSTRLEN];
14632 print_sockaddr(addr, sizeof(addr), &test_vector[i].u.ss);
14634 if (strcmp(addr, remove_duplicate_addrs2_test_strings_result[i]) != 0) {
14635 fprintf(stderr, "mismatch on [%zu] [%s] [%s]\n",
14638 remove_duplicate_addrs2_test_strings_result[i]);
14643 printf("run_local_remove_duplicate_addrs2: success\n");
14647 static bool run_local_tdb_opener(int dummy)
14653 t = tdb_open("test.tdb", 1000, TDB_CLEAR_IF_FIRST,
14654 O_RDWR|O_CREAT, 0755);
14656 perror("tdb_open failed");
14667 static bool run_local_tdb_writer(int dummy)
14673 t = tdb_open("test.tdb", 1000, 0, O_RDWR|O_CREAT, 0755);
14675 perror("tdb_open failed");
14679 val.dptr = (uint8_t *)&v;
14680 val.dsize = sizeof(v);
14686 ret = tdb_store(t, val, val, 0);
14688 printf("%s\n", tdb_errorstr(t));
14693 data = tdb_fetch(t, val);
14694 if (data.dptr != NULL) {
14695 SAFE_FREE(data.dptr);
14701 static bool run_local_canonicalize_path(int dummy)
14703 const char *src[] = {
14710 ".././././../../../boo",
14722 "/foo/bar/../baz/",
14723 "////////////////",
14724 "/////////./././././.",
14725 "/./.././../.boo/../baz",
14726 "/a/component/path",
14727 "/a/component/path/",
14728 "/a/component/path/..",
14729 "/a/component/../path/",
14730 "///a/./././///component/../////path/",
14733 const char *dst[] = {
14756 "/a/component/path",
14757 "/a/component/path",
14765 for (i = 0; src[i] != NULL; i++) {
14766 char *d = canonicalize_absolute_path(talloc_tos(), src[i]);
14768 perror("talloc fail\n");
14771 if (strcmp(d, dst[i]) != 0) {
14773 "canonicalize mismatch %s -> %s != %s",
14774 src[i], d, dst[i]);
14781 struct session_setup_nt1_truncated_state {
14786 static void smb1_session_setup_nt1_truncated_done(struct tevent_req *subreq);
14788 static struct tevent_req *smb1_session_setup_nt1_truncated_send(
14789 TALLOC_CTX *mem_ctx,
14790 struct tevent_context *ev,
14791 struct smbXcli_conn *conn)
14793 uint16_t *vwv = NULL;
14794 uint8_t *bytes = NULL;
14795 const char *pass = "12345678";
14796 const char *uname = "z";
14797 struct session_setup_nt1_truncated_state *state = NULL;
14798 struct tevent_req *req = NULL;
14799 struct tevent_req *subreq = NULL;
14801 req = tevent_req_create(mem_ctx,
14803 struct session_setup_nt1_truncated_state);
14807 vwv = &state->vwv[0];
14808 bytes = &state->bytes[0];
14810 SCVAL(vwv+0, 0, 0xff);
14811 SCVAL(vwv+0, 1, 0);
14812 SSVAL(vwv+1, 0, 0);
14813 SSVAL(vwv+2, 0, 8192);
14814 SSVAL(vwv+3, 0, 2);
14815 SSVAL(vwv+4, 0, 1);
14816 SIVAL(vwv+5, 0, 0);
14817 SSVAL(vwv+7, 0, strlen(pass)); /* OEMPasswordLen */
14818 SSVAL(vwv+8, 0, 0); /* UnicodePasswordLen */
14819 SSVAL(vwv+9, 0, 0); /* reserved */
14820 SSVAL(vwv+10, 0, 0); /* reserved */
14821 SIVAL(vwv+11, 0, CAP_STATUS32);
14823 memcpy(bytes, pass, strlen(pass));
14824 bytes += strlen(pass);
14825 memcpy(bytes, uname, strlen(uname)+1);
14827 subreq = smb1cli_req_send(state, ev, conn,
14829 0, /* additional_flags */
14830 0, /* clear_flags */
14831 0, /* additional_flags2 */
14832 0, /* clear_flags2 */
14833 10000, /* timeout_msec */
14836 NULL, /* session */
14839 strlen(pass), /* Truncate length at password. */
14841 if (tevent_req_nomem(subreq, req)) {
14842 return tevent_req_post(req, ev);
14844 tevent_req_set_callback(subreq,
14845 smb1_session_setup_nt1_truncated_done,
14850 static void smb1_session_setup_nt1_truncated_done(struct tevent_req *subreq)
14852 struct tevent_req *req =
14853 tevent_req_callback_data(subreq,
14854 struct tevent_req);
14855 struct session_setup_nt1_truncated_state *state =
14856 tevent_req_data(req,
14857 struct session_setup_nt1_truncated_state);
14859 struct smb1cli_req_expected_response expected[] = {
14861 .status = NT_STATUS_OK,
14866 status = smb1cli_req_recv(subreq, state,
14871 NULL, /* pvwv_offset */
14874 NULL, /* pbytes_offset */
14876 expected, ARRAY_SIZE(expected));
14877 TALLOC_FREE(subreq);
14878 if (tevent_req_nterror(req, status)) {
14881 tevent_req_done(req);
14884 static NTSTATUS smb1_session_setup_nt1_truncated_recv(struct tevent_req *req)
14886 return tevent_req_simple_recv_ntstatus(req);
14889 static bool run_smb1_truncated_sesssetup(int dummy)
14891 struct tevent_context *ev;
14892 struct tevent_req *req;
14893 struct smbXcli_conn *conn;
14894 struct sockaddr_storage ss;
14899 printf("Starting send truncated SMB1 sesssetup.\n");
14901 ok = resolve_name(host, &ss, 0x20, true);
14903 d_fprintf(stderr, "Could not resolve name %s\n", host);
14907 status = open_socket_out(&ss, 445, 10000, &fd);
14908 if (!NT_STATUS_IS_OK(status)) {
14909 d_fprintf(stderr, "open_socket_out failed: %s\n",
14910 nt_errstr(status));
14914 conn = smbXcli_conn_create(talloc_tos(), fd, host, SMB_SIGNING_OFF, 0,
14916 if (conn == NULL) {
14917 d_fprintf(stderr, "smbXcli_conn_create failed\n");
14921 status = smbXcli_negprot(conn,
14928 if (!NT_STATUS_IS_OK(status)) {
14929 d_fprintf(stderr, "smbXcli_negprot failed!\n");
14933 ev = samba_tevent_context_init(talloc_tos());
14935 d_fprintf(stderr, "samba_tevent_context_init failed\n");
14939 req = smb1_session_setup_nt1_truncated_send(ev, ev, conn);
14941 d_fprintf(stderr, "smb1_session_setup_nt1_truncated_send failed\n");
14945 ok = tevent_req_poll_ntstatus(req, ev, &status);
14947 d_fprintf(stderr, "tevent_req_poll failed with status %s\n",
14948 nt_errstr(status));
14952 status = smb1_session_setup_nt1_truncated_recv(req);
14953 if (!NT_STATUS_IS_OK(status)) {
14954 d_fprintf(stderr, "smb1_session_setup_nt1_truncated_recv returned "
14955 "%s, expected NT_STATUS_OK\n",
14956 nt_errstr(status));
14964 struct smb1_negotiate_exit_state {
14968 static void smb1_negotiate_exit_done(struct tevent_req *subreq);
14970 static struct tevent_req *smb1_negotiate_exit_send(
14971 TALLOC_CTX *mem_ctx,
14972 struct tevent_context *ev,
14973 struct smbXcli_conn *conn)
14975 struct smb1_negotiate_exit_state *state = NULL;
14976 struct tevent_req *req = NULL;
14977 struct tevent_req *subreq = NULL;
14979 req = tevent_req_create(mem_ctx,
14981 struct smb1_negotiate_exit_state);
14985 subreq = smb1cli_req_send(state, ev, conn,
14987 0, /* additional_flags */
14988 0, /* clear_flags */
14989 0, /* additional_flags2 */
14990 0, /* clear_flags2 */
14991 10000, /* timeout_msec */
14994 NULL, /* session */
14999 if (tevent_req_nomem(subreq, req)) {
15000 return tevent_req_post(req, ev);
15002 tevent_req_set_callback(subreq,
15003 smb1_negotiate_exit_done,
15008 static void smb1_negotiate_exit_done(struct tevent_req *subreq)
15010 struct tevent_req *req =
15011 tevent_req_callback_data(subreq,
15012 struct tevent_req);
15013 struct smb1_negotiate_exit_state *state =
15014 tevent_req_data(req,
15015 struct smb1_negotiate_exit_state);
15017 struct smb1cli_req_expected_response expected[] = {
15019 .status = NT_STATUS_OK,
15024 status = smb1cli_req_recv(subreq, state,
15029 NULL, /* pvwv_offset */
15032 NULL, /* pbytes_offset */
15034 expected, ARRAY_SIZE(expected));
15035 TALLOC_FREE(subreq);
15036 if (tevent_req_nterror(req, status)) {
15039 tevent_req_done(req);
15042 static NTSTATUS smb1_negotiate_exit_recv(struct tevent_req *req)
15044 return tevent_req_simple_recv_ntstatus(req);
15047 static bool do_smb1_exit(TALLOC_CTX *mem_ctx,
15048 struct tevent_context *ev,
15049 struct smbXcli_conn *conn)
15051 struct tevent_req *req;
15054 NTSTATUS expected_status = NT_STATUS_DOS(ERRSRV, ERRinvnid);;
15056 req = smb1_negotiate_exit_send(ev, ev, conn);
15058 d_fprintf(stderr, "smb1_negotiate_exit_send failed\n");
15062 ok = tevent_req_poll_ntstatus(req, ev, &status);
15064 d_fprintf(stderr, "tevent_req_poll failed with status %s\n",
15065 nt_errstr(status));
15069 status = smb1_negotiate_exit_recv(req);
15070 if (!NT_STATUS_EQUAL(status, expected_status)) {
15071 d_fprintf(stderr, "smb1_negotiate_exit_recv returned "
15072 "%s, expected ERRSRV, ERRinvnid\n",
15073 nt_errstr(status));
15079 static bool run_smb1_negotiate_exit(int dummy)
15081 struct tevent_context *ev;
15082 struct smbXcli_conn *conn;
15083 struct sockaddr_storage ss;
15088 printf("Starting send SMB1 negotiate+exit.\n");
15090 ok = resolve_name(host, &ss, 0x20, true);
15092 d_fprintf(stderr, "Could not resolve name %s\n", host);
15096 status = open_socket_out(&ss, 445, 10000, &fd);
15097 if (!NT_STATUS_IS_OK(status)) {
15098 d_fprintf(stderr, "open_socket_out failed: %s\n",
15099 nt_errstr(status));
15103 conn = smbXcli_conn_create(talloc_tos(), fd, host, SMB_SIGNING_OFF, 0,
15105 if (conn == NULL) {
15106 d_fprintf(stderr, "smbXcli_conn_create failed\n");
15110 status = smbXcli_negprot(conn,
15117 if (!NT_STATUS_IS_OK(status)) {
15118 d_fprintf(stderr, "smbXcli_negprot failed!\n");
15122 ev = samba_tevent_context_init(talloc_tos());
15124 d_fprintf(stderr, "samba_tevent_context_init failed\n");
15129 * Call do_smb1_exit twice to catch a server crash, the
15130 * server sends the first return code then crashes.
15132 ok = do_smb1_exit(ev, ev, conn);
15134 d_fprintf(stderr, "do_smb1_exit (1) failed\n");
15137 ok = do_smb1_exit(ev, ev, conn);
15139 d_fprintf(stderr, "do_smb1_exit (2) failed\n");
15147 static bool run_smb1_negotiate_tcon(int dummy)
15149 struct cli_state *cli = NULL;
15151 uint16_t max_xmit = 0;
15154 printf("Starting send SMB1 negotiate+tcon.\n");
15155 cli = open_nbt_connection();
15157 d_fprintf(stderr, "open_nbt_connection failed!\n");
15160 smbXcli_conn_set_sockopt(cli->conn, sockops);
15162 status = smbXcli_negprot(cli->conn,
15169 if (!NT_STATUS_IS_OK(status)) {
15170 d_fprintf(stderr, "smbXcli_negprot failed %s!\n",
15171 nt_errstr(status));
15174 status = cli_raw_tcon(cli,
15180 if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
15181 d_fprintf(stderr, "cli_raw_tcon failed - got %s "
15182 "(should get NT_STATUS_ACCESS_DENIED)!\n",
15183 nt_errstr(status));
15189 static bool run_ign_bad_negprot(int dummy)
15191 struct tevent_context *ev;
15192 struct tevent_req *req;
15193 struct smbXcli_conn *conn;
15194 struct sockaddr_storage ss;
15199 printf("starting ignore bad negprot\n");
15201 ok = resolve_name(host, &ss, 0x20, true);
15203 d_fprintf(stderr, "Could not resolve name %s\n", host);
15207 status = open_socket_out(&ss, 445, 10000, &fd);
15208 if (!NT_STATUS_IS_OK(status)) {
15209 d_fprintf(stderr, "open_socket_out failed: %s\n",
15210 nt_errstr(status));
15214 conn = smbXcli_conn_create(talloc_tos(), fd, host, SMB_SIGNING_OFF, 0,
15216 if (conn == NULL) {
15217 d_fprintf(stderr, "smbXcli_conn_create failed\n");
15221 status = smbXcli_negprot(conn,
15228 if (NT_STATUS_IS_OK(status)) {
15229 d_fprintf(stderr, "smbXcli_negprot succeeded!\n");
15233 ev = samba_tevent_context_init(talloc_tos());
15235 d_fprintf(stderr, "samba_tevent_context_init failed\n");
15239 req = smb1cli_session_setup_nt1_send(
15240 ev, ev, conn, 0, getpid(), NULL, 65503, 2, 1, 0, "", "",
15241 data_blob_null, data_blob_null, 0x40,
15242 "Windows 2000 2195", "Windows 2000 5.0");
15244 d_fprintf(stderr, "smb1cli_session_setup_nt1_send failed\n");
15248 ok = tevent_req_poll_ntstatus(req, ev, &status);
15250 d_fprintf(stderr, "tevent_req_poll failed\n");
15254 status = smb1cli_session_setup_nt1_recv(req, NULL, NULL, NULL, NULL,
15256 if (!NT_STATUS_EQUAL(status, NT_STATUS_CONNECTION_RESET)) {
15257 d_fprintf(stderr, "smb1cli_session_setup_nt1_recv returned "
15258 "%s, expected NT_STATUS_CONNECTION_RESET\n",
15259 nt_errstr(status));
15265 printf("starting ignore bad negprot\n");
15271 static double create_procs(bool (*fn)(int), bool *result)
15274 volatile pid_t *child_status;
15275 volatile bool *child_status_out;
15278 struct timeval start;
15282 child_status = (volatile pid_t *)anonymous_shared_allocate(sizeof(pid_t)*torture_nprocs);
15283 if (!child_status) {
15284 printf("Failed to setup shared memory\n");
15288 child_status_out = (volatile bool *)anonymous_shared_allocate(sizeof(bool)*torture_nprocs);
15289 if (!child_status_out) {
15290 printf("Failed to setup result status shared memory\n");
15294 for (i = 0; i < torture_nprocs; i++) {
15295 child_status[i] = 0;
15296 child_status_out[i] = True;
15299 start = timeval_current();
15301 for (i=0;i<torture_nprocs;i++) {
15304 pid_t mypid = getpid();
15305 sys_srandom(((int)mypid) ^ ((int)time(NULL)));
15307 slprintf(myname,sizeof(myname),"CLIENT%d", i);
15310 if (torture_open_connection(¤t_cli, i)) break;
15311 if (tries-- == 0) {
15312 printf("pid %d failed to start\n", (int)getpid());
15318 child_status[i] = getpid();
15320 while (child_status[i] && timeval_elapsed(&start) < 5) smb_msleep(2);
15322 child_status_out[i] = fn(i);
15329 for (i=0;i<torture_nprocs;i++) {
15330 if (child_status[i]) synccount++;
15332 if (synccount == torture_nprocs) break;
15334 } while (timeval_elapsed(&start) < 30);
15336 if (synccount != torture_nprocs) {
15337 printf("FAILED TO START %d CLIENTS (started %d)\n", torture_nprocs, synccount);
15339 return timeval_elapsed(&start);
15342 /* start the client load */
15343 start = timeval_current();
15345 for (i=0;i<torture_nprocs;i++) {
15346 child_status[i] = 0;
15349 printf("%d clients started\n", torture_nprocs);
15351 for (i=0;i<torture_nprocs;i++) {
15352 while (waitpid(0, &status, 0) == -1 && errno == EINTR) /* noop */ ;
15357 for (i=0;i<torture_nprocs;i++) {
15358 if (!child_status_out[i]) {
15362 return timeval_elapsed(&start);
15365 #define FLAG_MULTIPROC 1
15371 } torture_ops[] = {
15374 .fn = run_fdpasstest,
15378 .fn = run_locktest1,
15382 .fn = run_locktest2,
15386 .fn = run_locktest3,
15390 .fn = run_locktest4,
15394 .fn = run_locktest5,
15398 .fn = run_locktest6,
15402 .fn = run_locktest7,
15406 .fn = run_locktest8,
15410 .fn = run_locktest9a,
15414 .fn = run_locktest9b,
15418 .fn = run_locktest10,
15422 .fn = run_locktest11,
15426 .fn = run_locktest12,
15430 .fn = run_locktest13,
15434 .fn = run_unlinktest,
15438 .fn = run_browsetest,
15442 .fn = run_attrtest,
15446 .fn = run_trans2test,
15450 .fn = run_maxfidtest,
15451 .flags = FLAG_MULTIPROC,
15456 .flags = FLAG_MULTIPROC,
15459 .name = "RANDOMIPC",
15460 .fn = run_randomipc,
15463 .name = "NEGNOWAIT",
15464 .fn = run_negprot_nowait,
15486 #ifdef HAVE_KERNEL_OPLOCKS_LINUX
15498 .fn = run_dirtest1,
15501 .name = "DIR-CREATETIME",
15502 .fn = run_dir_createtime,
15506 .fn = torture_denytest1,
15510 .fn = torture_denytest2,
15514 .fn = run_tcon_test,
15518 .fn = run_tcon_devtype_test,
15522 .fn = run_readwritetest,
15526 .fn = run_readwritemulti,
15527 .flags = FLAG_MULTIPROC
15531 .fn = run_readwritelarge,
15534 .name = "RW-SIGNING",
15535 .fn = run_readwritelarge_signtest,
15539 .fn = run_opentest,
15543 .fn = run_simple_posix_open_test,
15546 .name = "POSIX-APPEND",
15547 .fn = run_posix_append,
15550 .name = "POSIX-SYMLINK-ACL",
15551 .fn = run_acl_symlink_test,
15554 .name = "POSIX-SYMLINK-EA",
15555 .fn = run_ea_symlink_test,
15558 .name = "POSIX-STREAM-DELETE",
15559 .fn = run_posix_stream_delete,
15562 .name = "POSIX-OFD-LOCK",
15563 .fn = run_posix_ofd_lock_test,
15566 .name = "POSIX-BLOCKING-LOCK",
15567 .fn = run_posix_blocking_lock,
15570 .name = "POSIX-MKDIR",
15571 .fn = run_posix_mkdir_test,
15574 .name = "POSIX-ACL-OPLOCK",
15575 .fn = run_posix_acl_oplock_test,
15578 .name = "POSIX-ACL-SHAREROOT",
15579 .fn = run_posix_acl_shareroot_test,
15582 .name = "POSIX-LS-WILDCARD",
15583 .fn = run_posix_ls_wildcard_test,
15586 .name = "POSIX-LS-SINGLE",
15587 .fn = run_posix_ls_single_test,
15590 .name = "POSIX-READLINK",
15591 .fn = run_posix_readlink_test,
15594 .name = "POSIX-STAT",
15595 .fn = run_posix_stat_test,
15598 .name = "POSIX-SYMLINK-PARENT",
15599 .fn = run_posix_symlink_parent_test,
15602 .name = "POSIX-SYMLINK-CHMOD",
15603 .fn = run_posix_symlink_chmod_test,
15606 .name = "POSIX-SYMLINK-RENAME",
15607 .fn = run_posix_symlink_rename_test,
15610 .name = "POSIX-DIR-DEFAULT-ACL",
15611 .fn = run_posix_dir_default_acl_test,
15614 .name = "POSIX-SYMLINK-GETPATHINFO",
15615 .fn = run_posix_symlink_getpathinfo_test,
15618 .name = "POSIX-SYMLINK-SETPATHINFO",
15619 .fn = run_posix_symlink_setpathinfo_test,
15622 .name = "WINDOWS-BAD-SYMLINK",
15623 .fn = run_symlink_open_test,
15626 .name = "SMB1-WILD-MANGLE-UNLINK",
15627 .fn = run_smb1_wild_mangle_unlink_test,
15630 .name = "SMB1-WILD-MANGLE-RENAME",
15631 .fn = run_smb1_wild_mangle_rename_test,
15634 .name = "CASE-INSENSITIVE-CREATE",
15635 .fn = run_case_insensitive_create,
15638 .name = "ASYNC-ECHO",
15639 .fn = run_async_echo,
15642 .name = "UID-REGRESSION-TEST",
15643 .fn = run_uid_regression_test,
15646 .name = "SHORTNAME-TEST",
15647 .fn = run_shortname_test,
15650 .name = "ADDRCHANGE",
15651 .fn = run_addrchange,
15655 .name = "OPENATTR",
15656 .fn = run_openattrtest,
15668 .name = "RENAME-ACCESS",
15669 .fn = run_rename_access,
15672 .name = "OWNER-RIGHTS",
15673 .fn = run_owner_rights,
15677 .fn = run_deletetest,
15680 .name = "DELETE-STREAM",
15681 .fn = run_delete_stream,
15684 .name = "DELETE-PRINT",
15685 .fn = run_delete_print_test,
15688 .name = "DELETE-LN",
15689 .fn = run_deletetest_ln,
15692 .name = "PROPERTIES",
15693 .fn = run_properties,
15697 .fn = torture_mangle,
15704 .name = "MANGLE-ILLEGAL",
15705 .fn = run_mangle_illegal,
15712 .name = "TRANS2SCAN",
15713 .fn = torture_trans2_scan,
15716 .name = "NTTRANSSCAN",
15717 .fn = torture_nttrans_scan,
15721 .fn = torture_utable,
15724 .name = "CASETABLE",
15725 .fn = torture_casetable,
15728 .name = "ERRMAPEXTRACT",
15729 .fn = run_error_map_extract,
15732 .name = "PIPE_NUMBER",
15733 .fn = run_pipe_number,
15737 .fn = run_tcon2_test,
15741 .fn = torture_ioctl_test,
15745 .fn = torture_chkpath_test,
15749 .fn = run_fdsesstest,
15756 .name = "SESSSETUP_BENCH",
15757 .fn = run_sesssetup_bench,
15772 .name = "WINDOWS-WRITE",
15773 .fn = run_windows_write,
15776 .name = "LARGE_READX",
15777 .fn = run_large_readx,
15780 .name = "MSDFS-ATTRIBUTE",
15781 .fn = run_msdfs_attribute,
15784 .name = "NTTRANS-CREATE",
15785 .fn = run_nttrans_create,
15788 .name = "NTTRANS-FSCTL",
15789 .fn = run_nttrans_fsctl,
15792 .name = "CLI_ECHO",
15793 .fn = run_cli_echo,
15796 .name = "CLI_SPLICE",
15797 .fn = run_cli_splice,
15804 .name = "STREAMERROR",
15805 .fn = run_streamerror,
15808 .name = "NOTIFY-BENCH",
15809 .fn = run_notify_bench,
15812 .name = "NOTIFY-BENCH2",
15813 .fn = run_notify_bench2,
15816 .name = "NOTIFY-BENCH3",
15817 .fn = run_notify_bench3,
15820 .name = "BAD-NBT-SESSION",
15821 .fn = run_bad_nbt_session,
15824 .name = "IGN-BAD-NEGPROT",
15825 .fn = run_ign_bad_negprot,
15828 .name = "SMB-ANY-CONNECT",
15829 .fn = run_smb_any_connect,
15832 .name = "NOTIFY-ONLINE",
15833 .fn = run_notify_online,
15836 .name = "SMB2-BASIC",
15837 .fn = run_smb2_basic,
15840 .name = "SMB2-NEGPROT",
15841 .fn = run_smb2_negprot,
15844 .name = "SMB2-ANONYMOUS",
15845 .fn = run_smb2_anonymous,
15848 .name = "SMB2-SESSION-RECONNECT",
15849 .fn = run_smb2_session_reconnect,
15852 .name = "SMB2-TCON-DEPENDENCE",
15853 .fn = run_smb2_tcon_dependence,
15856 .name = "SMB2-MULTI-CHANNEL",
15857 .fn = run_smb2_multi_channel,
15860 .name = "SMB2-SESSION-REAUTH",
15861 .fn = run_smb2_session_reauth,
15864 .name = "SMB2-FTRUNCATE",
15865 .fn = run_smb2_ftruncate,
15868 .name = "SMB2-DIR-FSYNC",
15869 .fn = run_smb2_dir_fsync,
15872 .name = "SMB2-PATH-SLASH",
15873 .fn = run_smb2_path_slash,
15876 .name = "SMB1-SYSTEM-SECURITY",
15877 .fn = run_smb1_system_security,
15880 .name = "SMB2-SACL",
15881 .fn = run_smb2_sacl,
15884 .name = "SMB2-QUOTA1",
15885 .fn = run_smb2_quota1,
15888 .name = "SMB2-INVALID-PIPENAME",
15889 .fn = run_smb2_invalid_pipename,
15892 .name = "SMB2-STREAM-ACL",
15893 .fn = run_smb2_stream_acl,
15896 .name = "SMB2-LIST-DIR-ASYNC",
15897 .fn = run_list_dir_async_test,
15900 .name = "SMB2-DEL-ON-CLOSE-NONEMPTY",
15901 .fn = run_delete_on_close_non_empty,
15904 .name = "SMB2-DEL-ON-CLOSE-NONWRITE-DELETE-YES",
15905 .fn = run_delete_on_close_nonwrite_delete_yes_test,
15908 .name = "SMB2-DEL-ON-CLOSE-NONWRITE-DELETE-NO",
15909 .fn = run_delete_on_close_nonwrite_delete_no_test,
15912 .name = "SMB2-DFS-PATHS",
15913 .fn = run_smb2_dfs_paths,
15916 .name = "SMB2-NON-DFS-SHARE",
15917 .fn = run_smb2_non_dfs_share,
15920 .name = "SMB2-DFS-SHARE-NON-DFS-PATH",
15921 .fn = run_smb2_dfs_share_non_dfs_path,
15924 .name = "SMB2-DFS-FILENAME-LEADING-BACKSLASH",
15925 .fn = run_smb2_dfs_filename_leading_backslash,
15928 .name = "SMB2-PIPE-READ-ASYNC-DISCONNECT",
15929 .fn = run_smb2_pipe_read_async_disconnect,
15932 .name = "SMB1-TRUNCATED-SESSSETUP",
15933 .fn = run_smb1_truncated_sesssetup,
15936 .name = "SMB1-NEGOTIATE-EXIT",
15937 .fn = run_smb1_negotiate_exit,
15940 .name = "SMB1-NEGOTIATE-TCON",
15941 .fn = run_smb1_negotiate_tcon,
15944 .name = "SMB1-DFS-PATHS",
15945 .fn = run_smb1_dfs_paths,
15948 .name = "SMB1-DFS-SEARCH-PATHS",
15949 .fn = run_smb1_dfs_search_paths,
15952 .name = "SMB1-DFS-OPERATIONS",
15953 .fn = run_smb1_dfs_operations,
15956 .name = "SMB1-DFS-BADPATH",
15957 .fn = run_smb1_dfs_check_badpath,
15960 .name = "CLEANUP1",
15961 .fn = run_cleanup1,
15964 .name = "CLEANUP2",
15965 .fn = run_cleanup2,
15968 .name = "CLEANUP4",
15969 .fn = run_cleanup4,
15972 .name = "OPLOCK-CANCEL",
15973 .fn = run_oplock_cancel,
15980 .name = "LOCAL-SUBSTITUTE",
15981 .fn = run_local_substitute,
15984 .name = "LOCAL-GENCACHE",
15985 .fn = run_local_gencache,
15988 .name = "LOCAL-DBWRAP-WATCH1",
15989 .fn = run_dbwrap_watch1,
15992 .name = "LOCAL-DBWRAP-WATCH2",
15993 .fn = run_dbwrap_watch2,
15996 .name = "LOCAL-DBWRAP-WATCH3",
15997 .fn = run_dbwrap_watch3,
16000 .name = "LOCAL-DBWRAP-WATCH4",
16001 .fn = run_dbwrap_watch4,
16004 .name = "LOCAL-DBWRAP-DO-LOCKED1",
16005 .fn = run_dbwrap_do_locked1,
16008 .name = "LOCAL-MESSAGING-READ1",
16009 .fn = run_messaging_read1,
16012 .name = "LOCAL-MESSAGING-READ2",
16013 .fn = run_messaging_read2,
16016 .name = "LOCAL-MESSAGING-READ3",
16017 .fn = run_messaging_read3,
16020 .name = "LOCAL-MESSAGING-READ4",
16021 .fn = run_messaging_read4,
16024 .name = "LOCAL-MESSAGING-FDPASS1",
16025 .fn = run_messaging_fdpass1,
16028 .name = "LOCAL-MESSAGING-FDPASS2",
16029 .fn = run_messaging_fdpass2,
16032 .name = "LOCAL-MESSAGING-FDPASS2a",
16033 .fn = run_messaging_fdpass2a,
16036 .name = "LOCAL-MESSAGING-FDPASS2b",
16037 .fn = run_messaging_fdpass2b,
16040 .name = "LOCAL-MESSAGING-SEND-ALL",
16041 .fn = run_messaging_send_all,
16044 .name = "LOCAL-BASE64",
16045 .fn = run_local_base64,
16048 .name = "LOCAL-RBTREE",
16049 .fn = run_local_rbtree,
16052 .name = "LOCAL-MEMCACHE",
16053 .fn = run_local_memcache,
16056 .name = "LOCAL-STREAM-NAME",
16057 .fn = run_local_stream_name,
16060 .name = "LOCAL-STR-MATCH-MSWILD",
16061 .fn = run_str_match_mswild,
16064 .name = "LOCAL-STR-MATCH-REGEX-SUB1",
16065 .fn = run_str_match_regex_sub1,
16068 .name = "WBCLIENT-MULTI-PING",
16069 .fn = run_wbclient_multi_ping,
16072 .name = "LOCAL-string_to_sid",
16073 .fn = run_local_string_to_sid,
16076 .name = "LOCAL-sid_to_string",
16077 .fn = run_local_sid_to_string,
16080 .name = "LOCAL-binary_to_sid",
16081 .fn = run_local_binary_to_sid,
16084 .name = "LOCAL-DBTRANS",
16085 .fn = run_local_dbtrans,
16088 .name = "LOCAL-TEVENT-POLL",
16089 .fn = run_local_tevent_poll,
16092 .name = "LOCAL-CONVERT-STRING",
16093 .fn = run_local_convert_string,
16096 .name = "LOCAL-CONV-AUTH-INFO",
16097 .fn = run_local_conv_auth_info,
16100 .name = "LOCAL-hex_encode_buf",
16101 .fn = run_local_hex_encode_buf,
16104 .name = "LOCAL-IDMAP-TDB-COMMON",
16105 .fn = run_idmap_tdb_common_test,
16108 .name = "LOCAL-remove_duplicate_addrs2",
16109 .fn = run_local_remove_duplicate_addrs2,
16112 .name = "local-tdb-opener",
16113 .fn = run_local_tdb_opener,
16116 .name = "local-tdb-writer",
16117 .fn = run_local_tdb_writer,
16120 .name = "LOCAL-DBWRAP-CTDB1",
16121 .fn = run_local_dbwrap_ctdb1,
16124 .name = "LOCAL-BENCH-PTHREADPOOL",
16125 .fn = run_bench_pthreadpool,
16128 .name = "LOCAL-PTHREADPOOL-TEVENT",
16129 .fn = run_pthreadpool_tevent,
16132 .name = "LOCAL-G-LOCK1",
16136 .name = "LOCAL-G-LOCK2",
16140 .name = "LOCAL-G-LOCK3",
16144 .name = "LOCAL-G-LOCK4",
16148 .name = "LOCAL-G-LOCK4A",
16149 .fn = run_g_lock4a,
16152 .name = "LOCAL-G-LOCK5",
16156 .name = "LOCAL-G-LOCK6",
16160 .name = "LOCAL-G-LOCK7",
16164 .name = "LOCAL-G-LOCK8",
16168 .name = "LOCAL-G-LOCK-PING-PONG",
16169 .fn = run_g_lock_ping_pong,
16172 .name = "LOCAL-CANONICALIZE-PATH",
16173 .fn = run_local_canonicalize_path,
16176 .name = "LOCAL-NAMEMAP-CACHE1",
16177 .fn = run_local_namemap_cache1,
16180 .name = "LOCAL-IDMAP-CACHE1",
16181 .fn = run_local_idmap_cache1,
16184 .name = "qpathinfo-bufsize",
16185 .fn = run_qpathinfo_bufsize,
16188 .name = "hide-new-files-timeout",
16189 .fn = run_hidenewfiles,
16192 .name = "hide-new-files-timeout-showdirs",
16193 .fn = run_hidenewfiles_showdirs,
16195 #ifdef CLUSTER_SUPPORT
16197 .name = "ctdbd-conn1",
16198 .fn = run_ctdbd_conn1,
16202 .name = "readdir-timestamp",
16203 .fn = run_readdir_timestamp,
16206 .name = "rpc-scale",
16207 .fn = run_rpc_scale,
16210 .name = "LOCAL-TDB-VALIDATE",
16211 .fn = run_tdb_validate,
16218 /****************************************************************************
16219 run a specified test or "ALL"
16220 ****************************************************************************/
16221 static bool run_test(const char *name)
16224 bool result = True;
16225 bool found = False;
16228 if (strequal(name,"ALL")) {
16229 for (i=0;torture_ops[i].name;i++) {
16230 run_test(torture_ops[i].name);
16235 for (i=0;torture_ops[i].name;i++) {
16236 fstr_sprintf(randomfname, "\\XX%x",
16237 (unsigned)random());
16239 if (strequal(name, torture_ops[i].name)) {
16241 printf("Running %s\n", name);
16242 if (torture_ops[i].flags & FLAG_MULTIPROC) {
16243 t = create_procs(torture_ops[i].fn, &result);
16246 printf("TEST %s FAILED!\n", name);
16249 struct timeval start;
16250 start = timeval_current();
16251 if (!torture_ops[i].fn(0)) {
16253 printf("TEST %s FAILED!\n", name);
16255 t = timeval_elapsed(&start);
16257 printf("%s took %g secs\n\n", name, t);
16262 printf("Did not find a test named %s\n", name);
16270 static void usage(void)
16274 printf("WARNING samba4 test suite is much more complete nowadays.\n");
16275 printf("Please use samba4 torture.\n\n");
16277 printf("Usage: smbtorture //server/share <options> TEST1 TEST2 ...\n");
16279 printf("\t-d debuglevel\n");
16280 printf("\t-U user%%pass\n");
16281 printf("\t-k use kerberos\n");
16282 printf("\t-N numprocs\n");
16283 printf("\t-n my_netbios_name\n");
16284 printf("\t-W workgroup\n");
16285 printf("\t-o num_operations\n");
16286 printf("\t-O socket_options\n");
16287 printf("\t-m maximum protocol\n");
16288 printf("\t-L use oplocks\n");
16289 printf("\t-c CLIENT.TXT specify client load file for NBENCH\n");
16290 printf("\t-A showall\n");
16291 printf("\t-p port\n");
16292 printf("\t-s seed\n");
16293 printf("\t-b unclist_filename specify multiple shares for multiple connections\n");
16294 printf("\t-f filename filename to test\n");
16295 printf("\t-e encrypt\n");
16298 printf("tests are:");
16299 for (i=0;torture_ops[i].name;i++) {
16300 printf(" %s", torture_ops[i].name);
16304 printf("default test is ALL\n");
16309 /****************************************************************************
16311 ****************************************************************************/
16312 int main(int argc,char *argv[])
16318 bool correct = True;
16319 TALLOC_CTX *frame = talloc_stackframe();
16320 int seed = time(NULL);
16321 struct loadparm_context *lp_ctx = NULL;
16323 #ifdef HAVE_SETBUFFER
16324 setbuffer(stdout, NULL, 0);
16327 setup_logging("smbtorture", DEBUG_STDOUT);
16332 lp_ctx = loadparm_init_s3(frame, loadparm_s3_helpers());
16333 if (lp_ctx == NULL) {
16335 "Failed to initialise the global parameter structure.\n");
16339 if (is_default_dyn_CONFIGFILE()) {
16340 if(getenv("SMB_CONF_PATH")) {
16341 set_dyn_CONFIGFILE(getenv("SMB_CONF_PATH"));
16344 lp_load_global(get_dyn_CONFIGFILE());
16351 for(p = argv[1]; *p; p++)
16355 if (strncmp(argv[1], "//", 2)) {
16359 fstrcpy(host, &argv[1][2]);
16360 p = strchr_m(&host[2],'/');
16365 fstrcpy(share, p+1);
16367 fstrcpy(myname, get_myname(talloc_tos()));
16369 fprintf(stderr, "Failed to get my hostname.\n");
16373 if (*username == 0 && getenv("LOGNAME")) {
16374 fstrcpy(username,getenv("LOGNAME"));
16380 fstrcpy(workgroup, lp_workgroup());
16382 while ((opt = getopt(argc, argv, "p:hW:U:n:N:O:o:m:Ll:d:Aec:ks:b:B:f:"))
16386 port_to_use = atoi(optarg);
16389 seed = atoi(optarg);
16392 fstrcpy(workgroup,optarg);
16395 lpcfg_set_cmdline(lp_ctx, "client max protocol", optarg);
16398 torture_nprocs = atoi(optarg);
16401 torture_numops = atoi(optarg);
16404 lpcfg_set_cmdline(lp_ctx, "log level", optarg);
16410 use_oplocks = True;
16413 local_path = optarg;
16416 torture_showall = True;
16419 fstrcpy(myname, optarg);
16422 client_txt = optarg;
16429 use_kerberos = True;
16431 d_printf("No kerberos support compiled in\n");
16437 fstrcpy(username,optarg);
16438 p = strchr_m(username,'%');
16441 fstrcpy(password, p+1);
16446 fstrcpy(multishare_conn_fname, optarg);
16447 use_multishare_conn = True;
16450 torture_blocksize = atoi(optarg);
16453 test_filename = SMB_STRDUP(optarg);
16456 printf("Unknown option %c (%d)\n", (char)opt, opt);
16461 d_printf("using seed %d\n", seed);
16465 if(use_kerberos && !gotuser) gotpass = True;
16468 char pwd[256] = {0};
16471 rc = samba_getpass("Password:", pwd, sizeof(pwd), false, false);
16473 fstrcpy(password, pwd);
16478 printf("host=%s share=%s user=%s myname=%s\n",
16479 host, share, username, myname);
16481 torture_creds = cli_session_creds_init(frame,
16487 false, /* fallback_after_kerberos */
16488 false, /* use_ccache */
16489 false); /* password_is_nt_hash */
16490 if (torture_creds == NULL) {
16491 d_printf("cli_session_creds_init() failed.\n");
16495 if (argc == optind) {
16496 correct = run_test("ALL");
16498 for (i=optind;i<argc;i++) {
16499 if (!run_test(argv[i])) {
16505 TALLOC_FREE(frame);