2 Unix SMB/CIFS implementation.
4 Copyright (C) Andrew Tridgell 1997-1998
5 Copyright (C) Jeremy Allison 2009
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program. If not, see <http://www.gnu.org/licenses/>.
22 #include "system/shmem.h"
23 #include "libsmb/namequery.h"
24 #include "wbc_async.h"
25 #include "torture/proto.h"
26 #include "libcli/security/security.h"
28 #include "tldap_util.h"
29 #include "tldap_gensec_bind.h"
30 #include "tldap_tls_connect.h"
31 #include "../librpc/gen_ndr/svcctl.h"
32 #include "../lib/util/memcache.h"
33 #include "nsswitch/winbind_client.h"
34 #include "dbwrap/dbwrap.h"
35 #include "dbwrap/dbwrap_open.h"
36 #include "dbwrap/dbwrap_rbt.h"
37 #include "async_smb.h"
38 #include "libsmb/libsmb.h"
39 #include "libsmb/clirap.h"
41 #include "libsmb/nmblib.h"
42 #include "../lib/util/tevent_ntstatus.h"
44 #include "../libcli/smb/read_smb.h"
45 #include "../libcli/smb/smbXcli_base.h"
46 #include "lib/util/sys_rw_data.h"
47 #include "lib/util/base64.h"
48 #include "lib/util/time.h"
49 #include "lib/gencache.h"
50 #include "lib/util/sys_rw.h"
51 #include "lib/util/asn1.h"
52 #include "lib/util/util_file.h"
53 #include "lib/param/param.h"
54 #include "auth/gensec/gensec.h"
55 #include "lib/util/string_wrappers.h"
56 #include "source3/lib/substitute.h"
59 #include <gnutls/gnutls.h>
60 #include <gnutls/crypto.h>
65 fstring host, workgroup, share, password, username, myname;
66 struct cli_credentials *torture_creds;
67 static const char *sockops="TCP_NODELAY";
69 static int port_to_use=0;
70 int torture_numops=100;
71 int torture_blocksize=1024*1024;
72 static int procnum; /* records process count number when forking */
73 static struct cli_state *current_cli;
74 static fstring randomfname;
75 static bool use_oplocks;
76 static bool use_level_II_oplocks;
77 static const char *client_txt = "client_oplocks.txt";
78 static bool disable_spnego;
79 static bool use_kerberos;
80 static bool force_dos_errors;
81 static fstring multishare_conn_fname;
82 static bool use_multishare_conn = False;
83 static bool do_encrypt;
84 static const char *local_path = NULL;
85 static enum smb_signing_setting signing_state = SMB_SIGNING_DEFAULT;
88 bool torture_showall = False;
90 static double create_procs(bool (*fn)(int), bool *result);
92 /********************************************************************
93 Ensure a connection is encrypted.
94 ********************************************************************/
96 static bool force_cli_encryption(struct cli_state *c,
97 const char *sharename)
99 uint16_t major, minor;
100 uint32_t caplow, caphigh;
103 if (!SERVER_HAS_UNIX_CIFS(c)) {
104 d_printf("Encryption required and "
105 "server that doesn't support "
106 "UNIX extensions - failing connect\n");
110 status = cli_unix_extensions_version(c, &major, &minor, &caplow,
112 if (!NT_STATUS_IS_OK(status)) {
113 d_printf("Encryption required and "
114 "can't get UNIX CIFS extensions "
115 "version from server: %s\n", nt_errstr(status));
119 if (!(caplow & CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP)) {
120 d_printf("Encryption required and "
121 "share %s doesn't support "
122 "encryption.\n", sharename);
126 status = cli_smb1_setup_encryption(c, torture_creds);
127 if (!NT_STATUS_IS_OK(status)) {
128 d_printf("Encryption required and "
129 "setup failed with error %s.\n",
138 static struct cli_state *open_nbt_connection(void)
144 if (disable_spnego) {
145 flags |= CLI_FULL_CONNECTION_DONT_SPNEGO;
149 flags |= CLI_FULL_CONNECTION_OPLOCKS;
152 if (use_level_II_oplocks) {
153 flags |= CLI_FULL_CONNECTION_LEVEL_II_OPLOCKS;
156 if (force_dos_errors) {
157 flags |= CLI_FULL_CONNECTION_FORCE_DOS_ERRORS;
160 status = cli_connect_nb(NULL,
169 if (!NT_STATUS_IS_OK(status)) {
170 printf("Failed to connect with %s. Error %s\n", host, nt_errstr(status) );
174 cli_set_timeout(c, 120000); /* set a really long timeout (2 minutes) */
179 /****************************************************************************
180 Send a corrupt session request. See rfc1002.txt 4.3 and 4.3.2.
181 ****************************************************************************/
183 static bool cli_bad_session_request(int fd,
184 struct nmb_name *calling, struct nmb_name *called)
193 uint8_t message_type;
195 struct tevent_context *ev;
196 struct tevent_req *req;
198 frame = talloc_stackframe();
200 iov[0].iov_base = len_buf;
201 iov[0].iov_len = sizeof(len_buf);
203 /* put in the destination name */
205 iov[1].iov_base = name_mangle(talloc_tos(), called->name,
207 if (iov[1].iov_base == NULL) {
210 iov[1].iov_len = name_len((unsigned char *)iov[1].iov_base,
211 talloc_get_size(iov[1].iov_base));
215 iov[2].iov_base = name_mangle(talloc_tos(), calling->name,
217 if (iov[2].iov_base == NULL) {
220 iov[2].iov_len = name_len((unsigned char *)iov[2].iov_base,
221 talloc_get_size(iov[2].iov_base));
223 /* Deliberately corrupt the name len (first byte) */
224 *((uint8_t *)iov[2].iov_base) = 100;
226 /* send a session request (RFC 1002) */
227 /* setup the packet length
228 * Remove four bytes from the length count, since the length
229 * field in the NBT Session Service header counts the number
230 * of bytes which follow. The cli_send_smb() function knows
231 * about this and accounts for those four bytes.
235 _smb_setlen(len_buf, iov[1].iov_len + iov[2].iov_len);
236 SCVAL(len_buf,0,0x81);
238 len = write_data_iov(fd, iov, 3);
243 ev = samba_tevent_context_init(frame);
247 req = read_smb_send(frame, ev, fd);
251 if (!tevent_req_poll(req, ev)) {
254 len = read_smb_recv(req, talloc_tos(), &inbuf, &err);
261 message_type = CVAL(inbuf, 0);
262 if (message_type != 0x83) {
263 d_fprintf(stderr, "Expected msg type 0x83, got 0x%2.2x\n",
268 if (smb_len(inbuf) != 1) {
269 d_fprintf(stderr, "Expected smb_len 1, got %d\n",
270 (int)smb_len(inbuf));
274 error = CVAL(inbuf, 4);
276 d_fprintf(stderr, "Expected error 0x82, got %d\n",
287 /* Insert a NULL at the first separator of the given path and return a pointer
288 * to the remainder of the string.
291 terminate_path_at_separator(char * path)
299 if ((p = strchr_m(path, '/'))) {
304 if ((p = strchr_m(path, '\\'))) {
314 parse a //server/share type UNC name
316 bool smbcli_parse_unc(const char *unc_name, TALLOC_CTX *mem_ctx,
317 char **hostname, char **sharename)
321 *hostname = *sharename = NULL;
323 if (strncmp(unc_name, "\\\\", 2) &&
324 strncmp(unc_name, "//", 2)) {
328 *hostname = talloc_strdup(mem_ctx, &unc_name[2]);
329 p = terminate_path_at_separator(*hostname);
332 *sharename = talloc_strdup(mem_ctx, p);
333 terminate_path_at_separator(*sharename);
336 if (*hostname && *sharename) {
340 TALLOC_FREE(*hostname);
341 TALLOC_FREE(*sharename);
345 static bool torture_open_connection_share(struct cli_state **c,
346 const char *hostname,
347 const char *sharename,
352 status = cli_full_connection_creds(c,
361 if (!NT_STATUS_IS_OK(status)) {
362 printf("failed to open share connection: //%s/%s port:%d - %s\n",
363 hostname, sharename, port_to_use, nt_errstr(status));
367 cli_set_timeout(*c, 120000); /* set a really long timeout (2 minutes) */
370 return force_cli_encryption(*c,
376 bool torture_open_connection_flags(struct cli_state **c, int conn_index, int flags)
378 char **unc_list = NULL;
379 int num_unc_names = 0;
382 if (use_multishare_conn==True) {
384 unc_list = file_lines_load(multishare_conn_fname, &num_unc_names, 0, NULL);
385 if (!unc_list || num_unc_names <= 0) {
386 printf("Failed to load unc names list from '%s'\n", multishare_conn_fname);
390 if (!smbcli_parse_unc(unc_list[conn_index % num_unc_names],
392 printf("Failed to parse UNC name %s\n",
393 unc_list[conn_index % num_unc_names]);
394 TALLOC_FREE(unc_list);
398 result = torture_open_connection_share(c, h, s, flags);
400 /* h, s were copied earlier */
401 TALLOC_FREE(unc_list);
405 return torture_open_connection_share(c, host, share, flags);
408 bool torture_open_connection(struct cli_state **c, int conn_index)
410 int flags = CLI_FULL_CONNECTION_FORCE_SMB1;
413 flags |= CLI_FULL_CONNECTION_OPLOCKS;
415 if (use_level_II_oplocks) {
416 flags |= CLI_FULL_CONNECTION_LEVEL_II_OPLOCKS;
419 return torture_open_connection_flags(c, conn_index, flags);
422 bool torture_init_connection(struct cli_state **pcli)
424 struct cli_state *cli;
426 cli = open_nbt_connection();
435 bool torture_cli_session_setup2(struct cli_state *cli, uint16_t *new_vuid)
437 uint16_t old_vuid = cli_state_get_uid(cli);
441 cli_state_set_uid(cli, 0);
442 status = cli_session_setup_creds(cli, torture_creds);
443 ret = NT_STATUS_IS_OK(status);
444 *new_vuid = cli_state_get_uid(cli);
445 cli_state_set_uid(cli, old_vuid);
450 bool torture_close_connection(struct cli_state *c)
455 status = cli_tdis(c);
456 if (!NT_STATUS_IS_OK(status)) {
457 printf("tdis failed (%s)\n", nt_errstr(status));
466 void torture_conn_set_sockopt(struct cli_state *cli)
468 smbXcli_conn_set_sockopt(cli->conn, sockops);
471 static NTSTATUS torture_delete_fn(struct file_info *finfo,
476 char *filename = NULL;
477 char *dirname = NULL;
479 TALLOC_CTX *frame = talloc_stackframe();
480 struct cli_state *cli = (struct cli_state *)state;
482 if (ISDOT(finfo->name) || ISDOTDOT(finfo->name)) {
487 dirname = talloc_strdup(frame, pattern);
488 if (dirname == NULL) {
490 return NT_STATUS_NO_MEMORY;
492 p = strrchr_m(dirname, '\\');
494 /* Remove the terminating '\' */
497 if (dirname[0] != '\0') {
498 filename = talloc_asprintf(frame,
503 filename = talloc_asprintf(frame,
507 if (filename == NULL) {
509 return NT_STATUS_NO_MEMORY;
511 if (finfo->attr & FILE_ATTRIBUTE_DIRECTORY) {
512 char *subdirname = talloc_asprintf(frame,
515 if (subdirname == NULL) {
517 return NT_STATUS_NO_MEMORY;
519 status = cli_list(cli,
521 FILE_ATTRIBUTE_DIRECTORY |
522 FILE_ATTRIBUTE_HIDDEN |
523 FILE_ATTRIBUTE_SYSTEM,
526 if (!NT_STATUS_IS_OK(status)) {
527 printf("torture_delete_fn: cli_list "
528 "of %s failed (%s)\n",
534 status = cli_rmdir(cli, filename);
536 status = cli_unlink(cli,
538 FILE_ATTRIBUTE_SYSTEM |
539 FILE_ATTRIBUTE_HIDDEN);
541 if (!NT_STATUS_IS_OK(status)) {
542 if (finfo->attr & FILE_ATTRIBUTE_DIRECTORY) {
543 printf("torture_delete_fn: cli_rmdir"
544 " of %s failed (%s)\n",
548 printf("torture_delete_fn: cli_unlink"
549 " of %s failed (%s)\n",
558 void torture_deltree(struct cli_state *cli, const char *dname)
563 /* It might be a file */
564 (void)cli_unlink(cli,
566 FILE_ATTRIBUTE_SYSTEM |
567 FILE_ATTRIBUTE_HIDDEN);
569 mask = talloc_asprintf(cli,
573 printf("torture_deltree: talloc_asprintf failed\n");
577 status = cli_list(cli,
579 FILE_ATTRIBUTE_DIRECTORY |
580 FILE_ATTRIBUTE_HIDDEN|
581 FILE_ATTRIBUTE_SYSTEM,
584 if (!NT_STATUS_IS_OK(status)) {
585 printf("torture_deltree: cli_list of %s failed (%s)\n",
590 status = cli_rmdir(cli, dname);
591 if (!NT_STATUS_IS_OK(status)) {
592 printf("torture_deltree: cli_rmdir of %s failed (%s)\n",
598 /* check if the server produced the expected dos or nt error code */
599 static bool check_both_error(int line, NTSTATUS status,
600 uint8_t eclass, uint32_t ecode, NTSTATUS nterr)
602 if (NT_STATUS_IS_DOS(status)) {
606 /* Check DOS error */
607 cclass = NT_STATUS_DOS_CLASS(status);
608 num = NT_STATUS_DOS_CODE(status);
610 if (eclass != cclass || ecode != num) {
611 printf("unexpected error code class=%d code=%d\n",
612 (int)cclass, (int)num);
613 printf(" expected %d/%d %s (line=%d)\n",
614 (int)eclass, (int)ecode, nt_errstr(nterr), line);
619 if (!NT_STATUS_EQUAL(nterr, status)) {
620 printf("unexpected error code %s\n",
622 printf(" expected %s (line=%d)\n",
623 nt_errstr(nterr), line);
632 /* check if the server produced the expected error code */
633 static bool check_error(int line, NTSTATUS status,
634 uint8_t eclass, uint32_t ecode, NTSTATUS nterr)
636 if (NT_STATUS_IS_DOS(status)) {
640 /* Check DOS error */
642 cclass = NT_STATUS_DOS_CLASS(status);
643 num = NT_STATUS_DOS_CODE(status);
645 if (eclass != cclass || ecode != num) {
646 printf("unexpected error code class=%d code=%d\n",
647 (int)cclass, (int)num);
648 printf(" expected %d/%d %s (line=%d)\n",
649 (int)eclass, (int)ecode, nt_errstr(nterr),
657 if (NT_STATUS_V(nterr) != NT_STATUS_V(status)) {
658 printf("unexpected error code %s\n",
660 printf(" expected %s (line=%d)\n", nt_errstr(nterr),
669 NTSTATUS cli_qpathinfo1(struct cli_state *cli,
677 int timezone = smb1cli_conn_server_time_zone(cli->conn);
678 time_t (*date_fn)(const void *buf, int serverzone) = NULL;
679 uint8_t *rdata = NULL;
683 status = cli_qpathinfo(talloc_tos(),
691 if (!NT_STATUS_IS_OK(status)) {
695 date_fn = make_unix_date;
697 date_fn = make_unix_date2;
701 *change_time = date_fn(rdata + 0, timezone);
704 *access_time = date_fn(rdata + 4, timezone);
707 *write_time = date_fn(rdata + 8, timezone);
710 *size = PULL_LE_U32(rdata, 12);
713 *pattr = PULL_LE_U16(rdata, l1_attrFile);
718 static bool wait_lock(struct cli_state *c, int fnum, uint32_t offset, uint32_t len)
722 status = cli_lock32(c, fnum, offset, len, -1, WRITE_LOCK);
724 while (!NT_STATUS_IS_OK(status)) {
725 if (!check_both_error(__LINE__, status, ERRDOS,
726 ERRlock, NT_STATUS_LOCK_NOT_GRANTED)) {
730 status = cli_lock32(c, fnum, offset, len, -1, WRITE_LOCK);
737 static bool rw_torture(struct cli_state *c)
739 const char *lockfname = "\\torture.lck";
743 pid_t pid2, pid = getpid();
750 memset(buf, '\0', sizeof(buf));
752 status = cli_openx(c, lockfname, O_RDWR | O_CREAT | O_EXCL,
754 if (!NT_STATUS_IS_OK(status)) {
755 status = cli_openx(c, lockfname, O_RDWR, DENY_NONE, &fnum2);
757 if (!NT_STATUS_IS_OK(status)) {
758 printf("open of %s failed (%s)\n",
759 lockfname, nt_errstr(status));
763 for (i=0;i<torture_numops;i++) {
764 unsigned n = (unsigned)sys_random()%10;
767 printf("%d\r", i); fflush(stdout);
769 slprintf(fname, sizeof(fstring) - 1, "\\torture.%u", n);
771 if (!wait_lock(c, fnum2, n*sizeof(int), sizeof(int))) {
775 status = cli_openx(c, fname, O_RDWR | O_CREAT | O_TRUNC,
777 if (!NT_STATUS_IS_OK(status)) {
778 printf("open failed (%s)\n", nt_errstr(status));
783 status = cli_writeall(c, fnum, 0, (uint8_t *)&pid, 0,
785 if (!NT_STATUS_IS_OK(status)) {
786 printf("write failed (%s)\n", nt_errstr(status));
791 status = cli_writeall(c, fnum, 0, (uint8_t *)buf,
792 sizeof(pid)+(j*sizeof(buf)),
794 if (!NT_STATUS_IS_OK(status)) {
795 printf("write failed (%s)\n",
803 status = cli_read(c, fnum, (char *)&pid2, 0, sizeof(pid),
805 if (!NT_STATUS_IS_OK(status)) {
806 printf("read failed (%s)\n", nt_errstr(status));
808 } else if (nread != sizeof(pid)) {
809 printf("read/write compare failed: "
810 "recv %ld req %ld\n", (unsigned long)nread,
811 (unsigned long)sizeof(pid));
816 printf("data corruption!\n");
820 status = cli_close(c, fnum);
821 if (!NT_STATUS_IS_OK(status)) {
822 printf("close failed (%s)\n", nt_errstr(status));
826 status = cli_unlink(c, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
827 if (!NT_STATUS_IS_OK(status)) {
828 printf("unlink failed (%s)\n", nt_errstr(status));
832 status = cli_unlock(c, fnum2, n*sizeof(int), sizeof(int));
833 if (!NT_STATUS_IS_OK(status)) {
834 printf("unlock failed (%s)\n", nt_errstr(status));
840 cli_unlink(c, lockfname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
847 static bool run_torture(int dummy)
849 struct cli_state *cli;
854 smbXcli_conn_set_sockopt(cli->conn, sockops);
856 ret = rw_torture(cli);
858 if (!torture_close_connection(cli)) {
865 static bool rw_torture3(struct cli_state *c, char *lockfname)
867 uint16_t fnum = (uint16_t)-1;
872 unsigned countprev = 0;
875 NTSTATUS status = NT_STATUS_OK;
878 for (i = 0; i < sizeof(buf); i += sizeof(uint32_t))
880 SIVAL(buf, i, sys_random());
887 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
888 if (!NT_STATUS_IS_OK(status)) {
889 printf("unlink failed (%s) (normal, this file should "
890 "not exist)\n", nt_errstr(status));
893 status = cli_openx(c, lockfname, O_RDWR | O_CREAT | O_EXCL,
895 if (!NT_STATUS_IS_OK(status)) {
896 printf("first open read/write of %s failed (%s)\n",
897 lockfname, nt_errstr(status));
903 for (i = 0; i < 500 && fnum == (uint16_t)-1; i++)
905 status = cli_openx(c, lockfname, O_RDONLY,
907 if (NT_STATUS_IS_OK(status)) {
912 if (!NT_STATUS_IS_OK(status)) {
913 printf("second open read-only of %s failed (%s)\n",
914 lockfname, nt_errstr(status));
920 for (count = 0; count < sizeof(buf); count += sent)
922 if (count >= countprev) {
923 printf("%d %8d\r", i, count);
926 countprev += (sizeof(buf) / 20);
931 sent = ((unsigned)sys_random()%(20))+ 1;
932 if (sent > sizeof(buf) - count)
934 sent = sizeof(buf) - count;
937 status = cli_writeall(c, fnum, 0, (uint8_t *)buf+count,
939 if (!NT_STATUS_IS_OK(status)) {
940 printf("write failed (%s)\n",
947 status = cli_read(c, fnum, buf_rd+count, count,
948 sizeof(buf)-count, &sent);
949 if(!NT_STATUS_IS_OK(status)) {
950 printf("read failed offset:%d size:%ld (%s)\n",
951 count, (unsigned long)sizeof(buf)-count,
955 } else if (sent > 0) {
956 if (memcmp(buf_rd+count, buf+count, sent) != 0)
958 printf("read/write compare failed\n");
959 printf("offset: %d req %ld recvd %ld\n", count, (unsigned long)sizeof(buf)-count, (unsigned long)sent);
968 status = cli_close(c, fnum);
969 if (!NT_STATUS_IS_OK(status)) {
970 printf("close failed (%s)\n", nt_errstr(status));
977 static bool rw_torture2(struct cli_state *c1, struct cli_state *c2)
979 const char *lockfname = "\\torture2.lck";
989 status = cli_unlink(c1, lockfname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
990 if (!NT_STATUS_IS_OK(status)) {
991 printf("unlink failed (%s) (normal, this file should not exist)\n", nt_errstr(status));
994 status = cli_openx(c1, lockfname, O_RDWR | O_CREAT | O_EXCL,
996 if (!NT_STATUS_IS_OK(status)) {
997 printf("first open read/write of %s failed (%s)\n",
998 lockfname, nt_errstr(status));
1002 status = cli_openx(c2, lockfname, O_RDONLY, DENY_NONE, &fnum2);
1003 if (!NT_STATUS_IS_OK(status)) {
1004 printf("second open read-only of %s failed (%s)\n",
1005 lockfname, nt_errstr(status));
1006 cli_close(c1, fnum1);
1010 for (i = 0; i < torture_numops; i++)
1012 size_t buf_size = ((unsigned)sys_random()%(sizeof(buf)-1))+ 1;
1014 printf("%d\r", i); fflush(stdout);
1017 generate_random_buffer((unsigned char *)buf, buf_size);
1019 status = cli_writeall(c1, fnum1, 0, (uint8_t *)buf, 0,
1021 if (!NT_STATUS_IS_OK(status)) {
1022 printf("write failed (%s)\n", nt_errstr(status));
1027 status = cli_read(c2, fnum2, buf_rd, 0, buf_size, &bytes_read);
1028 if(!NT_STATUS_IS_OK(status)) {
1029 printf("read failed (%s)\n", nt_errstr(status));
1032 } else if (bytes_read != buf_size) {
1033 printf("read failed\n");
1034 printf("read %ld, expected %ld\n",
1035 (unsigned long)bytes_read,
1036 (unsigned long)buf_size);
1041 if (memcmp(buf_rd, buf, buf_size) != 0)
1043 printf("read/write compare failed\n");
1049 status = cli_close(c2, fnum2);
1050 if (!NT_STATUS_IS_OK(status)) {
1051 printf("close failed (%s)\n", nt_errstr(status));
1055 status = cli_close(c1, fnum1);
1056 if (!NT_STATUS_IS_OK(status)) {
1057 printf("close failed (%s)\n", nt_errstr(status));
1061 status = cli_unlink(c1, lockfname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1062 if (!NT_STATUS_IS_OK(status)) {
1063 printf("unlink failed (%s)\n", nt_errstr(status));
1070 static bool run_readwritetest(int dummy)
1072 struct cli_state *cli1, *cli2;
1073 bool test1, test2 = False;
1075 if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
1078 smbXcli_conn_set_sockopt(cli1->conn, sockops);
1079 smbXcli_conn_set_sockopt(cli2->conn, sockops);
1081 printf("starting readwritetest\n");
1083 test1 = rw_torture2(cli1, cli2);
1084 printf("Passed readwritetest v1: %s\n", BOOLSTR(test1));
1087 test2 = rw_torture2(cli1, cli1);
1088 printf("Passed readwritetest v2: %s\n", BOOLSTR(test2));
1091 if (!torture_close_connection(cli1)) {
1095 if (!torture_close_connection(cli2)) {
1099 return (test1 && test2);
1102 static bool run_readwritemulti(int dummy)
1104 struct cli_state *cli;
1109 smbXcli_conn_set_sockopt(cli->conn, sockops);
1111 printf("run_readwritemulti: fname %s\n", randomfname);
1112 test = rw_torture3(cli, randomfname);
1114 if (!torture_close_connection(cli)) {
1121 static bool run_readwritelarge_internal(void)
1123 static struct cli_state *cli1;
1125 const char *lockfname = "\\large.dat";
1128 bool correct = True;
1131 if (!torture_open_connection(&cli1, 0)) {
1134 smbXcli_conn_set_sockopt(cli1->conn, sockops);
1135 memset(buf,'\0',sizeof(buf));
1137 printf("starting readwritelarge_internal\n");
1139 cli_unlink(cli1, lockfname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1141 status = cli_openx(cli1, lockfname, O_RDWR | O_CREAT | O_EXCL,
1143 if (!NT_STATUS_IS_OK(status)) {
1144 printf("open read/write of %s failed (%s)\n", lockfname, nt_errstr(status));
1148 cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 0, sizeof(buf), NULL);
1150 status = cli_qfileinfo_basic(cli1, fnum1, NULL, &fsize, NULL, NULL,
1152 if (!NT_STATUS_IS_OK(status)) {
1153 printf("qfileinfo failed (%s)\n", nt_errstr(status));
1157 if (fsize == sizeof(buf))
1158 printf("readwritelarge_internal test 1 succeeded (size = %lx)\n",
1159 (unsigned long)fsize);
1161 printf("readwritelarge_internal test 1 failed (size = %lx)\n",
1162 (unsigned long)fsize);
1166 status = cli_close(cli1, fnum1);
1167 if (!NT_STATUS_IS_OK(status)) {
1168 printf("close failed (%s)\n", nt_errstr(status));
1172 status = cli_unlink(cli1, lockfname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1173 if (!NT_STATUS_IS_OK(status)) {
1174 printf("unlink failed (%s)\n", nt_errstr(status));
1178 status = cli_openx(cli1, lockfname, O_RDWR | O_CREAT | O_EXCL,
1180 if (!NT_STATUS_IS_OK(status)) {
1181 printf("open read/write of %s failed (%s)\n", lockfname, nt_errstr(status));
1185 cli_smbwrite(cli1, fnum1, buf, 0, sizeof(buf), NULL);
1187 status = cli_qfileinfo_basic(cli1, fnum1, NULL, &fsize, NULL, NULL,
1189 if (!NT_STATUS_IS_OK(status)) {
1190 printf("qfileinfo failed (%s)\n", nt_errstr(status));
1194 if (fsize == sizeof(buf))
1195 printf("readwritelarge_internal test 2 succeeded (size = %lx)\n",
1196 (unsigned long)fsize);
1198 printf("readwritelarge_internal test 2 failed (size = %lx)\n",
1199 (unsigned long)fsize);
1203 status = cli_close(cli1, fnum1);
1204 if (!NT_STATUS_IS_OK(status)) {
1205 printf("close failed (%s)\n", nt_errstr(status));
1209 if (!torture_close_connection(cli1)) {
1215 static bool run_readwritelarge(int dummy)
1217 return run_readwritelarge_internal();
1220 static bool run_readwritelarge_signtest(int dummy)
1223 signing_state = SMB_SIGNING_REQUIRED;
1224 ret = run_readwritelarge_internal();
1225 signing_state = SMB_SIGNING_DEFAULT;
1232 #define ival(s) strtol(s, NULL, 0)
1234 /* run a test that simulates an approximate netbench client load */
1235 static bool run_netbench(int client)
1237 struct cli_state *cli;
1242 const char *params[20];
1243 bool correct = True;
1249 smbXcli_conn_set_sockopt(cli->conn, sockops);
1253 slprintf(cname,sizeof(cname)-1, "client%d", client);
1255 f = fopen(client_txt, "r");
1262 while (fgets(line, sizeof(line)-1, f)) {
1266 line[strlen(line)-1] = 0;
1268 /* printf("[%d] %s\n", line_count, line); */
1270 all_string_sub(line,"client1", cname, sizeof(line));
1272 /* parse the command parameters */
1273 params[0] = strtok_r(line, " ", &saveptr);
1275 while (params[i]) params[++i] = strtok_r(NULL, " ", &saveptr);
1279 if (i < 2) continue;
1281 if (!strncmp(params[0],"SMB", 3)) {
1282 printf("ERROR: You are using a dbench 1 load file\n");
1286 if (!strcmp(params[0],"NTCreateX")) {
1287 nb_createx(params[1], ival(params[2]), ival(params[3]),
1289 } else if (!strcmp(params[0],"Close")) {
1290 nb_close(ival(params[1]));
1291 } else if (!strcmp(params[0],"Rename")) {
1292 nb_rename(params[1], params[2]);
1293 } else if (!strcmp(params[0],"Unlink")) {
1294 nb_unlink(params[1]);
1295 } else if (!strcmp(params[0],"Deltree")) {
1296 nb_deltree(params[1]);
1297 } else if (!strcmp(params[0],"Rmdir")) {
1298 nb_rmdir(params[1]);
1299 } else if (!strcmp(params[0],"QUERY_PATH_INFORMATION")) {
1300 nb_qpathinfo(params[1]);
1301 } else if (!strcmp(params[0],"QUERY_FILE_INFORMATION")) {
1302 nb_qfileinfo(ival(params[1]));
1303 } else if (!strcmp(params[0],"QUERY_FS_INFORMATION")) {
1304 nb_qfsinfo(ival(params[1]));
1305 } else if (!strcmp(params[0],"FIND_FIRST")) {
1306 nb_findfirst(params[1]);
1307 } else if (!strcmp(params[0],"WriteX")) {
1308 nb_writex(ival(params[1]),
1309 ival(params[2]), ival(params[3]), ival(params[4]));
1310 } else if (!strcmp(params[0],"ReadX")) {
1311 nb_readx(ival(params[1]),
1312 ival(params[2]), ival(params[3]), ival(params[4]));
1313 } else if (!strcmp(params[0],"Flush")) {
1314 nb_flush(ival(params[1]));
1316 printf("Unknown operation %s\n", params[0]);
1324 if (!torture_close_connection(cli)) {
1332 /* run a test that simulates an approximate netbench client load */
1333 static bool run_nbench(int dummy)
1336 bool correct = True;
1338 nbio_shmem(torture_nprocs);
1342 signal(SIGALRM, nb_alarm);
1344 t = create_procs(run_netbench, &correct);
1347 printf("\nThroughput %g MB/sec\n",
1348 1.0e-6 * nbio_total() / t);
1354 This test checks for two things:
1356 1) correct support for retaining locks over a close (ie. the server
1357 must not use posix semantics)
1358 2) support for lock timeouts
1360 static bool run_locktest1(int dummy)
1362 struct cli_state *cli1, *cli2;
1363 const char *fname = "\\lockt1.lck";
1364 uint16_t fnum1, fnum2, fnum3;
1366 unsigned lock_timeout;
1369 if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
1372 smbXcli_conn_set_sockopt(cli1->conn, sockops);
1373 smbXcli_conn_set_sockopt(cli2->conn, sockops);
1375 printf("starting locktest1\n");
1377 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1379 status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
1381 if (!NT_STATUS_IS_OK(status)) {
1382 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
1386 status = cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum2);
1387 if (!NT_STATUS_IS_OK(status)) {
1388 printf("open2 of %s failed (%s)\n", fname, nt_errstr(status));
1392 status = cli_openx(cli2, fname, O_RDWR, DENY_NONE, &fnum3);
1393 if (!NT_STATUS_IS_OK(status)) {
1394 printf("open3 of %s failed (%s)\n", fname, nt_errstr(status));
1398 status = cli_lock32(cli1, fnum1, 0, 4, 0, WRITE_LOCK);
1399 if (!NT_STATUS_IS_OK(status)) {
1400 printf("lock1 failed (%s)\n", nt_errstr(status));
1404 status = cli_lock32(cli2, fnum3, 0, 4, 0, WRITE_LOCK);
1405 if (NT_STATUS_IS_OK(status)) {
1406 printf("lock2 succeeded! This is a locking bug\n");
1409 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1410 NT_STATUS_LOCK_NOT_GRANTED)) {
1415 lock_timeout = (1 + (random() % 20));
1416 printf("Testing lock timeout with timeout=%u\n", lock_timeout);
1418 status = cli_lock32(cli2, fnum3, 0, 4, lock_timeout * 1000, WRITE_LOCK);
1419 if (NT_STATUS_IS_OK(status)) {
1420 printf("lock3 succeeded! This is a locking bug\n");
1423 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1424 NT_STATUS_FILE_LOCK_CONFLICT)) {
1430 if (ABS(t2 - t1) < lock_timeout-1) {
1431 printf("error: This server appears not to support timed lock requests\n");
1434 printf("server slept for %u seconds for a %u second timeout\n",
1435 (unsigned int)(t2-t1), lock_timeout);
1437 status = cli_close(cli1, fnum2);
1438 if (!NT_STATUS_IS_OK(status)) {
1439 printf("close1 failed (%s)\n", nt_errstr(status));
1443 status = cli_lock32(cli2, fnum3, 0, 4, 0, WRITE_LOCK);
1444 if (NT_STATUS_IS_OK(status)) {
1445 printf("lock4 succeeded! This is a locking bug\n");
1448 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1449 NT_STATUS_FILE_LOCK_CONFLICT)) {
1454 status = cli_close(cli1, fnum1);
1455 if (!NT_STATUS_IS_OK(status)) {
1456 printf("close2 failed (%s)\n", nt_errstr(status));
1460 status = cli_close(cli2, fnum3);
1461 if (!NT_STATUS_IS_OK(status)) {
1462 printf("close3 failed (%s)\n", nt_errstr(status));
1466 status = cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1467 if (!NT_STATUS_IS_OK(status)) {
1468 printf("unlink failed (%s)\n", nt_errstr(status));
1473 if (!torture_close_connection(cli1)) {
1477 if (!torture_close_connection(cli2)) {
1481 printf("Passed locktest1\n");
1486 this checks to see if a secondary tconx can use open files from an
1489 static bool run_tcon_test(int dummy)
1491 static struct cli_state *cli;
1492 const char *fname = "\\tcontest.tmp";
1494 uint32_t cnum1, cnum2, cnum3;
1495 struct smbXcli_tcon *orig_tcon = NULL;
1496 char *orig_share = NULL;
1497 uint16_t vuid1, vuid2;
1502 memset(buf, '\0', sizeof(buf));
1504 if (!torture_open_connection(&cli, 0)) {
1507 smbXcli_conn_set_sockopt(cli->conn, sockops);
1509 printf("starting tcontest\n");
1511 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1513 status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
1514 if (!NT_STATUS_IS_OK(status)) {
1515 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
1519 cnum1 = cli_state_get_tid(cli);
1520 vuid1 = cli_state_get_uid(cli);
1522 status = cli_writeall(cli, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
1523 if (!NT_STATUS_IS_OK(status)) {
1524 printf("initial write failed (%s)", nt_errstr(status));
1528 cli_state_save_tcon_share(cli, &orig_tcon, &orig_share);
1530 status = cli_tree_connect_creds(cli, share, "?????", torture_creds);
1531 if (!NT_STATUS_IS_OK(status)) {
1532 printf("%s refused 2nd tree connect (%s)\n", host,
1534 cli_state_restore_tcon_share(cli, orig_tcon, orig_share);
1539 cnum2 = cli_state_get_tid(cli);
1540 cnum3 = MAX(cnum1, cnum2) + 1; /* any invalid number */
1541 vuid2 = cli_state_get_uid(cli) + 1;
1543 /* try a write with the wrong tid */
1544 cli_state_set_tid(cli, cnum2);
1546 status = cli_writeall(cli, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
1547 if (NT_STATUS_IS_OK(status)) {
1548 printf("* server allows write with wrong TID\n");
1551 printf("server fails write with wrong TID : %s\n",
1556 /* try a write with an invalid tid */
1557 cli_state_set_tid(cli, cnum3);
1559 status = cli_writeall(cli, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
1560 if (NT_STATUS_IS_OK(status)) {
1561 printf("* server allows write with invalid TID\n");
1564 printf("server fails write with invalid TID : %s\n",
1568 /* try a write with an invalid vuid */
1569 cli_state_set_uid(cli, vuid2);
1570 cli_state_set_tid(cli, cnum1);
1572 status = cli_writeall(cli, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
1573 if (NT_STATUS_IS_OK(status)) {
1574 printf("* server allows write with invalid VUID\n");
1577 printf("server fails write with invalid VUID : %s\n",
1581 cli_state_set_tid(cli, cnum1);
1582 cli_state_set_uid(cli, vuid1);
1584 status = cli_close(cli, fnum1);
1585 if (!NT_STATUS_IS_OK(status)) {
1586 printf("close failed (%s)\n", nt_errstr(status));
1587 cli_state_restore_tcon_share(cli, orig_tcon, orig_share);
1592 cli_state_set_tid(cli, cnum2);
1594 status = cli_tdis(cli);
1595 if (!NT_STATUS_IS_OK(status)) {
1596 printf("secondary tdis failed (%s)\n", nt_errstr(status));
1597 cli_state_restore_tcon_share(cli, orig_tcon, orig_share);
1602 cli_state_restore_tcon_share(cli, orig_tcon, orig_share);
1604 cli_state_set_tid(cli, cnum1);
1606 if (!torture_close_connection(cli)) {
1615 checks for old style tcon support
1617 static bool run_tcon2_test(int dummy)
1619 static struct cli_state *cli;
1620 uint16_t cnum, max_xmit;
1624 if (!torture_open_connection(&cli, 0)) {
1627 smbXcli_conn_set_sockopt(cli->conn, sockops);
1629 printf("starting tcon2 test\n");
1631 if (asprintf(&service, "\\\\%s\\%s", host, share) == -1) {
1635 status = cli_raw_tcon(cli, service, password, "?????", &max_xmit, &cnum);
1639 if (!NT_STATUS_IS_OK(status)) {
1640 printf("tcon2 failed : %s\n", nt_errstr(status));
1642 printf("tcon OK : max_xmit=%d cnum=%d\n",
1643 (int)max_xmit, (int)cnum);
1646 if (!torture_close_connection(cli)) {
1650 printf("Passed tcon2 test\n");
1654 static bool tcon_devtest(struct cli_state *cli,
1655 const char *myshare, const char *devtype,
1656 const char *return_devtype,
1657 NTSTATUS expected_error)
1662 status = cli_tree_connect_creds(cli, myshare, devtype, torture_creds);
1664 if (NT_STATUS_IS_OK(expected_error)) {
1665 if (NT_STATUS_IS_OK(status)) {
1666 if (return_devtype != NULL &&
1667 strequal(cli->dev, return_devtype)) {
1670 printf("tconX to share %s with type %s "
1671 "succeeded but returned the wrong "
1672 "device type (got [%s] but should have got [%s])\n",
1673 myshare, devtype, cli->dev, return_devtype);
1677 printf("tconX to share %s with type %s "
1678 "should have succeeded but failed\n",
1684 if (NT_STATUS_IS_OK(status)) {
1685 printf("tconx to share %s with type %s "
1686 "should have failed but succeeded\n",
1690 if (NT_STATUS_EQUAL(status, expected_error)) {
1693 printf("Returned unexpected error\n");
1702 checks for correct tconX support
1704 static bool run_tcon_devtype_test(int dummy)
1706 static struct cli_state *cli1 = NULL;
1707 int flags = CLI_FULL_CONNECTION_FORCE_SMB1;
1711 status = cli_full_connection_creds(&cli1,
1717 NULL, /* service_type */
1721 if (!NT_STATUS_IS_OK(status)) {
1722 printf("could not open connection\n");
1726 if (!tcon_devtest(cli1, "IPC$", "A:", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1729 if (!tcon_devtest(cli1, "IPC$", "?????", "IPC", NT_STATUS_OK))
1732 if (!tcon_devtest(cli1, "IPC$", "LPT:", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1735 if (!tcon_devtest(cli1, "IPC$", "IPC", "IPC", NT_STATUS_OK))
1738 if (!tcon_devtest(cli1, "IPC$", "FOOBA", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1741 if (!tcon_devtest(cli1, share, "A:", "A:", NT_STATUS_OK))
1744 if (!tcon_devtest(cli1, share, "?????", "A:", NT_STATUS_OK))
1747 if (!tcon_devtest(cli1, share, "LPT:", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1750 if (!tcon_devtest(cli1, share, "IPC", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1753 if (!tcon_devtest(cli1, share, "FOOBA", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1759 printf("Passed tcondevtest\n");
1766 This test checks that
1768 1) the server supports multiple locking contexts on the one SMB
1769 connection, distinguished by PID.
1771 2) the server correctly fails overlapping locks made by the same PID (this
1772 goes against POSIX behaviour, which is why it is tricky to implement)
1774 3) the server denies unlock requests by an incorrect client PID
1776 static bool run_locktest2(int dummy)
1778 static struct cli_state *cli;
1779 const char *fname = "\\lockt2.lck";
1780 uint16_t fnum1, fnum2, fnum3;
1781 bool correct = True;
1784 if (!torture_open_connection(&cli, 0)) {
1788 smbXcli_conn_set_sockopt(cli->conn, sockops);
1790 printf("starting locktest2\n");
1792 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1796 status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
1797 if (!NT_STATUS_IS_OK(status)) {
1798 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
1802 status = cli_openx(cli, fname, O_RDWR, DENY_NONE, &fnum2);
1803 if (!NT_STATUS_IS_OK(status)) {
1804 printf("open2 of %s failed (%s)\n", fname, nt_errstr(status));
1810 status = cli_openx(cli, fname, O_RDWR, DENY_NONE, &fnum3);
1811 if (!NT_STATUS_IS_OK(status)) {
1812 printf("open3 of %s failed (%s)\n", fname, nt_errstr(status));
1818 status = cli_lock32(cli, fnum1, 0, 4, 0, WRITE_LOCK);
1819 if (!NT_STATUS_IS_OK(status)) {
1820 printf("lock1 failed (%s)\n", nt_errstr(status));
1824 status = cli_lock32(cli, fnum1, 0, 4, 0, WRITE_LOCK);
1825 if (NT_STATUS_IS_OK(status)) {
1826 printf("WRITE lock1 succeeded! This is a locking bug\n");
1829 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1830 NT_STATUS_LOCK_NOT_GRANTED)) {
1835 status = cli_lock32(cli, fnum2, 0, 4, 0, WRITE_LOCK);
1836 if (NT_STATUS_IS_OK(status)) {
1837 printf("WRITE lock2 succeeded! This is a locking bug\n");
1840 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1841 NT_STATUS_LOCK_NOT_GRANTED)) {
1846 status = cli_lock32(cli, fnum2, 0, 4, 0, READ_LOCK);
1847 if (NT_STATUS_IS_OK(status)) {
1848 printf("READ lock2 succeeded! This is a locking bug\n");
1851 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1852 NT_STATUS_FILE_LOCK_CONFLICT)) {
1857 status = cli_lock32(cli, fnum1, 100, 4, 0, WRITE_LOCK);
1858 if (!NT_STATUS_IS_OK(status)) {
1859 printf("lock at 100 failed (%s)\n", nt_errstr(status));
1862 if (NT_STATUS_IS_OK(cli_unlock(cli, fnum1, 100, 4))) {
1863 printf("unlock at 100 succeeded! This is a locking bug\n");
1867 status = cli_unlock(cli, fnum1, 0, 4);
1868 if (NT_STATUS_IS_OK(status)) {
1869 printf("unlock1 succeeded! This is a locking bug\n");
1872 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1873 NT_STATUS_RANGE_NOT_LOCKED)) {
1878 status = cli_unlock(cli, fnum1, 0, 8);
1879 if (NT_STATUS_IS_OK(status)) {
1880 printf("unlock2 succeeded! This is a locking bug\n");
1883 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1884 NT_STATUS_RANGE_NOT_LOCKED)) {
1889 status = cli_lock32(cli, fnum3, 0, 4, 0, WRITE_LOCK);
1890 if (NT_STATUS_IS_OK(status)) {
1891 printf("lock3 succeeded! This is a locking bug\n");
1894 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1895 NT_STATUS_LOCK_NOT_GRANTED)) {
1902 status = cli_close(cli, fnum1);
1903 if (!NT_STATUS_IS_OK(status)) {
1904 printf("close1 failed (%s)\n", nt_errstr(status));
1908 status = cli_close(cli, fnum2);
1909 if (!NT_STATUS_IS_OK(status)) {
1910 printf("close2 failed (%s)\n", nt_errstr(status));
1914 status = cli_close(cli, fnum3);
1915 if (!NT_STATUS_IS_OK(status)) {
1916 printf("close3 failed (%s)\n", nt_errstr(status));
1920 if (!torture_close_connection(cli)) {
1924 printf("locktest2 finished\n");
1931 This test checks that
1933 1) the server supports the full offset range in lock requests
1935 static bool run_locktest3(int dummy)
1937 static struct cli_state *cli1, *cli2;
1938 const char *fname = "\\lockt3.lck";
1939 uint16_t fnum1, fnum2;
1942 bool correct = True;
1945 #define NEXT_OFFSET offset += (~(uint32_t)0) / torture_numops
1947 if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
1950 smbXcli_conn_set_sockopt(cli1->conn, sockops);
1951 smbXcli_conn_set_sockopt(cli2->conn, sockops);
1953 printf("starting locktest3\n");
1955 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1957 status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
1959 if (!NT_STATUS_IS_OK(status)) {
1960 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
1964 status = cli_openx(cli2, fname, O_RDWR, DENY_NONE, &fnum2);
1965 if (!NT_STATUS_IS_OK(status)) {
1966 printf("open2 of %s failed (%s)\n", fname, nt_errstr(status));
1970 for (offset=i=0;i<torture_numops;i++) {
1973 status = cli_lock32(cli1, fnum1, offset-1, 1, 0, WRITE_LOCK);
1974 if (!NT_STATUS_IS_OK(status)) {
1975 printf("lock1 %d failed (%s)\n",
1981 status = cli_lock32(cli2, fnum2, offset-2, 1, 0, WRITE_LOCK);
1982 if (!NT_STATUS_IS_OK(status)) {
1983 printf("lock2 %d failed (%s)\n",
1990 for (offset=i=0;i<torture_numops;i++) {
1993 status = cli_lock32(cli1, fnum1, offset-2, 1, 0, WRITE_LOCK);
1994 if (NT_STATUS_IS_OK(status)) {
1995 printf("error: lock1 %d succeeded!\n", i);
1999 status = cli_lock32(cli2, fnum2, offset-1, 1, 0, WRITE_LOCK);
2000 if (NT_STATUS_IS_OK(status)) {
2001 printf("error: lock2 %d succeeded!\n", i);
2005 status = cli_lock32(cli1, fnum1, offset-1, 1, 0, WRITE_LOCK);
2006 if (NT_STATUS_IS_OK(status)) {
2007 printf("error: lock3 %d succeeded!\n", i);
2011 status = cli_lock32(cli2, fnum2, offset-2, 1, 0, WRITE_LOCK);
2012 if (NT_STATUS_IS_OK(status)) {
2013 printf("error: lock4 %d succeeded!\n", i);
2018 for (offset=i=0;i<torture_numops;i++) {
2021 status = cli_unlock(cli1, fnum1, offset-1, 1);
2022 if (!NT_STATUS_IS_OK(status)) {
2023 printf("unlock1 %d failed (%s)\n",
2029 status = cli_unlock(cli2, fnum2, offset-2, 1);
2030 if (!NT_STATUS_IS_OK(status)) {
2031 printf("unlock2 %d failed (%s)\n",
2038 status = cli_close(cli1, fnum1);
2039 if (!NT_STATUS_IS_OK(status)) {
2040 printf("close1 failed (%s)\n", nt_errstr(status));
2044 status = cli_close(cli2, fnum2);
2045 if (!NT_STATUS_IS_OK(status)) {
2046 printf("close2 failed (%s)\n", nt_errstr(status));
2050 status = cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2051 if (!NT_STATUS_IS_OK(status)) {
2052 printf("unlink failed (%s)\n", nt_errstr(status));
2056 if (!torture_close_connection(cli1)) {
2060 if (!torture_close_connection(cli2)) {
2064 printf("finished locktest3\n");
2069 static bool test_cli_read(struct cli_state *cli, uint16_t fnum,
2070 char *buf, off_t offset, size_t size,
2071 size_t *nread, size_t expect)
2076 status = cli_read(cli, fnum, buf, offset, size, &l_nread);
2078 if(!NT_STATUS_IS_OK(status)) {
2080 } else if (l_nread != expect) {
2091 #define EXPECTED(ret, v) if ((ret) != (v)) { \
2092 printf("** "); correct = False; \
2096 looks at overlapping locks
2098 static bool run_locktest4(int dummy)
2100 static struct cli_state *cli1, *cli2;
2101 const char *fname = "\\lockt4.lck";
2102 uint16_t fnum1, fnum2, f;
2105 bool correct = True;
2108 if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
2112 smbXcli_conn_set_sockopt(cli1->conn, sockops);
2113 smbXcli_conn_set_sockopt(cli2->conn, sockops);
2115 printf("starting locktest4\n");
2117 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2119 cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
2120 cli_openx(cli2, fname, O_RDWR, DENY_NONE, &fnum2);
2122 memset(buf, 0, sizeof(buf));
2124 status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 0, sizeof(buf),
2126 if (!NT_STATUS_IS_OK(status)) {
2127 printf("Failed to create file: %s\n", nt_errstr(status));
2132 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 4, 0, WRITE_LOCK)) &&
2133 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 2, 4, 0, WRITE_LOCK));
2134 EXPECTED(ret, False);
2135 printf("the same process %s set overlapping write locks\n", ret?"can":"cannot");
2137 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 10, 4, 0, READ_LOCK)) &&
2138 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 12, 4, 0, READ_LOCK));
2139 EXPECTED(ret, True);
2140 printf("the same process %s set overlapping read locks\n", ret?"can":"cannot");
2142 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 20, 4, 0, WRITE_LOCK)) &&
2143 NT_STATUS_IS_OK(cli_lock32(cli2, fnum2, 22, 4, 0, WRITE_LOCK));
2144 EXPECTED(ret, False);
2145 printf("a different connection %s set overlapping write locks\n", ret?"can":"cannot");
2147 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 30, 4, 0, READ_LOCK)) &&
2148 NT_STATUS_IS_OK(cli_lock32(cli2, fnum2, 32, 4, 0, READ_LOCK));
2149 EXPECTED(ret, True);
2150 printf("a different connection %s set overlapping read locks\n", ret?"can":"cannot");
2152 ret = (cli_setpid(cli1, 1),
2153 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 40, 4, 0, WRITE_LOCK))) &&
2154 (cli_setpid(cli1, 2),
2155 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 42, 4, 0, WRITE_LOCK)));
2156 EXPECTED(ret, False);
2157 printf("a different pid %s set overlapping write locks\n", ret?"can":"cannot");
2159 ret = (cli_setpid(cli1, 1),
2160 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 50, 4, 0, READ_LOCK))) &&
2161 (cli_setpid(cli1, 2),
2162 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 52, 4, 0, READ_LOCK)));
2163 EXPECTED(ret, True);
2164 printf("a different pid %s set overlapping read locks\n", ret?"can":"cannot");
2166 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 60, 4, 0, READ_LOCK)) &&
2167 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 60, 4, 0, READ_LOCK));
2168 EXPECTED(ret, True);
2169 printf("the same process %s set the same read lock twice\n", ret?"can":"cannot");
2171 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 70, 4, 0, WRITE_LOCK)) &&
2172 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 70, 4, 0, WRITE_LOCK));
2173 EXPECTED(ret, False);
2174 printf("the same process %s set the same write lock twice\n", ret?"can":"cannot");
2176 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 80, 4, 0, READ_LOCK)) &&
2177 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 80, 4, 0, WRITE_LOCK));
2178 EXPECTED(ret, False);
2179 printf("the same process %s overlay a read lock with a write lock\n", ret?"can":"cannot");
2181 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 90, 4, 0, WRITE_LOCK)) &&
2182 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 90, 4, 0, READ_LOCK));
2183 EXPECTED(ret, True);
2184 printf("the same process %s overlay a write lock with a read lock\n", ret?"can":"cannot");
2186 ret = (cli_setpid(cli1, 1),
2187 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 100, 4, 0, WRITE_LOCK))) &&
2188 (cli_setpid(cli1, 2),
2189 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 100, 4, 0, READ_LOCK)));
2190 EXPECTED(ret, False);
2191 printf("a different pid %s overlay a write lock with a read lock\n", ret?"can":"cannot");
2193 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 110, 4, 0, READ_LOCK)) &&
2194 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 112, 4, 0, READ_LOCK)) &&
2195 NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 110, 6));
2196 EXPECTED(ret, False);
2197 printf("the same process %s coalesce read locks\n", ret?"can":"cannot");
2200 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 120, 4, 0, WRITE_LOCK)) &&
2201 test_cli_read(cli2, fnum2, buf, 120, 4, NULL, 4);
2202 EXPECTED(ret, False);
2203 printf("this server %s strict write locking\n", ret?"doesn't do":"does");
2205 status = cli_lock32(cli1, fnum1, 130, 4, 0, READ_LOCK);
2206 ret = NT_STATUS_IS_OK(status);
2208 status = cli_writeall(cli2, fnum2, 0, (uint8_t *)buf, 130, 4,
2210 ret = NT_STATUS_IS_OK(status);
2212 EXPECTED(ret, False);
2213 printf("this server %s strict read locking\n", ret?"doesn't do":"does");
2216 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 140, 4, 0, READ_LOCK)) &&
2217 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 140, 4, 0, READ_LOCK)) &&
2218 NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 140, 4)) &&
2219 NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 140, 4));
2220 EXPECTED(ret, True);
2221 printf("this server %s do recursive read locking\n", ret?"does":"doesn't");
2224 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 150, 4, 0, WRITE_LOCK)) &&
2225 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 150, 4, 0, READ_LOCK)) &&
2226 NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 150, 4)) &&
2227 test_cli_read(cli2, fnum2, buf, 150, 4, NULL, 4) &&
2228 !(NT_STATUS_IS_OK(cli_writeall(cli2, fnum2, 0, (uint8_t *)buf,
2230 NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 150, 4));
2231 EXPECTED(ret, True);
2232 printf("this server %s do recursive lock overlays\n", ret?"does":"doesn't");
2234 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 160, 4, 0, READ_LOCK)) &&
2235 NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 160, 4)) &&
2236 NT_STATUS_IS_OK(cli_writeall(cli2, fnum2, 0, (uint8_t *)buf,
2238 test_cli_read(cli2, fnum2, buf, 160, 4, NULL, 4);
2239 EXPECTED(ret, True);
2240 printf("the same process %s remove a read lock using write locking\n", ret?"can":"cannot");
2242 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 170, 4, 0, WRITE_LOCK)) &&
2243 NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 170, 4)) &&
2244 NT_STATUS_IS_OK(cli_writeall(cli2, fnum2, 0, (uint8_t *)buf,
2246 test_cli_read(cli2, fnum2, buf, 170, 4, NULL, 4);
2247 EXPECTED(ret, True);
2248 printf("the same process %s remove a write lock using read locking\n", ret?"can":"cannot");
2250 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 190, 4, 0, WRITE_LOCK)) &&
2251 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 190, 4, 0, READ_LOCK)) &&
2252 NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 190, 4)) &&
2253 !NT_STATUS_IS_OK(cli_writeall(cli2, fnum2, 0, (uint8_t *)buf,
2255 test_cli_read(cli2, fnum2, buf, 190, 4, NULL, 4);
2256 EXPECTED(ret, True);
2257 printf("the same process %s remove the first lock first\n", ret?"does":"doesn't");
2259 cli_close(cli1, fnum1);
2260 cli_close(cli2, fnum2);
2261 cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
2262 cli_openx(cli1, fname, O_RDWR, DENY_NONE, &f);
2263 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 8, 0, READ_LOCK)) &&
2264 NT_STATUS_IS_OK(cli_lock32(cli1, f, 0, 1, 0, READ_LOCK)) &&
2265 NT_STATUS_IS_OK(cli_close(cli1, fnum1)) &&
2266 NT_STATUS_IS_OK(cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1)) &&
2267 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 7, 1, 0, WRITE_LOCK));
2269 cli_close(cli1, fnum1);
2270 EXPECTED(ret, True);
2271 printf("the server %s have the NT byte range lock bug\n", !ret?"does":"doesn't");
2274 cli_close(cli1, fnum1);
2275 cli_close(cli2, fnum2);
2276 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2277 torture_close_connection(cli1);
2278 torture_close_connection(cli2);
2280 printf("finished locktest4\n");
2285 looks at lock upgrade/downgrade.
2287 static bool run_locktest5(int dummy)
2289 static struct cli_state *cli1, *cli2;
2290 const char *fname = "\\lockt5.lck";
2291 uint16_t fnum1, fnum2, fnum3;
2294 bool correct = True;
2297 if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
2301 smbXcli_conn_set_sockopt(cli1->conn, sockops);
2302 smbXcli_conn_set_sockopt(cli2->conn, sockops);
2304 printf("starting locktest5\n");
2306 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2308 cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
2309 cli_openx(cli2, fname, O_RDWR, DENY_NONE, &fnum2);
2310 cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum3);
2312 memset(buf, 0, sizeof(buf));
2314 status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 0, sizeof(buf),
2316 if (!NT_STATUS_IS_OK(status)) {
2317 printf("Failed to create file: %s\n", nt_errstr(status));
2322 /* Check for NT bug... */
2323 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 8, 0, READ_LOCK)) &&
2324 NT_STATUS_IS_OK(cli_lock32(cli1, fnum3, 0, 1, 0, READ_LOCK));
2325 cli_close(cli1, fnum1);
2326 cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
2327 status = cli_lock32(cli1, fnum1, 7, 1, 0, WRITE_LOCK);
2328 ret = NT_STATUS_IS_OK(status);
2329 EXPECTED(ret, True);
2330 printf("this server %s the NT locking bug\n", ret ? "doesn't have" : "has");
2331 cli_close(cli1, fnum1);
2332 cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
2333 cli_unlock(cli1, fnum3, 0, 1);
2335 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 4, 0, WRITE_LOCK)) &&
2336 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 1, 1, 0, READ_LOCK));
2337 EXPECTED(ret, True);
2338 printf("the same process %s overlay a write with a read lock\n", ret?"can":"cannot");
2340 status = cli_lock32(cli2, fnum2, 0, 4, 0, READ_LOCK);
2341 ret = NT_STATUS_IS_OK(status);
2342 EXPECTED(ret, False);
2344 printf("a different process %s get a read lock on the first process lock stack\n", ret?"can":"cannot");
2346 /* Unlock the process 2 lock. */
2347 cli_unlock(cli2, fnum2, 0, 4);
2349 status = cli_lock32(cli1, fnum3, 0, 4, 0, READ_LOCK);
2350 ret = NT_STATUS_IS_OK(status);
2351 EXPECTED(ret, False);
2353 printf("the same process on a different fnum %s get a read lock\n", ret?"can":"cannot");
2355 /* Unlock the process 1 fnum3 lock. */
2356 cli_unlock(cli1, fnum3, 0, 4);
2358 /* Stack 2 more locks here. */
2359 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 4, 0, READ_LOCK)) &&
2360 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 4, 0, READ_LOCK));
2362 EXPECTED(ret, True);
2363 printf("the same process %s stack read locks\n", ret?"can":"cannot");
2365 /* Unlock the first process lock, then check this was the WRITE lock that was
2368 ret = NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 0, 4)) &&
2369 NT_STATUS_IS_OK(cli_lock32(cli2, fnum2, 0, 4, 0, READ_LOCK));
2371 EXPECTED(ret, True);
2372 printf("the first unlock removes the %s lock\n", ret?"WRITE":"READ");
2374 /* Unlock the process 2 lock. */
2375 cli_unlock(cli2, fnum2, 0, 4);
2377 /* We should have 3 stacked locks here. Ensure we need to do 3 unlocks. */
2379 ret = NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 1, 1)) &&
2380 NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 0, 4)) &&
2381 NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 0, 4));
2383 EXPECTED(ret, True);
2384 printf("the same process %s unlock the stack of 4 locks\n", ret?"can":"cannot");
2386 /* Ensure the next unlock fails. */
2387 ret = NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 0, 4));
2388 EXPECTED(ret, False);
2389 printf("the same process %s count the lock stack\n", !ret?"can":"cannot");
2391 /* Ensure connection 2 can get a write lock. */
2392 status = cli_lock32(cli2, fnum2, 0, 4, 0, WRITE_LOCK);
2393 ret = NT_STATUS_IS_OK(status);
2394 EXPECTED(ret, True);
2396 printf("a different process %s get a write lock on the unlocked stack\n", ret?"can":"cannot");
2400 cli_close(cli1, fnum1);
2401 cli_close(cli2, fnum2);
2402 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2403 if (!torture_close_connection(cli1)) {
2406 if (!torture_close_connection(cli2)) {
2410 printf("finished locktest5\n");
2416 tries the unusual lockingX locktype bits
2418 static bool run_locktest6(int dummy)
2420 static struct cli_state *cli;
2421 const char *fname[1] = { "\\lock6.txt" };
2426 if (!torture_open_connection(&cli, 0)) {
2430 smbXcli_conn_set_sockopt(cli->conn, sockops);
2432 printf("starting locktest6\n");
2435 printf("Testing %s\n", fname[i]);
2437 cli_unlink(cli, fname[i], FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2439 cli_openx(cli, fname[i], O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
2440 status = cli_locktype(cli, fnum, 0, 8, 0, LOCKING_ANDX_CHANGE_LOCKTYPE);
2441 cli_close(cli, fnum);
2442 printf("CHANGE_LOCKTYPE gave %s\n", nt_errstr(status));
2444 cli_openx(cli, fname[i], O_RDWR, DENY_NONE, &fnum);
2445 status = cli_locktype(cli, fnum, 0, 8, 0, LOCKING_ANDX_CANCEL_LOCK);
2446 cli_close(cli, fnum);
2447 printf("CANCEL_LOCK gave %s\n", nt_errstr(status));
2449 cli_unlink(cli, fname[i], FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2452 torture_close_connection(cli);
2454 printf("finished locktest6\n");
2458 static bool run_locktest7(int dummy)
2460 struct cli_state *cli1;
2461 const char *fname = "\\lockt7.lck";
2464 bool correct = False;
2468 if (!torture_open_connection(&cli1, 0)) {
2472 smbXcli_conn_set_sockopt(cli1->conn, sockops);
2474 printf("starting locktest7\n");
2476 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2478 cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
2480 memset(buf, 0, sizeof(buf));
2482 status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 0, sizeof(buf),
2484 if (!NT_STATUS_IS_OK(status)) {
2485 printf("Failed to create file: %s\n", nt_errstr(status));
2489 cli_setpid(cli1, 1);
2491 status = cli_lock32(cli1, fnum1, 130, 4, 0, READ_LOCK);
2492 if (!NT_STATUS_IS_OK(status)) {
2493 printf("Unable to apply read lock on range 130:4, "
2494 "error was %s\n", nt_errstr(status));
2497 printf("pid1 successfully locked range 130:4 for READ\n");
2500 status = cli_read(cli1, fnum1, buf, 130, 4, &nread);
2501 if (!NT_STATUS_IS_OK(status)) {
2502 printf("pid1 unable to read the range 130:4, error was %s\n",
2505 } else if (nread != 4) {
2506 printf("pid1 unable to read the range 130:4, "
2507 "recv %ld req %d\n", (unsigned long)nread, 4);
2510 printf("pid1 successfully read the range 130:4\n");
2513 status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
2514 if (!NT_STATUS_IS_OK(status)) {
2515 printf("pid1 unable to write to the range 130:4, error was "
2516 "%s\n", nt_errstr(status));
2517 if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
2518 printf("Incorrect error (should be NT_STATUS_FILE_LOCK_CONFLICT)\n");
2522 printf("pid1 successfully wrote to the range 130:4 (should be denied)\n");
2526 cli_setpid(cli1, 2);
2528 status = cli_read(cli1, fnum1, buf, 130, 4, &nread);
2529 if (!NT_STATUS_IS_OK(status)) {
2530 printf("pid2 unable to read the range 130:4, error was %s\n",
2533 } else if (nread != 4) {
2534 printf("pid2 unable to read the range 130:4, "
2535 "recv %ld req %d\n", (unsigned long)nread, 4);
2538 printf("pid2 successfully read the range 130:4\n");
2541 status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
2542 if (!NT_STATUS_IS_OK(status)) {
2543 printf("pid2 unable to write to the range 130:4, error was "
2544 "%s\n", nt_errstr(status));
2545 if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
2546 printf("Incorrect error (should be NT_STATUS_FILE_LOCK_CONFLICT)\n");
2550 printf("pid2 successfully wrote to the range 130:4 (should be denied)\n");
2554 cli_setpid(cli1, 1);
2555 cli_unlock(cli1, fnum1, 130, 4);
2557 status = cli_lock32(cli1, fnum1, 130, 4, 0, WRITE_LOCK);
2558 if (!NT_STATUS_IS_OK(status)) {
2559 printf("Unable to apply write lock on range 130:4, error was %s\n", nt_errstr(status));
2562 printf("pid1 successfully locked range 130:4 for WRITE\n");
2565 status = cli_read(cli1, fnum1, buf, 130, 4, &nread);
2566 if (!NT_STATUS_IS_OK(status)) {
2567 printf("pid1 unable to read the range 130:4, error was %s\n",
2570 } else if (nread != 4) {
2571 printf("pid1 unable to read the range 130:4, "
2572 "recv %ld req %d\n", (unsigned long)nread, 4);
2575 printf("pid1 successfully read the range 130:4\n");
2578 status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
2579 if (!NT_STATUS_IS_OK(status)) {
2580 printf("pid1 unable to write to the range 130:4, error was "
2581 "%s\n", nt_errstr(status));
2584 printf("pid1 successfully wrote to the range 130:4\n");
2587 cli_setpid(cli1, 2);
2589 status = cli_read(cli1, fnum1, buf, 130, 4, &nread);
2590 if (!NT_STATUS_IS_OK(status)) {
2591 printf("pid2 unable to read the range 130:4, error was "
2592 "%s\n", nt_errstr(status));
2593 if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
2594 printf("Incorrect error (should be NT_STATUS_FILE_LOCK_CONFLICT)\n");
2598 printf("pid2 successfully read the range 130:4 (should be denied) recv %ld\n",
2599 (unsigned long)nread);
2603 status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
2604 if (!NT_STATUS_IS_OK(status)) {
2605 printf("pid2 unable to write to the range 130:4, error was "
2606 "%s\n", nt_errstr(status));
2607 if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
2608 printf("Incorrect error (should be NT_STATUS_FILE_LOCK_CONFLICT)\n");
2612 printf("pid2 successfully wrote to the range 130:4 (should be denied)\n");
2616 cli_unlock(cli1, fnum1, 130, 0);
2620 cli_close(cli1, fnum1);
2621 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2622 torture_close_connection(cli1);
2624 printf("finished locktest7\n");
2629 * This demonstrates a problem with our use of GPFS share modes: A file
2630 * descriptor sitting in the pending close queue holding a GPFS share mode
2631 * blocks opening a file another time. Happens with Word 2007 temp files.
2632 * With "posix locking = yes" and "gpfs:sharemodes = yes" enabled, the third
2633 * open is denied with NT_STATUS_SHARING_VIOLATION.
2636 static bool run_locktest8(int dummy)
2638 struct cli_state *cli1;
2639 const char *fname = "\\lockt8.lck";
2640 uint16_t fnum1, fnum2;
2642 bool correct = False;
2645 if (!torture_open_connection(&cli1, 0)) {
2649 smbXcli_conn_set_sockopt(cli1->conn, sockops);
2651 printf("starting locktest8\n");
2653 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2655 status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_WRITE,
2657 if (!NT_STATUS_IS_OK(status)) {
2658 d_fprintf(stderr, "cli_openx returned %s\n", nt_errstr(status));
2662 memset(buf, 0, sizeof(buf));
2664 status = cli_openx(cli1, fname, O_RDONLY, DENY_NONE, &fnum2);
2665 if (!NT_STATUS_IS_OK(status)) {
2666 d_fprintf(stderr, "cli_openx second time returned %s\n",
2671 status = cli_lock32(cli1, fnum2, 1, 1, 0, READ_LOCK);
2672 if (!NT_STATUS_IS_OK(status)) {
2673 printf("Unable to apply read lock on range 1:1, error was "
2674 "%s\n", nt_errstr(status));
2678 status = cli_close(cli1, fnum1);
2679 if (!NT_STATUS_IS_OK(status)) {
2680 d_fprintf(stderr, "cli_close(fnum1) %s\n", nt_errstr(status));
2684 status = cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
2685 if (!NT_STATUS_IS_OK(status)) {
2686 d_fprintf(stderr, "cli_openx third time returned %s\n",
2694 cli_close(cli1, fnum1);
2695 cli_close(cli1, fnum2);
2696 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2697 torture_close_connection(cli1);
2699 printf("finished locktest8\n");
2704 * This test is designed to be run in conjunction with
2705 * external NFS or POSIX locks taken in the filesystem.
2706 * It checks that the smbd server will block until the
2707 * lock is released and then acquire it. JRA.
2710 static bool got_alarm;
2711 static struct cli_state *alarm_cli;
2713 static void alarm_handler(int dummy)
2718 static void alarm_handler_parent(int dummy)
2720 smbXcli_conn_disconnect(alarm_cli->conn, NT_STATUS_LOCAL_DISCONNECT);
2723 static void do_local_lock(const char *fname, int read_fd, int write_fd)
2728 const char *local_pathname = NULL;
2731 local_pathname = talloc_asprintf(talloc_tos(),
2732 "%s/%s", local_path, fname);
2733 if (!local_pathname) {
2734 printf("child: alloc fail\n");
2738 unlink(local_pathname);
2739 fd = open(local_pathname, O_RDWR|O_CREAT, 0666);
2741 printf("child: open of %s failed %s.\n",
2742 local_pathname, strerror(errno));
2746 /* Now take a fcntl lock. */
2747 lock.l_type = F_WRLCK;
2748 lock.l_whence = SEEK_SET;
2751 lock.l_pid = getpid();
2753 ret = fcntl(fd,F_SETLK,&lock);
2755 printf("child: failed to get lock 0:4 on file %s. Error %s\n",
2756 local_pathname, strerror(errno));
2759 printf("child: got lock 0:4 on file %s.\n",
2764 CatchSignal(SIGALRM, alarm_handler);
2766 /* Signal the parent. */
2767 if (write(write_fd, &c, 1) != 1) {
2768 printf("child: start signal fail %s.\n",
2775 /* Wait for the parent to be ready. */
2776 if (read(read_fd, &c, 1) != 1) {
2777 printf("child: reply signal fail %s.\n",
2785 printf("child: released lock 0:4 on file %s.\n",
2791 static bool _run_locktest9X(const char *fname, int timeout)
2793 struct cli_state *cli1;
2794 char *fpath = talloc_asprintf(talloc_tos(), "\\%s", fname);
2796 bool correct = False;
2797 int pipe_in[2], pipe_out[2];
2801 struct timeval start;
2805 printf("starting locktest9X: %s\n", fname);
2807 if (local_path == NULL) {
2808 d_fprintf(stderr, "locktest9X must be given a local path via -l <localpath>\n");
2812 if (pipe(pipe_in) == -1 || pipe(pipe_out) == -1) {
2817 if (child_pid == -1) {
2821 if (child_pid == 0) {
2823 do_local_lock(fname, pipe_out[0], pipe_in[1]);
2833 ret = read(pipe_in[0], &c, 1);
2835 d_fprintf(stderr, "failed to read start signal from child. %s\n",
2840 if (!torture_open_connection(&cli1, 0)) {
2844 smbXcli_conn_set_sockopt(cli1->conn, sockops);
2846 status = cli_openx(cli1, fpath, O_RDWR, DENY_NONE,
2848 if (!NT_STATUS_IS_OK(status)) {
2849 d_fprintf(stderr, "cli_openx returned %s\n", nt_errstr(status));
2853 /* Ensure the child has the lock. */
2854 status = cli_lock32(cli1, fnum, 0, 4, 0, WRITE_LOCK);
2855 if (NT_STATUS_IS_OK(status)) {
2856 d_fprintf(stderr, "Got the lock on range 0:4 - this should not happen !\n");
2859 d_printf("Child has the lock.\n");
2862 /* Tell the child to wait 5 seconds then exit. */
2863 ret = write(pipe_out[1], &c, 1);
2865 d_fprintf(stderr, "failed to send exit signal to child. %s\n",
2870 /* Wait 20 seconds for the lock. */
2872 CatchSignal(SIGALRM, alarm_handler_parent);
2875 start = timeval_current();
2877 status = cli_lock32(cli1, fnum, 0, 4, timeout, WRITE_LOCK);
2878 if (!NT_STATUS_IS_OK(status)) {
2879 d_fprintf(stderr, "Unable to apply write lock on range 0:4, error was "
2880 "%s\n", nt_errstr(status));
2885 seconds = timeval_elapsed(&start);
2887 printf("Parent got the lock after %.2f seconds.\n",
2890 status = cli_close(cli1, fnum);
2891 if (!NT_STATUS_IS_OK(status)) {
2892 d_fprintf(stderr, "cli_close(fnum1) %s\n", nt_errstr(status));
2899 cli_close(cli1, fnum);
2900 torture_close_connection(cli1);
2904 printf("finished locktest9X: %s\n", fname);
2908 static bool run_locktest9a(int dummy)
2910 return _run_locktest9X("lock9a.dat", -1);
2913 static bool run_locktest9b(int dummy)
2915 return _run_locktest9X("lock9b.dat", 10000);
2918 struct locktest10_state {
2923 static void locktest10_lockingx_done(struct tevent_req *subreq);
2924 static void locktest10_read_andx_done(struct tevent_req *subreq);
2926 static bool run_locktest10(int dummy)
2928 struct tevent_context *ev = NULL;
2929 struct cli_state *cli1 = NULL;
2930 struct cli_state *cli2 = NULL;
2931 struct smb1_lock_element lck = { 0 };
2932 struct tevent_req *reqs[2] = { NULL };
2933 struct tevent_req *smbreqs[2] = { NULL };
2934 const char fname[] = "\\lockt10.lck";
2935 uint16_t fnum1, fnum2;
2939 struct locktest10_state state = { .ok = true };
2942 printf("starting locktest10\n");
2944 ev = samba_tevent_context_init(NULL);
2946 d_fprintf(stderr, "samba_tevent_context_init failed\n");
2950 ok = torture_open_connection(&cli1, 0);
2954 smbXcli_conn_set_sockopt(cli1->conn, sockops);
2956 ok = torture_open_connection(&cli2, 1);
2960 smbXcli_conn_set_sockopt(cli2->conn, sockops);
2962 status = cli_openx(cli1, fname, O_CREAT|O_RDWR, DENY_NONE, &fnum1);
2963 if (!NT_STATUS_IS_OK(status)) {
2965 "cli_openx failed: %s\n",
2970 status = cli_writeall(cli1, fnum1, 0, &data, 0, sizeof(data), NULL);
2971 if (!NT_STATUS_IS_OK(status)) {
2973 "cli_writeall failed: %s\n",
2978 status = cli_openx(cli2, fname, O_CREAT|O_RDWR, DENY_NONE, &fnum2);
2979 if (!NT_STATUS_IS_OK(status)) {
2981 "cli_openx failed: %s\n",
2986 status = cli_locktype(
2987 cli2, fnum2, 0, 1, 0, LOCKING_ANDX_EXCLUSIVE_LOCK);
2988 if (!NT_STATUS_IS_OK(status)) {
2990 "cli_locktype failed: %s\n",
2995 lck = (struct smb1_lock_element) {
2996 .pid = cli_getpid(cli1), .offset = 0, .length = 1,
2999 reqs[0] = cli_lockingx_create(
3001 ev, /* tevent_context */
3004 LOCKING_ANDX_EXCLUSIVE_LOCK, /* typeoflock */
3005 0, /* newoplocklevel */
3007 0, /* num_unlocks */
3011 &smbreqs[0]); /* psmbreq */
3012 if (reqs[0] == NULL) {
3013 d_fprintf(stderr, "cli_lockingx_create failed\n");
3016 tevent_req_set_callback(reqs[0], locktest10_lockingx_done, &state);
3018 reqs[1] = cli_read_andx_create(
3025 &smbreqs[1]); /* psmbreq */
3026 if (reqs[1] == NULL) {
3027 d_fprintf(stderr, "cli_read_andx_create failed\n");
3030 tevent_req_set_callback(reqs[1], locktest10_read_andx_done, &state);
3032 status = smb1cli_req_chain_submit(smbreqs, ARRAY_SIZE(smbreqs));
3033 if (!NT_STATUS_IS_OK(status)) {
3035 "smb1cli_req_chain_submit failed: %s\n",
3040 while (!state.done) {
3041 tevent_loop_once(ev);
3044 torture_close_connection(cli1);
3053 static void locktest10_lockingx_done(struct tevent_req *subreq)
3055 struct locktest10_state *state = tevent_req_callback_data_void(subreq);
3058 status = cli_lockingx_recv(subreq);
3059 TALLOC_FREE(subreq);
3061 if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
3062 d_printf("cli_lockingx returned %s\n", nt_errstr(status));
3067 static void locktest10_read_andx_done(struct tevent_req *subreq)
3069 struct locktest10_state *state = tevent_req_callback_data_void(subreq);
3070 ssize_t received = -1;
3071 uint8_t *rcvbuf = NULL;
3074 status = cli_read_andx_recv(subreq, &received, &rcvbuf);
3076 if (!NT_STATUS_EQUAL(status, NT_STATUS_REQUEST_ABORTED)) {
3077 d_printf("cli_read_andx returned %s\n", nt_errstr(status));
3082 TALLOC_FREE(subreq);
3085 static bool run_locktest11(int dummy)
3087 struct cli_state *cli1;
3088 const char *fname = "\\lockt11.lck";
3093 if (!torture_open_connection(&cli1, 0)) {
3097 smbXcli_conn_set_sockopt(cli1->conn, sockops);
3099 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3101 status = cli_openx(cli1, fname, O_CREAT|O_RDWR, DENY_NONE, &fnum);
3102 if (!NT_STATUS_IS_OK(status)) {
3104 "cli_openx returned %s\n",
3110 * Test that LOCKING_ANDX_CANCEL_LOCK without any locks
3111 * returns NT_STATUS_OK
3114 status = cli_lockingx(
3117 LOCKING_ANDX_CANCEL_LOCK, /* typeoflock */
3118 0, /* newoplocklevel */
3120 0, /* num_unlocks */
3125 if (!NT_STATUS_IS_OK(status)) {
3126 d_printf("cli_lockingX returned %s\n", nt_errstr(status));
3132 cli_close(cli1, fnum);
3133 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3138 struct deferred_close_state {
3139 struct tevent_context *ev;
3140 struct cli_state *cli;
3144 static void deferred_close_waited(struct tevent_req *subreq);
3145 static void deferred_close_done(struct tevent_req *subreq);
3147 static struct tevent_req *deferred_close_send(
3148 TALLOC_CTX *mem_ctx,
3149 struct tevent_context *ev,
3151 struct cli_state *cli,
3154 struct tevent_req *req = NULL, *subreq = NULL;
3155 struct deferred_close_state *state = NULL;
3156 struct timeval wakeup_time = timeval_current_ofs(wait_secs, 0);
3158 req = tevent_req_create(
3159 mem_ctx, &state, struct deferred_close_state);
3167 subreq = tevent_wakeup_send(state, state->ev, wakeup_time);
3168 if (tevent_req_nomem(subreq, req)) {
3169 return tevent_req_post(req, ev);
3171 tevent_req_set_callback(subreq, deferred_close_waited, req);
3175 static void deferred_close_waited(struct tevent_req *subreq)
3177 struct tevent_req *req = tevent_req_callback_data(
3178 subreq, struct tevent_req);
3179 struct deferred_close_state *state = tevent_req_data(
3180 req, struct deferred_close_state);
3183 ok = tevent_wakeup_recv(subreq);
3184 TALLOC_FREE(subreq);
3186 tevent_req_oom(req);
3190 subreq = cli_close_send(state, state->ev, state->cli, state->fnum, 0);
3191 if (tevent_req_nomem(subreq, req)) {
3194 tevent_req_set_callback(subreq, deferred_close_done, req);
3197 static void deferred_close_done(struct tevent_req *subreq)
3199 NTSTATUS status = cli_close_recv(subreq);
3200 tevent_req_simple_finish_ntstatus(subreq, status);
3203 static NTSTATUS deferred_close_recv(struct tevent_req *req)
3205 return tevent_req_simple_recv_ntstatus(req);
3208 struct lockread_state {
3209 struct smb1_lock_element lck;
3210 struct tevent_req *reqs[2];
3211 struct tevent_req *smbreqs[2];
3212 NTSTATUS lock_status;
3213 NTSTATUS read_status;
3217 static void lockread_lockingx_done(struct tevent_req *subreq);
3218 static void lockread_read_andx_done(struct tevent_req *subreq);
3220 static struct tevent_req *lockread_send(
3221 TALLOC_CTX *mem_ctx,
3222 struct tevent_context *ev,
3223 struct cli_state *cli,
3226 struct tevent_req *req = NULL;
3227 struct lockread_state *state = NULL;
3230 req = tevent_req_create(mem_ctx, &state, struct lockread_state);
3235 state->lck = (struct smb1_lock_element) {
3236 .pid = cli_getpid(cli), .offset = 0, .length = 1,
3239 state->reqs[0] = cli_lockingx_create(
3241 ev, /* tevent_context */
3244 LOCKING_ANDX_EXCLUSIVE_LOCK, /* typeoflock */
3245 0, /* newoplocklevel */
3246 10000, /* timeout */
3247 0, /* num_unlocks */
3250 &state->lck, /* locks */
3251 &state->smbreqs[0]); /* psmbreq */
3252 if (tevent_req_nomem(state->reqs[0], req)) {
3253 return tevent_req_post(req, ev);
3255 tevent_req_set_callback(
3256 state->reqs[0], lockread_lockingx_done, req);
3258 state->reqs[1] = cli_read_andx_create(
3265 &state->smbreqs[1]); /* psmbreq */
3266 if (tevent_req_nomem(state->reqs[1], req)) {
3267 return tevent_req_post(req, ev);
3269 tevent_req_set_callback(
3270 state->reqs[1], lockread_read_andx_done, req);
3272 status = smb1cli_req_chain_submit(state->smbreqs, 2);
3273 if (tevent_req_nterror(req, status)) {
3274 return tevent_req_post(req, ev);
3279 static void lockread_lockingx_done(struct tevent_req *subreq)
3281 struct tevent_req *req = tevent_req_callback_data(
3282 subreq, struct tevent_req);
3283 struct lockread_state *state = tevent_req_data(
3284 req, struct lockread_state);
3285 state->lock_status = cli_lockingx_recv(subreq);
3286 TALLOC_FREE(subreq);
3288 "lockingx returned %s\n",
3289 nt_errstr(state->lock_status));
3292 static void lockread_read_andx_done(struct tevent_req *subreq)
3294 struct tevent_req *req = tevent_req_callback_data(
3295 subreq, struct tevent_req);
3296 struct lockread_state *state = tevent_req_data(
3297 req, struct lockread_state);
3298 ssize_t received = -1;
3299 uint8_t *rcvbuf = NULL;
3301 state->read_status = cli_read_andx_recv(subreq, &received, &rcvbuf);
3304 "read returned %s\n",
3305 nt_errstr(state->read_status));
3307 if (!NT_STATUS_IS_OK(state->read_status)) {
3308 TALLOC_FREE(subreq);
3309 tevent_req_done(req);
3314 state->readbuf = talloc_memdup(state, rcvbuf, received);
3315 TALLOC_FREE(subreq);
3316 if (tevent_req_nomem(state->readbuf, req)) {
3320 TALLOC_FREE(subreq);
3321 tevent_req_done(req);
3324 static NTSTATUS lockread_recv(
3325 struct tevent_req *req,
3326 NTSTATUS *lock_status,
3327 NTSTATUS *read_status,
3328 TALLOC_CTX *mem_ctx,
3331 struct lockread_state *state = tevent_req_data(
3332 req, struct lockread_state);
3335 if (tevent_req_is_nterror(req, &status)) {
3339 *lock_status = state->lock_status;
3340 *read_status = state->read_status;
3341 if (state->readbuf != NULL) {
3342 *read_buf = talloc_move(mem_ctx, &state->readbuf);
3347 return NT_STATUS_OK;
3350 struct lock12_state {
3354 static void lock12_closed(struct tevent_req *subreq);
3355 static void lock12_read(struct tevent_req *subreq);
3357 static struct tevent_req *lock12_send(
3358 TALLOC_CTX *mem_ctx,
3359 struct tevent_context *ev,
3360 struct cli_state *cli,
3364 struct tevent_req *req = NULL, *subreq = NULL;
3365 struct lock12_state *state = NULL;
3367 req = tevent_req_create(mem_ctx, &state, struct lock12_state);
3372 subreq = deferred_close_send(state, ev, 1, cli, fnum1);
3373 if (tevent_req_nomem(subreq, req)) {
3374 return tevent_req_post(req, ev);
3376 tevent_req_set_callback(subreq, lock12_closed, req);
3378 subreq = lockread_send(state, ev, cli, fnum2);
3379 if (tevent_req_nomem(subreq, req)) {
3380 return tevent_req_post(req, ev);
3382 tevent_req_set_callback(subreq, lock12_read, req);
3387 static void lock12_closed(struct tevent_req *subreq)
3389 struct tevent_req *req = tevent_req_callback_data(
3390 subreq, struct tevent_req);
3393 status = deferred_close_recv(subreq);
3394 TALLOC_FREE(subreq);
3395 DBG_DEBUG("close returned %s\n", nt_errstr(status));
3396 if (tevent_req_nterror(req, status)) {
3401 static void lock12_read(struct tevent_req *subreq)
3403 struct tevent_req *req = tevent_req_callback_data(
3404 subreq, struct tevent_req);
3405 struct lock12_state *state = tevent_req_data(
3406 req, struct lock12_state);
3407 NTSTATUS status, lock_status, read_status;
3408 uint8_t *buf = NULL;
3410 status = lockread_recv(
3411 subreq, &lock_status, &read_status, state, &buf);
3412 TALLOC_FREE(subreq);
3413 if (tevent_req_nterror(req, status) ||
3414 tevent_req_nterror(req, lock_status) ||
3415 tevent_req_nterror(req, read_status)) {
3418 tevent_req_done(req);
3421 static NTSTATUS lock12_recv(struct tevent_req *req)
3426 if (tevent_req_is_nterror(req, &status)) {
3429 return NT_STATUS_OK;
3432 static bool run_locktest12(int dummy)
3434 struct tevent_context *ev = NULL;
3435 struct tevent_req *req = NULL;
3436 struct cli_state *cli = NULL;
3437 const char fname[] = "\\lockt12.lck";
3438 uint16_t fnum1, fnum2;
3444 printf("starting locktest12\n");
3446 ev = samba_tevent_context_init(NULL);
3448 d_fprintf(stderr, "samba_tevent_context_init failed\n");
3452 ok = torture_open_connection(&cli, 0);
3456 smbXcli_conn_set_sockopt(cli->conn, sockops);
3458 status = cli_openx(cli, fname, O_CREAT|O_RDWR, DENY_NONE, &fnum1);
3459 if (!NT_STATUS_IS_OK(status)) {
3461 "cli_openx failed: %s\n",
3466 status = cli_openx(cli, fname, O_CREAT|O_RDWR, DENY_NONE, &fnum2);
3467 if (!NT_STATUS_IS_OK(status)) {
3469 "cli_openx failed: %s\n",
3474 status = cli_writeall(cli, fnum1, 0, &data, 0, sizeof(data), NULL);
3475 if (!NT_STATUS_IS_OK(status)) {
3477 "cli_writeall failed: %s\n",
3482 status = cli_locktype(
3483 cli, fnum1, 0, 1, 0, LOCKING_ANDX_EXCLUSIVE_LOCK);
3484 if (!NT_STATUS_IS_OK(status)) {
3486 "cli_locktype failed: %s\n",
3491 req = lock12_send(ev, ev, cli, fnum1, fnum2);
3493 d_fprintf(stderr, "lock12_send failed\n");
3497 ok = tevent_req_poll_ntstatus(req, ev, &status);
3499 d_fprintf(stderr, "tevent_req_poll_ntstatus failed\n");
3503 if (!NT_STATUS_IS_OK(status)) {
3505 "tevent_req_poll_ntstatus returned %s\n",
3510 status = lock12_recv(req);
3511 if (!NT_STATUS_IS_OK(status)) {
3512 d_fprintf(stderr, "lock12 returned %s\n", nt_errstr(status));
3519 torture_close_connection(cli);
3524 struct lock_ntcancel_state {
3525 struct timeval start;
3526 struct smb1_lock_element lck;
3527 struct tevent_req *subreq;
3530 static void lock_ntcancel_waited(struct tevent_req *subreq);
3531 static void lock_ntcancel_done(struct tevent_req *subreq);
3533 static struct tevent_req *lock_ntcancel_send(
3534 TALLOC_CTX *mem_ctx,
3535 struct tevent_context *ev,
3536 struct cli_state *cli,
3539 struct tevent_req *req = NULL, *subreq = NULL;
3540 struct lock_ntcancel_state *state = NULL;
3542 req = tevent_req_create(mem_ctx, &state, struct lock_ntcancel_state);
3546 state->lck = (struct smb1_lock_element) {
3547 .pid = cli_getpid(cli), .offset = 0, .length = 1,
3549 state->start = timeval_current();
3551 state->subreq = cli_lockingx_send(
3552 state, /* mem_ctx */
3553 ev, /* tevent_context */
3556 LOCKING_ANDX_EXCLUSIVE_LOCK, /* typeoflock */
3557 0, /* newoplocklevel */
3558 10000, /* timeout */
3559 0, /* num_unlocks */
3562 &state->lck); /* locks */
3563 if (tevent_req_nomem(state->subreq, req)) {
3564 return tevent_req_post(req, ev);
3566 tevent_req_set_callback(state->subreq, lock_ntcancel_done, req);
3568 subreq = tevent_wakeup_send(state, ev, timeval_current_ofs(1, 0));
3569 if (tevent_req_nomem(subreq, req)) {
3570 return tevent_req_post(req, ev);
3572 tevent_req_set_callback(subreq, lock_ntcancel_waited, req);
3576 static void lock_ntcancel_waited(struct tevent_req *subreq)
3578 struct tevent_req *req = tevent_req_callback_data(
3579 subreq, struct tevent_req);
3580 struct lock_ntcancel_state *state = tevent_req_data(
3581 req, struct lock_ntcancel_state);
3584 ok = tevent_wakeup_recv(subreq);
3585 TALLOC_FREE(subreq);
3587 tevent_req_oom(req);
3591 ok = tevent_req_cancel(state->subreq);
3593 d_fprintf(stderr, "Could not cancel subreq\n");
3594 tevent_req_oom(req);
3599 static void lock_ntcancel_done(struct tevent_req *subreq)
3601 struct tevent_req *req = tevent_req_callback_data(
3602 subreq, struct tevent_req);
3603 struct lock_ntcancel_state *state = tevent_req_data(
3604 req, struct lock_ntcancel_state);
3608 status = cli_lockingx_recv(subreq);
3609 TALLOC_FREE(subreq);
3611 if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
3612 d_printf("cli_lockingx returned %s\n", nt_errstr(status));
3613 tevent_req_nterror(req, NT_STATUS_UNSUCCESSFUL);
3617 elapsed = timeval_elapsed(&state->start);
3620 d_printf("cli_lockingx was too slow, cancel did not work\n");
3621 tevent_req_nterror(req, NT_STATUS_UNSUCCESSFUL);
3625 tevent_req_done(req);
3628 static NTSTATUS lock_ntcancel_recv(struct tevent_req *req)
3630 return tevent_req_simple_recv_ntstatus(req);
3633 static bool run_locktest13(int dummy)
3635 struct tevent_context *ev = NULL;
3636 struct tevent_req *req = NULL;
3637 struct cli_state *cli = NULL;
3638 const char fname[] = "\\lockt13.lck";
3639 uint16_t fnum1, fnum2;
3645 printf("starting locktest13\n");
3647 ev = samba_tevent_context_init(NULL);
3649 d_fprintf(stderr, "samba_tevent_context_init failed\n");
3653 ok = torture_open_connection(&cli, 0);
3657 smbXcli_conn_set_sockopt(cli->conn, sockops);
3659 status = cli_openx(cli, fname, O_CREAT|O_RDWR, DENY_NONE, &fnum1);
3660 if (!NT_STATUS_IS_OK(status)) {
3662 "cli_openx failed: %s\n",
3667 status = cli_openx(cli, fname, O_CREAT|O_RDWR, DENY_NONE, &fnum2);
3668 if (!NT_STATUS_IS_OK(status)) {
3670 "cli_openx failed: %s\n",
3675 status = cli_writeall(cli, fnum1, 0, &data, 0, sizeof(data), NULL);
3676 if (!NT_STATUS_IS_OK(status)) {
3678 "cli_writeall failed: %s\n",
3683 status = cli_locktype(
3684 cli, fnum1, 0, 1, 0, LOCKING_ANDX_EXCLUSIVE_LOCK);
3685 if (!NT_STATUS_IS_OK(status)) {
3687 "cli_locktype failed: %s\n",
3692 req = lock_ntcancel_send(ev, ev, cli, fnum2);
3694 d_fprintf(stderr, "lock_ntcancel_send failed\n");
3698 ok = tevent_req_poll_ntstatus(req, ev, &status);
3700 d_fprintf(stderr, "tevent_req_poll_ntstatus failed\n");
3704 if (!NT_STATUS_IS_OK(status)) {
3706 "tevent_req_poll_ntstatus returned %s\n",
3711 status = lock_ntcancel_recv(req);
3712 if (!NT_STATUS_IS_OK(status)) {
3714 "lock_ntcancel returned %s\n",
3722 torture_close_connection(cli);
3728 test whether fnums and tids open on one VC are available on another (a major
3731 static bool run_fdpasstest(int dummy)
3733 struct cli_state *cli1, *cli2;
3734 const char *fname = "\\fdpass.tst";
3739 if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
3742 smbXcli_conn_set_sockopt(cli1->conn, sockops);
3743 smbXcli_conn_set_sockopt(cli2->conn, sockops);
3745 printf("starting fdpasstest\n");
3747 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3749 status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
3751 if (!NT_STATUS_IS_OK(status)) {
3752 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
3756 status = cli_writeall(cli1, fnum1, 0, (const uint8_t *)"hello world\n", 0,
3758 if (!NT_STATUS_IS_OK(status)) {
3759 printf("write failed (%s)\n", nt_errstr(status));
3763 cli_state_set_uid(cli2, cli_state_get_uid(cli1));
3764 cli_state_set_tid(cli2, cli_state_get_tid(cli1));
3765 cli_setpid(cli2, cli_getpid(cli1));
3767 if (test_cli_read(cli2, fnum1, buf, 0, 13, NULL, 13)) {
3768 printf("read succeeded! nasty security hole [%s]\n", buf);
3772 cli_close(cli1, fnum1);
3773 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3775 torture_close_connection(cli1);
3776 torture_close_connection(cli2);
3778 printf("finished fdpasstest\n");
3782 static bool run_fdsesstest(int dummy)
3784 struct cli_state *cli;
3786 uint16_t saved_vuid;
3788 uint32_t saved_cnum;
3789 const char *fname = "\\fdsess.tst";
3790 const char *fname1 = "\\fdsess1.tst";
3797 if (!torture_open_connection(&cli, 0))
3799 smbXcli_conn_set_sockopt(cli->conn, sockops);
3801 if (!torture_cli_session_setup2(cli, &new_vuid))
3804 saved_cnum = cli_state_get_tid(cli);
3805 if (!NT_STATUS_IS_OK(cli_tree_connect(cli, share, "?????", NULL)))
3807 new_cnum = cli_state_get_tid(cli);
3808 cli_state_set_tid(cli, saved_cnum);
3810 printf("starting fdsesstest\n");
3812 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3813 cli_unlink(cli, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3815 status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
3816 if (!NT_STATUS_IS_OK(status)) {
3817 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
3821 status = cli_writeall(cli, fnum1, 0, (const uint8_t *)"hello world\n", 0, 13,
3823 if (!NT_STATUS_IS_OK(status)) {
3824 printf("write failed (%s)\n", nt_errstr(status));
3828 saved_vuid = cli_state_get_uid(cli);
3829 cli_state_set_uid(cli, new_vuid);
3831 if (test_cli_read(cli, fnum1, buf, 0, 13, NULL, 13)) {
3832 printf("read succeeded with different vuid! "
3833 "nasty security hole [%s]\n", buf);
3836 /* Try to open a file with different vuid, samba cnum. */
3837 if (NT_STATUS_IS_OK(cli_openx(cli, fname1, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum2))) {
3838 printf("create with different vuid, same cnum succeeded.\n");
3839 cli_close(cli, fnum2);
3840 cli_unlink(cli, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3842 printf("create with different vuid, same cnum failed.\n");
3843 printf("This will cause problems with service clients.\n");
3847 cli_state_set_uid(cli, saved_vuid);
3849 /* Try with same vuid, different cnum. */
3850 cli_state_set_tid(cli, new_cnum);
3852 if (test_cli_read(cli, fnum1, buf, 0, 13, NULL, 13)) {
3853 printf("read succeeded with different cnum![%s]\n", buf);
3857 cli_state_set_tid(cli, saved_cnum);
3858 cli_close(cli, fnum1);
3859 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3861 torture_close_connection(cli);
3863 printf("finished fdsesstest\n");
3868 This test checks that
3870 1) the server does not allow an unlink on a file that is open
3872 static bool run_unlinktest(int dummy)
3874 struct cli_state *cli;
3875 const char *fname = "\\unlink.tst";
3877 bool correct = True;
3880 if (!torture_open_connection(&cli, 0)) {
3884 smbXcli_conn_set_sockopt(cli->conn, sockops);
3886 printf("starting unlink test\n");
3888 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3892 status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
3893 if (!NT_STATUS_IS_OK(status)) {
3894 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
3898 status = cli_unlink(cli, fname,
3899 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3900 if (NT_STATUS_IS_OK(status)) {
3901 printf("error: server allowed unlink on an open file\n");
3904 correct = check_error(__LINE__, status, ERRDOS, ERRbadshare,
3905 NT_STATUS_SHARING_VIOLATION);
3908 cli_close(cli, fnum);
3909 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3911 if (!torture_close_connection(cli)) {
3915 printf("unlink test finished\n");
3922 test how many open files this server supports on the one socket
3924 static bool run_maxfidtest(int dummy)
3926 struct cli_state *cli;
3928 uint16_t fnums[0x11000];
3931 bool correct = True;
3937 printf("failed to connect\n");
3941 smbXcli_conn_set_sockopt(cli->conn, sockops);
3943 for (i=0; i<0x11000; i++) {
3944 slprintf(fname,sizeof(fname)-1,"\\maxfid.%d.%d", i,(int)getpid());
3945 status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_TRUNC, DENY_NONE,
3947 if (!NT_STATUS_IS_OK(status)) {
3948 printf("open of %s failed (%s)\n",
3949 fname, nt_errstr(status));
3950 printf("maximum fnum is %d\n", i);
3958 printf("cleaning up\n");
3960 slprintf(fname,sizeof(fname)-1,"\\maxfid.%d.%d", i,(int)getpid());
3961 cli_close(cli, fnums[i]);
3963 status = cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3964 if (!NT_STATUS_IS_OK(status)) {
3965 printf("unlink of %s failed (%s)\n",
3966 fname, nt_errstr(status));
3973 printf("maxfid test finished\n");
3974 if (!torture_close_connection(cli)) {
3980 /* generate a random buffer */
3981 static void rand_buf(char *buf, int len)
3984 *buf = (char)sys_random();
3989 /* send smb negprot commands, not reading the response */
3990 static bool run_negprot_nowait(int dummy)
3992 struct tevent_context *ev;
3994 struct cli_state *cli;
3995 bool correct = True;
3997 printf("starting negprot nowait test\n");
3999 ev = samba_tevent_context_init(talloc_tos());
4004 if (!(cli = open_nbt_connection())) {
4009 for (i=0;i<50000;i++) {
4010 struct tevent_req *req;
4012 req = smbXcli_negprot_send(
4025 if (!tevent_req_poll(req, ev)) {
4026 d_fprintf(stderr, "tevent_req_poll failed: %s\n",
4034 if (torture_close_connection(cli)) {
4038 printf("finished negprot nowait test\n");
4043 /* send smb negprot commands, not reading the response */
4044 static bool run_bad_nbt_session(int dummy)
4046 struct nmb_name called, calling;
4047 struct sockaddr_storage ss;
4052 printf("starting bad nbt session test\n");
4054 make_nmb_name(&calling, myname, 0x0);
4055 make_nmb_name(&called , host, 0x20);
4057 if (!resolve_name(host, &ss, 0x20, true)) {
4058 d_fprintf(stderr, "Could not resolve name %s\n", host);
4062 status = open_socket_out(&ss, NBT_SMB_PORT, 10000, &fd);
4063 if (!NT_STATUS_IS_OK(status)) {
4064 d_fprintf(stderr, "open_socket_out failed: %s\n",
4069 ret = cli_bad_session_request(fd, &calling, &called);
4072 d_fprintf(stderr, "open_socket_out failed: %s\n",
4077 printf("finished bad nbt session test\n");
4081 /* send random IPC commands */
4082 static bool run_randomipc(int dummy)
4084 char *rparam = NULL;
4086 unsigned int rdrcnt,rprcnt;
4088 int api, param_len, i;
4089 struct cli_state *cli;
4090 bool correct = True;
4093 printf("starting random ipc test\n");
4095 if (!torture_open_connection(&cli, 0)) {
4099 for (i=0;i<count;i++) {
4100 api = sys_random() % 500;
4101 param_len = (sys_random() % 64);
4103 rand_buf(param, param_len);
4108 param, param_len, 8,
4109 NULL, 0, CLI_BUFFER_SIZE,
4113 printf("%d/%d\r", i,count);
4116 printf("%d/%d\n", i, count);
4118 if (!torture_close_connection(cli)) {
4125 printf("finished random ipc test\n");
4132 static void browse_callback(const char *sname, uint32_t stype,
4133 const char *comment, void *state)
4135 printf("\t%20.20s %08x %s\n", sname, stype, comment);
4141 This test checks the browse list code
4144 static bool run_browsetest(int dummy)
4146 static struct cli_state *cli;
4147 bool correct = True;
4149 printf("starting browse test\n");
4151 if (!torture_open_connection(&cli, 0)) {
4155 printf("domain list:\n");
4156 cli_NetServerEnum(cli, cli->server_domain,
4157 SV_TYPE_DOMAIN_ENUM,
4158 browse_callback, NULL);
4160 printf("machine list:\n");
4161 cli_NetServerEnum(cli, cli->server_domain,
4163 browse_callback, NULL);
4165 if (!torture_close_connection(cli)) {
4169 printf("browse test finished\n");
4175 static bool check_attributes(struct cli_state *cli,
4177 uint32_t expected_attrs)
4180 NTSTATUS status = cli_getatr(cli,
4185 if (!NT_STATUS_IS_OK(status)) {
4186 printf("cli_getatr failed with %s\n",
4190 if (attrs != expected_attrs) {
4191 printf("Attributes incorrect 0x%x, should be 0x%x\n",
4192 (unsigned int)attrs,
4193 (unsigned int)expected_attrs);
4200 This checks how the getatr calls works
4202 static bool run_attrtest(int dummy)
4204 struct cli_state *cli;
4207 const char *fname = "\\attrib123456789.tst";
4208 bool correct = True;
4211 printf("starting attrib test\n");
4213 if (!torture_open_connection(&cli, 0)) {
4217 /* Ensure we can't unlink with out-of-range (unknown) attribute. */
4218 status = cli_unlink(cli, fname, 0x20000);
4219 if (!NT_STATUS_EQUAL(status, NT_STATUS_INVALID_PARAMETER)) {
4224 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4225 cli_openx(cli, fname,
4226 O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum);
4227 cli_close(cli, fnum);
4229 status = cli_getatr(cli, fname, NULL, NULL, &t);
4230 if (!NT_STATUS_IS_OK(status)) {
4231 printf("getatr failed (%s)\n", nt_errstr(status));
4235 if (labs(t - time(NULL)) > 60*60*24*10) {
4236 printf("ERROR: SMBgetatr bug. time is %s",
4242 t2 = t-60*60*24; /* 1 day ago */
4244 /* Ensure we can't set with out-of-range (unknown) attribute. */
4245 status = cli_setatr(cli, fname, 0x20000, t2);
4246 if (!NT_STATUS_EQUAL(status, NT_STATUS_INVALID_PARAMETER)) {
4251 status = cli_setatr(cli, fname, 0, t2);
4252 if (!NT_STATUS_IS_OK(status)) {
4253 printf("setatr failed (%s)\n", nt_errstr(status));
4257 status = cli_getatr(cli, fname, NULL, NULL, &t);
4258 if (!NT_STATUS_IS_OK(status)) {
4259 printf("getatr failed (%s)\n", nt_errstr(status));
4264 printf("ERROR: getatr/setatr bug. times are\n%s",
4266 printf("%s", ctime(&t2));
4270 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4272 /* Check cli_setpathinfo_ext() */
4273 /* Re-create the file. */
4274 status = cli_openx(cli, fname,
4275 O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum);
4276 if (!NT_STATUS_IS_OK(status)) {
4277 printf("Failed to recreate %s (%s)\n",
4278 fname, nt_errstr(status));
4281 cli_close(cli, fnum);
4283 status = cli_setpathinfo_ext(
4286 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* create */
4287 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* access */
4288 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* write */
4289 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* change */
4290 FILE_ATTRIBUTE_SYSTEM |
4291 FILE_ATTRIBUTE_HIDDEN |
4292 FILE_ATTRIBUTE_READONLY);
4293 if (!NT_STATUS_IS_OK(status)) {
4294 printf("cli_setpathinfo_ext failed with %s\n",
4299 /* Check attributes are correct. */
4300 correct = check_attributes(cli,
4302 FILE_ATTRIBUTE_SYSTEM |
4303 FILE_ATTRIBUTE_HIDDEN |
4304 FILE_ATTRIBUTE_READONLY);
4305 if (correct == false) {
4309 /* Setting to FILE_ATTRIBUTE_NORMAL should be ignored. */
4310 status = cli_setpathinfo_ext(
4313 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* create */
4314 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* access */
4315 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* write */
4316 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* change */
4317 FILE_ATTRIBUTE_NORMAL);
4318 if (!NT_STATUS_IS_OK(status)) {
4319 printf("cli_setpathinfo_ext failed with %s\n",
4324 /* Check attributes are correct. */
4325 correct = check_attributes(cli,
4327 FILE_ATTRIBUTE_SYSTEM |
4328 FILE_ATTRIBUTE_HIDDEN |
4329 FILE_ATTRIBUTE_READONLY);
4330 if (correct == false) {
4334 /* Setting to (uint16_t)-1 should also be ignored. */
4335 status = cli_setpathinfo_ext(
4338 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* create */
4339 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* access */
4340 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* write */
4341 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* change */
4343 if (!NT_STATUS_IS_OK(status)) {
4344 printf("cli_setpathinfo_ext failed with %s\n",
4349 /* Check attributes are correct. */
4350 correct = check_attributes(cli,
4352 FILE_ATTRIBUTE_SYSTEM |
4353 FILE_ATTRIBUTE_HIDDEN |
4354 FILE_ATTRIBUTE_READONLY);
4355 if (correct == false) {
4359 /* Setting to 0 should clear them all. */
4360 status = cli_setpathinfo_ext(
4363 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* create */
4364 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* access */
4365 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* write */
4366 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* change */
4368 if (!NT_STATUS_IS_OK(status)) {
4369 printf("cli_setpathinfo_ext failed with %s\n",
4374 /* Check attributes are correct. */
4375 correct = check_attributes(cli,
4377 FILE_ATTRIBUTE_NORMAL);
4378 if (correct == false) {
4386 FILE_ATTRIBUTE_SYSTEM |
4387 FILE_ATTRIBUTE_HIDDEN|
4388 FILE_ATTRIBUTE_READONLY);
4390 if (!torture_close_connection(cli)) {
4394 printf("attrib test finished\n");
4399 static NTSTATUS cli_qfilename(
4400 struct cli_state *cli,
4402 TALLOC_CTX *mem_ctx,
4405 uint16_t recv_flags2;
4412 status = cli_qfileinfo(talloc_tos(), cli, fnum,
4413 SMB_QUERY_FILE_NAME_INFO,
4414 4, CLI_BUFFER_SIZE, &recv_flags2,
4415 &rdata, &num_rdata);
4416 if (!NT_STATUS_IS_OK(status)) {
4420 namelen = IVAL(rdata, 0);
4421 if (namelen > (num_rdata - 4)) {
4423 return NT_STATUS_INVALID_NETWORK_RESPONSE;
4426 pull_string_talloc(mem_ctx,
4427 (const char *)rdata,
4434 status = map_nt_error_from_unix(errno);
4441 return NT_STATUS_OK;
4445 This checks a couple of trans2 calls
4447 static bool run_trans2test(int dummy)
4449 struct cli_state *cli;
4452 time_t c_time, a_time, m_time;
4453 struct timespec c_time_ts, a_time_ts, m_time_ts, w_time_ts, m_time2_ts;
4454 const char *fname = "\\trans2.tst";
4455 const char *dname = "\\trans2";
4456 const char *fname2 = "\\trans2\\trans2.tst";
4458 bool correct = True;
4463 printf("starting trans2 test\n");
4465 if (!torture_open_connection(&cli, 0)) {
4469 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
4470 /* Ensure ino is zero, SMB2 gets a real one. */
4473 /* Ensure ino is -1, SMB1 never gets a real one. */
4477 status = cli_get_fs_attr_info(cli, &fs_attr);
4478 if (!NT_STATUS_IS_OK(status)) {
4479 printf("ERROR: cli_get_fs_attr_info returned %s\n",
4484 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4485 cli_openx(cli, fname, O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum);
4486 status = cli_qfileinfo_basic(cli, fnum, NULL, &size, &c_time_ts,
4487 &a_time_ts, &w_time_ts, &m_time_ts, NULL);
4488 if (!NT_STATUS_IS_OK(status)) {
4489 printf("ERROR: qfileinfo failed (%s)\n", nt_errstr(status));
4493 status = cli_qfilename(cli, fnum, talloc_tos(), &pname);
4494 if (!NT_STATUS_IS_OK(status)) {
4495 printf("ERROR: qfilename failed (%s)\n", nt_errstr(status));
4498 else if (strcmp(pname, fname)) {
4499 printf("qfilename gave different name? [%s] [%s]\n",
4504 cli_close(cli, fnum);
4508 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4509 status = cli_openx(cli, fname, O_RDWR | O_CREAT | O_TRUNC, DENY_NONE,
4511 if (!NT_STATUS_IS_OK(status)) {
4512 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
4515 cli_close(cli, fnum);
4517 status = cli_qpathinfo1(cli, fname, &c_time, &a_time, &m_time, &size,
4519 if (!NT_STATUS_IS_OK(status)) {
4520 printf("ERROR: qpathinfo failed (%s)\n", nt_errstr(status));
4523 time_t t = time(NULL);
4525 if (c_time != m_time) {
4526 printf("create time=%s", ctime(&c_time));
4527 printf("modify time=%s", ctime(&m_time));
4528 printf("This system appears to have sticky create times\n");
4530 if ((labs(a_time - t) > 60) && (a_time % (60*60) == 0)) {
4531 printf("access time=%s", ctime(&a_time));
4532 printf("This system appears to set a midnight access time\n");
4536 if (labs(m_time - t) > 60*60*24*7) {
4537 printf("ERROR: totally incorrect times - maybe word reversed? mtime=%s", ctime(&m_time));
4543 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4544 cli_openx(cli, fname,
4545 O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum);
4546 cli_close(cli, fnum);
4547 status = cli_qpathinfo2(cli,
4557 if (!NT_STATUS_IS_OK(status)) {
4558 printf("ERROR: qpathinfo2 failed (%s)\n", nt_errstr(status));
4561 if (w_time_ts.tv_sec < 60*60*24*2) {
4562 printf("write time=%s", ctime(&w_time_ts.tv_sec));
4563 printf("This system appears to set a initial 0 write time\n");
4566 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
4567 /* SMB2 should always return an inode. */
4569 printf("SMB2 bad inode (0)\n");
4573 /* SMB1 must always return zero here. */
4575 printf("SMB1 bad inode (!0)\n");
4581 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4584 /* check if the server updates the directory modification time
4585 when creating a new file */
4586 status = cli_mkdir(cli, dname);
4587 if (!NT_STATUS_IS_OK(status)) {
4588 printf("ERROR: mkdir failed (%s)\n", nt_errstr(status));
4592 status = cli_qpathinfo2(cli,
4602 if (!NT_STATUS_IS_OK(status)) {
4603 printf("ERROR: qpathinfo2 failed (%s)\n", nt_errstr(status));
4607 cli_openx(cli, fname2,
4608 O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum);
4609 cli_writeall(cli, fnum, 0, (uint8_t *)&fnum, 0, sizeof(fnum), NULL);
4610 cli_close(cli, fnum);
4611 status = cli_qpathinfo2(cli,
4621 if (!NT_STATUS_IS_OK(status)) {
4622 printf("ERROR: qpathinfo2 failed (%s)\n", nt_errstr(status));
4625 if (memcmp(&m_time_ts, &m_time2_ts, sizeof(struct timespec))
4627 printf("This system does not update directory modification times\n");
4631 cli_unlink(cli, fname2, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4632 cli_rmdir(cli, dname);
4634 if (!torture_close_connection(cli)) {
4638 printf("trans2 test finished\n");
4644 This checks new W2K calls.
4647 static NTSTATUS new_trans(struct cli_state *pcli, int fnum, int level)
4649 uint8_t *buf = NULL;
4653 status = cli_qfileinfo(talloc_tos(), pcli, fnum, level, 0,
4654 CLI_BUFFER_SIZE, NULL, &buf, &len);
4655 if (!NT_STATUS_IS_OK(status)) {
4656 printf("ERROR: qfileinfo (%d) failed (%s)\n", level,
4659 printf("qfileinfo: level %d, len = %u\n", level, len);
4660 dump_data(0, (uint8_t *)buf, len);
4667 static bool run_w2ktest(int dummy)
4669 struct cli_state *cli;
4671 const char *fname = "\\w2ktest\\w2k.tst";
4673 bool correct = True;
4675 printf("starting w2k test\n");
4677 if (!torture_open_connection(&cli, 0)) {
4681 cli_openx(cli, fname,
4682 O_RDWR | O_CREAT , DENY_NONE, &fnum);
4684 for (level = 1004; level < 1040; level++) {
4685 new_trans(cli, fnum, level);
4688 cli_close(cli, fnum);
4690 if (!torture_close_connection(cli)) {
4694 printf("w2k test finished\n");
4701 this is a harness for some oplock tests
4703 static bool run_oplock1(int dummy)
4705 struct cli_state *cli1;
4706 const char *fname = "\\lockt1.lck";
4708 bool correct = True;
4711 printf("starting oplock test 1\n");
4713 if (!torture_open_connection(&cli1, 0)) {
4717 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4719 smbXcli_conn_set_sockopt(cli1->conn, sockops);
4721 cli1->use_oplocks = True;
4723 status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
4725 if (!NT_STATUS_IS_OK(status)) {
4726 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
4730 cli1->use_oplocks = False;
4732 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4733 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4735 status = cli_close(cli1, fnum1);
4736 if (!NT_STATUS_IS_OK(status)) {
4737 printf("close2 failed (%s)\n", nt_errstr(status));
4741 status = cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4742 if (!NT_STATUS_IS_OK(status)) {
4743 printf("unlink failed (%s)\n", nt_errstr(status));
4747 if (!torture_close_connection(cli1)) {
4751 printf("finished oplock test 1\n");
4756 static bool run_oplock2(int dummy)
4758 struct cli_state *cli1, *cli2;
4759 const char *fname = "\\lockt2.lck";
4760 uint16_t fnum1, fnum2;
4761 int saved_use_oplocks = use_oplocks;
4763 bool correct = True;
4764 volatile bool *shared_correct;
4768 shared_correct = (volatile bool *)anonymous_shared_allocate(sizeof(bool));
4769 *shared_correct = True;
4771 use_level_II_oplocks = True;
4774 printf("starting oplock test 2\n");
4776 if (!torture_open_connection(&cli1, 0)) {
4777 use_level_II_oplocks = False;
4778 use_oplocks = saved_use_oplocks;
4782 if (!torture_open_connection(&cli2, 1)) {
4783 use_level_II_oplocks = False;
4784 use_oplocks = saved_use_oplocks;
4788 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4790 smbXcli_conn_set_sockopt(cli1->conn, sockops);
4791 smbXcli_conn_set_sockopt(cli2->conn, sockops);
4793 status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
4795 if (!NT_STATUS_IS_OK(status)) {
4796 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
4800 /* Don't need the globals any more. */
4801 use_level_II_oplocks = False;
4802 use_oplocks = saved_use_oplocks;
4806 status = cli_openx(cli2, fname, O_RDWR, DENY_NONE, &fnum2);
4807 if (!NT_STATUS_IS_OK(status)) {
4808 printf("second open of %s failed (%s)\n", fname, nt_errstr(status));
4809 *shared_correct = False;
4815 status = cli_close(cli2, fnum2);
4816 if (!NT_STATUS_IS_OK(status)) {
4817 printf("close2 failed (%s)\n", nt_errstr(status));
4818 *shared_correct = False;
4826 /* Ensure cli1 processes the break. Empty file should always return 0
4828 status = cli_read(cli1, fnum1, buf, 0, 4, &nread);
4829 if (!NT_STATUS_IS_OK(status)) {
4830 printf("read on fnum1 failed (%s)\n", nt_errstr(status));
4832 } else if (nread != 0) {
4833 printf("read on empty fnum1 failed. recv %ld expected %d\n",
4834 (unsigned long)nread, 0);
4838 /* Should now be at level II. */
4839 /* Test if sending a write locks causes a break to none. */
4840 status = cli_lock32(cli1, fnum1, 0, 4, 0, READ_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 status = cli_lock32(cli1, fnum1, 0, 4, 0, WRITE_LOCK);
4851 if (!NT_STATUS_IS_OK(status)) {
4852 printf("lock failed (%s)\n", nt_errstr(status));
4856 cli_unlock(cli1, fnum1, 0, 4);
4860 cli_read(cli1, fnum1, buf, 0, 4, NULL);
4862 status = cli_close(cli1, fnum1);
4863 if (!NT_STATUS_IS_OK(status)) {
4864 printf("close1 failed (%s)\n", nt_errstr(status));
4870 status = cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4871 if (!NT_STATUS_IS_OK(status)) {
4872 printf("unlink failed (%s)\n", nt_errstr(status));
4876 if (!torture_close_connection(cli1)) {
4880 if (!*shared_correct) {
4884 printf("finished oplock test 2\n");
4889 struct oplock4_state {
4890 struct tevent_context *ev;
4891 struct cli_state *cli;
4896 static void oplock4_got_break(struct tevent_req *req);
4897 static void oplock4_got_open(struct tevent_req *req);
4899 static bool run_oplock4(int dummy)
4901 struct tevent_context *ev;
4902 struct cli_state *cli1, *cli2;
4903 struct tevent_req *oplock_req, *open_req;
4904 const char *fname = "\\lockt4.lck";
4905 const char *fname_ln = "\\lockt4_ln.lck";
4906 uint16_t fnum1, fnum2;
4907 int saved_use_oplocks = use_oplocks;
4909 bool correct = true;
4913 struct oplock4_state *state;
4915 printf("starting oplock test 4\n");
4917 if (!torture_open_connection(&cli1, 0)) {
4918 use_level_II_oplocks = false;
4919 use_oplocks = saved_use_oplocks;
4923 if (!torture_open_connection(&cli2, 1)) {
4924 use_level_II_oplocks = false;
4925 use_oplocks = saved_use_oplocks;
4929 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4930 cli_unlink(cli1, fname_ln, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4932 smbXcli_conn_set_sockopt(cli1->conn, sockops);
4933 smbXcli_conn_set_sockopt(cli2->conn, sockops);
4935 /* Create the file. */
4936 status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
4938 if (!NT_STATUS_IS_OK(status)) {
4939 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
4943 status = cli_close(cli1, fnum1);
4944 if (!NT_STATUS_IS_OK(status)) {
4945 printf("close1 failed (%s)\n", nt_errstr(status));
4949 /* Now create a hardlink. */
4950 status = cli_hardlink(cli1, fname, fname_ln);
4951 if (!NT_STATUS_IS_OK(status)) {
4952 printf("nt hardlink failed (%s)\n", nt_errstr(status));
4956 /* Prove that opening hardlinks cause deny modes to conflict. */
4957 status = cli_openx(cli1, fname, O_RDWR, DENY_ALL, &fnum1);
4958 if (!NT_STATUS_IS_OK(status)) {
4959 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
4963 status = cli_openx(cli1, fname_ln, O_RDWR, DENY_NONE, &fnum2);
4964 if (NT_STATUS_IS_OK(status)) {
4965 printf("open of %s succeeded - should fail with sharing violation.\n",
4970 if (!NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
4971 printf("open of %s should fail with sharing violation. Got %s\n",
4972 fname_ln, nt_errstr(status));
4976 status = cli_close(cli1, fnum1);
4977 if (!NT_STATUS_IS_OK(status)) {
4978 printf("close1 failed (%s)\n", nt_errstr(status));
4982 cli1->use_oplocks = true;
4983 cli2->use_oplocks = true;
4985 status = cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
4986 if (!NT_STATUS_IS_OK(status)) {
4987 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
4991 ev = samba_tevent_context_init(talloc_tos());
4993 printf("tevent_context_init failed\n");
4997 state = talloc(ev, struct oplock4_state);
4998 if (state == NULL) {
4999 printf("talloc failed\n");
5004 state->got_break = &got_break;
5005 state->fnum2 = &fnum2;
5007 oplock_req = cli_smb_oplock_break_waiter_send(
5008 talloc_tos(), ev, cli1);
5009 if (oplock_req == NULL) {
5010 printf("cli_smb_oplock_break_waiter_send failed\n");
5013 tevent_req_set_callback(oplock_req, oplock4_got_break, state);
5015 open_req = cli_openx_send(
5016 talloc_tos(), ev, cli2, fname_ln, O_RDWR, DENY_NONE);
5017 if (open_req == NULL) {
5018 printf("cli_openx_send failed\n");
5021 tevent_req_set_callback(open_req, oplock4_got_open, state);
5026 while (!got_break || fnum2 == 0xffff) {
5028 ret = tevent_loop_once(ev);
5030 printf("tevent_loop_once failed: %s\n",
5036 status = cli_close(cli2, fnum2);
5037 if (!NT_STATUS_IS_OK(status)) {
5038 printf("close2 failed (%s)\n", nt_errstr(status));
5042 status = cli_close(cli1, fnum1);
5043 if (!NT_STATUS_IS_OK(status)) {
5044 printf("close1 failed (%s)\n", nt_errstr(status));
5048 status = cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5049 if (!NT_STATUS_IS_OK(status)) {
5050 printf("unlink failed (%s)\n", nt_errstr(status));
5054 status = cli_unlink(cli1, fname_ln, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5055 if (!NT_STATUS_IS_OK(status)) {
5056 printf("unlink failed (%s)\n", nt_errstr(status));
5060 if (!torture_close_connection(cli1)) {
5068 printf("finished oplock test 4\n");
5073 static void oplock4_got_break(struct tevent_req *req)
5075 struct oplock4_state *state = tevent_req_callback_data(
5076 req, struct oplock4_state);
5081 status = cli_smb_oplock_break_waiter_recv(req, &fnum, &level);
5083 if (!NT_STATUS_IS_OK(status)) {
5084 printf("cli_smb_oplock_break_waiter_recv returned %s\n",
5088 *state->got_break = true;
5090 req = cli_oplock_ack_send(state, state->ev, state->cli, fnum,
5093 printf("cli_oplock_ack_send failed\n");
5098 static void oplock4_got_open(struct tevent_req *req)
5100 struct oplock4_state *state = tevent_req_callback_data(
5101 req, struct oplock4_state);
5104 status = cli_openx_recv(req, state->fnum2);
5105 if (!NT_STATUS_IS_OK(status)) {
5106 printf("cli_openx_recv returned %s\n", nt_errstr(status));
5107 *state->fnum2 = 0xffff;
5111 #ifdef HAVE_KERNEL_OPLOCKS_LINUX
5113 struct oplock5_state {
5118 * Async open the file that has a kernel oplock, do an echo to get
5119 * that 100% across, close the file to signal to the child fd that the
5120 * oplock can be dropped, wait for the open reply.
5123 static void oplock5_opened(struct tevent_req *subreq);
5124 static void oplock5_pong(struct tevent_req *subreq);
5125 static void oplock5_timedout(struct tevent_req *subreq);
5127 static struct tevent_req *oplock5_send(
5128 TALLOC_CTX *mem_ctx,
5129 struct tevent_context *ev,
5130 struct cli_state *cli,
5134 struct tevent_req *req = NULL, *subreq = NULL;
5135 struct oplock5_state *state = NULL;
5136 static uint8_t data = 0;
5138 req = tevent_req_create(mem_ctx, &state, struct oplock5_state);
5142 state->pipe_down_fd = pipe_down_fd;
5144 subreq = cli_ntcreate_send(
5150 SEC_FILE_READ_DATA, /* DesiredAccess */
5151 FILE_ATTRIBUTE_NORMAL, /* FileAttributes */
5152 FILE_SHARE_WRITE|FILE_SHARE_READ, /* ShareAccess */
5153 FILE_OPEN, /* CreateDisposition */
5154 FILE_NON_DIRECTORY_FILE, /* CreateOptions */
5155 0, /* Impersonation */
5156 0); /* SecurityFlags */
5157 if (tevent_req_nomem(subreq, req)) {
5158 return tevent_req_post(req, ev);
5160 tevent_req_set_callback(subreq, oplock5_opened, req);
5162 subreq = cli_echo_send(
5167 (DATA_BLOB) { .data = &data, .length = sizeof(data) });
5168 if (tevent_req_nomem(subreq, req)) {
5169 return tevent_req_post(req, ev);
5171 tevent_req_set_callback(subreq, oplock5_pong, req);
5173 subreq = tevent_wakeup_send(state, ev, timeval_current_ofs(20, 0));
5174 if (tevent_req_nomem(subreq, req)) {
5175 return tevent_req_post(req, ev);
5177 tevent_req_set_callback(subreq, oplock5_timedout, req);
5182 static void oplock5_opened(struct tevent_req *subreq)
5184 struct tevent_req *req = tevent_req_callback_data(
5185 subreq, struct tevent_req);
5189 status = cli_ntcreate_recv(subreq, &fnum, NULL);
5190 TALLOC_FREE(subreq);
5191 if (tevent_req_nterror(req, status)) {
5194 tevent_req_done(req);
5197 static void oplock5_pong(struct tevent_req *subreq)
5199 struct tevent_req *req = tevent_req_callback_data(
5200 subreq, struct tevent_req);
5201 struct oplock5_state *state = tevent_req_data(
5202 req, struct oplock5_state);
5205 status = cli_echo_recv(subreq);
5206 TALLOC_FREE(subreq);
5207 if (tevent_req_nterror(req, status)) {
5211 close(state->pipe_down_fd);
5214 static void oplock5_timedout(struct tevent_req *subreq)
5216 struct tevent_req *req = tevent_req_callback_data(
5217 subreq, struct tevent_req);
5220 ok = tevent_wakeup_recv(subreq);
5221 TALLOC_FREE(subreq);
5223 tevent_req_oom(req);
5226 tevent_req_nterror(req, NT_STATUS_TIMEOUT);
5229 static NTSTATUS oplock5_recv(struct tevent_req *req)
5231 return tevent_req_simple_recv_ntstatus(req);
5234 static bool run_oplock5(int dummy)
5236 struct tevent_context *ev = NULL;
5237 struct tevent_req *req = NULL;
5238 struct cli_state *cli = NULL;
5239 const char *fname = "oplock5.txt";
5240 int pipe_down[2], pipe_up[2];
5247 printf("starting oplock5\n");
5249 if (local_path == NULL) {
5250 d_fprintf(stderr, "oplock5 must be given a local path via "
5251 "-l <localpath>\n");
5255 ret = pipe(pipe_down);
5257 d_fprintf(stderr, "pipe() failed: %s\n", strerror(errno));
5260 ret = pipe(pipe_up);
5262 d_fprintf(stderr, "pipe() failed: %s\n", strerror(errno));
5267 if (child_pid == -1) {
5268 d_fprintf(stderr, "fork() failed: %s\n", strerror(errno));
5272 if (child_pid == 0) {
5273 char *local_file = NULL;
5276 close(pipe_down[1]);
5279 local_file = talloc_asprintf(
5280 talloc_tos(), "%s/%s", local_path, fname);
5281 if (local_file == 0) {
5285 fd = open(local_file, O_RDWR|O_CREAT, 0644);
5288 "open(%s) in child failed: %s\n",
5295 signal(SIGIO, SIG_IGN);
5297 ret = fcntl(fd, F_SETLEASE, F_WRLCK);
5300 "SETLEASE in child failed: %s\n",
5307 ret = sys_write(pipe_up[1], &c, sizeof(c));
5310 "sys_write failed: %s\n",
5314 ret = sys_read(pipe_down[0], &c, sizeof(c));
5317 "sys_read failed: %s\n",
5325 close(pipe_down[0]);
5327 ret = sys_read(pipe_up[0], &c, sizeof(c));
5330 "sys_read failed: %s\n",
5335 d_fprintf(stderr, "got error code %"PRIu8"\n", c);
5339 ok = torture_open_connection(&cli, 0);
5341 d_fprintf(stderr, "torture_open_connection failed\n");
5345 ev = samba_tevent_context_init(talloc_tos());
5347 d_fprintf(stderr, "samba_tevent_context_init failed\n");
5351 req = oplock5_send(ev, ev, cli, fname, pipe_down[1]);
5353 d_fprintf(stderr, "oplock5_send failed\n");
5357 ok = tevent_req_poll_ntstatus(req, ev, &status);
5360 "tevent_req_poll_ntstatus failed: %s\n",
5365 status = oplock5_recv(req);
5367 if (!NT_STATUS_IS_OK(status)) {
5369 "oplock5 failed: %s\n",
5377 #endif /* HAVE_KERNEL_OPLOCKS_LINUX */
5380 Test delete on close semantics.
5382 static bool run_deletetest(int dummy)
5384 struct cli_state *cli1 = NULL;
5385 struct cli_state *cli2 = NULL;
5386 const char *fname = "\\delete.file";
5387 uint16_t fnum1 = (uint16_t)-1;
5388 uint16_t fnum2 = (uint16_t)-1;
5389 bool correct = false;
5392 printf("starting delete test\n");
5394 if (!torture_open_connection(&cli1, 0)) {
5398 smbXcli_conn_set_sockopt(cli1->conn, sockops);
5400 /* Test 1 - this should delete the file on close. */
5402 cli_setatr(cli1, fname, 0, 0);
5403 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5405 status = cli_ntcreate(cli1, fname, 0, GENERIC_ALL_ACCESS|DELETE_ACCESS,
5406 FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
5407 FILE_DELETE_ON_CLOSE, 0, &fnum1, NULL);
5408 if (!NT_STATUS_IS_OK(status)) {
5409 printf("[1] open of %s failed (%s)\n", fname, nt_errstr(status));
5413 status = cli_close(cli1, fnum1);
5414 if (!NT_STATUS_IS_OK(status)) {
5415 printf("[1] close failed (%s)\n", nt_errstr(status));
5419 status = cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
5420 if (NT_STATUS_IS_OK(status)) {
5421 printf("[1] open of %s succeeded (should fail)\n", fname);
5425 printf("first delete on close test succeeded.\n");
5427 /* Test 2 - this should delete the file on close. */
5429 cli_setatr(cli1, fname, 0, 0);
5430 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5432 status = cli_ntcreate(cli1, fname, 0, GENERIC_ALL_ACCESS,
5433 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
5434 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
5435 if (!NT_STATUS_IS_OK(status)) {
5436 printf("[2] open of %s failed (%s)\n", fname, nt_errstr(status));
5440 status = cli_nt_delete_on_close(cli1, fnum1, true);
5441 if (!NT_STATUS_IS_OK(status)) {
5442 printf("[2] setting delete_on_close failed (%s)\n", nt_errstr(status));
5446 status = cli_close(cli1, fnum1);
5447 if (!NT_STATUS_IS_OK(status)) {
5448 printf("[2] close failed (%s)\n", nt_errstr(status));
5452 status = cli_openx(cli1, fname, O_RDONLY, DENY_NONE, &fnum1);
5453 if (NT_STATUS_IS_OK(status)) {
5454 printf("[2] open of %s succeeded should have been deleted on close !\n", fname);
5455 status = cli_close(cli1, fnum1);
5456 if (!NT_STATUS_IS_OK(status)) {
5457 printf("[2] close failed (%s)\n", nt_errstr(status));
5459 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5463 printf("second delete on close test succeeded.\n");
5466 cli_setatr(cli1, fname, 0, 0);
5467 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5469 status = cli_ntcreate(cli1, fname, 0, GENERIC_ALL_ACCESS,
5470 FILE_ATTRIBUTE_NORMAL,
5471 FILE_SHARE_READ|FILE_SHARE_WRITE,
5472 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
5473 if (!NT_STATUS_IS_OK(status)) {
5474 printf("[3] open - 1 of %s failed (%s)\n", fname, nt_errstr(status));
5478 /* This should fail with a sharing violation - open for delete is only compatible
5479 with SHARE_DELETE. */
5481 status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
5482 FILE_ATTRIBUTE_NORMAL,
5483 FILE_SHARE_READ|FILE_SHARE_WRITE,
5484 FILE_OPEN, 0, 0, &fnum2, NULL);
5485 if (NT_STATUS_IS_OK(status)) {
5486 printf("[3] open - 2 of %s succeeded - should have failed.\n", fname);
5490 /* This should succeed. */
5491 status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
5492 FILE_ATTRIBUTE_NORMAL,
5493 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5494 FILE_OPEN, 0, 0, &fnum2, NULL);
5495 if (!NT_STATUS_IS_OK(status)) {
5496 printf("[3] open - 3 of %s failed (%s)\n", fname, nt_errstr(status));
5500 status = cli_nt_delete_on_close(cli1, fnum1, true);
5501 if (!NT_STATUS_IS_OK(status)) {
5502 printf("[3] setting delete_on_close failed (%s)\n", nt_errstr(status));
5506 status = cli_close(cli1, fnum1);
5507 if (!NT_STATUS_IS_OK(status)) {
5508 printf("[3] close 1 failed (%s)\n", nt_errstr(status));
5512 status = cli_close(cli1, fnum2);
5513 if (!NT_STATUS_IS_OK(status)) {
5514 printf("[3] close 2 failed (%s)\n", nt_errstr(status));
5518 /* This should fail - file should no longer be there. */
5520 status = cli_openx(cli1, fname, O_RDONLY, DENY_NONE, &fnum1);
5521 if (NT_STATUS_IS_OK(status)) {
5522 printf("[3] open of %s succeeded should have been deleted on close !\n", fname);
5523 status = cli_close(cli1, fnum1);
5524 if (!NT_STATUS_IS_OK(status)) {
5525 printf("[3] close failed (%s)\n", nt_errstr(status));
5527 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5531 printf("third delete on close test succeeded.\n");
5534 cli_setatr(cli1, fname, 0, 0);
5535 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5537 status = cli_ntcreate(cli1, fname, 0,
5538 FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
5539 FILE_ATTRIBUTE_NORMAL,
5540 FILE_SHARE_READ|FILE_SHARE_WRITE,
5541 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
5542 if (!NT_STATUS_IS_OK(status)) {
5543 printf("[4] open of %s failed (%s)\n", fname, nt_errstr(status));
5547 /* This should succeed. */
5548 status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
5549 FILE_ATTRIBUTE_NORMAL,
5550 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5551 FILE_OPEN, 0, 0, &fnum2, NULL);
5552 if (!NT_STATUS_IS_OK(status)) {
5553 printf("[4] open - 2 of %s failed (%s)\n", fname, nt_errstr(status));
5557 status = cli_close(cli1, fnum2);
5558 if (!NT_STATUS_IS_OK(status)) {
5559 printf("[4] close - 1 failed (%s)\n", nt_errstr(status));
5563 status = cli_nt_delete_on_close(cli1, fnum1, true);
5564 if (!NT_STATUS_IS_OK(status)) {
5565 printf("[4] setting delete_on_close failed (%s)\n", nt_errstr(status));
5569 /* This should fail - no more opens once delete on close set. */
5570 status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
5571 FILE_ATTRIBUTE_NORMAL,
5572 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5573 FILE_OPEN, 0, 0, &fnum2, NULL);
5574 if (NT_STATUS_IS_OK(status)) {
5575 printf("[4] open - 3 of %s succeeded ! Should have failed.\n", fname );
5579 status = cli_close(cli1, fnum1);
5580 if (!NT_STATUS_IS_OK(status)) {
5581 printf("[4] close - 2 failed (%s)\n", nt_errstr(status));
5585 printf("fourth delete on close test succeeded.\n");
5588 cli_setatr(cli1, fname, 0, 0);
5589 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5591 status = cli_openx(cli1, fname, O_RDWR|O_CREAT, DENY_NONE, &fnum1);
5592 if (!NT_STATUS_IS_OK(status)) {
5593 printf("[5] open of %s failed (%s)\n", fname, nt_errstr(status));
5597 /* This should fail - only allowed on NT opens with DELETE access. */
5599 status = cli_nt_delete_on_close(cli1, fnum1, true);
5600 if (NT_STATUS_IS_OK(status)) {
5601 printf("[5] setting delete_on_close on OpenX file succeeded - should fail !\n");
5605 status = cli_close(cli1, fnum1);
5606 if (!NT_STATUS_IS_OK(status)) {
5607 printf("[5] close failed (%s)\n", nt_errstr(status));
5611 printf("fifth delete on close test succeeded.\n");
5614 cli_setatr(cli1, fname, 0, 0);
5615 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5617 status = cli_ntcreate(cli1, fname, 0, FILE_READ_DATA|FILE_WRITE_DATA,
5618 FILE_ATTRIBUTE_NORMAL,
5619 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5620 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
5621 if (!NT_STATUS_IS_OK(status)) {
5622 printf("[6] open of %s failed (%s)\n", fname,
5627 /* This should fail - only allowed on NT opens with DELETE access. */
5629 status = cli_nt_delete_on_close(cli1, fnum1, true);
5630 if (NT_STATUS_IS_OK(status)) {
5631 printf("[6] setting delete_on_close on file with no delete access succeeded - should fail !\n");
5635 status = cli_close(cli1, fnum1);
5636 if (!NT_STATUS_IS_OK(status)) {
5637 printf("[6] close failed (%s)\n", nt_errstr(status));
5641 printf("sixth delete on close test succeeded.\n");
5644 cli_setatr(cli1, fname, 0, 0);
5645 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5647 status = cli_ntcreate(cli1, fname, 0,
5648 FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
5649 FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
5650 0, 0, &fnum1, NULL);
5651 if (!NT_STATUS_IS_OK(status)) {
5652 printf("[7] open of %s failed (%s)\n", fname, nt_errstr(status));
5656 status = cli_nt_delete_on_close(cli1, fnum1, true);
5657 if (!NT_STATUS_IS_OK(status)) {
5658 printf("[7] setting delete_on_close on file failed !\n");
5662 status = cli_nt_delete_on_close(cli1, fnum1, false);
5663 if (!NT_STATUS_IS_OK(status)) {
5664 printf("[7] unsetting delete_on_close on file failed !\n");
5668 status = cli_close(cli1, fnum1);
5669 if (!NT_STATUS_IS_OK(status)) {
5670 printf("[7] close - 1 failed (%s)\n", nt_errstr(status));
5674 /* This next open should succeed - we reset the flag. */
5675 status = cli_openx(cli1, fname, O_RDONLY, DENY_NONE, &fnum1);
5676 if (!NT_STATUS_IS_OK(status)) {
5677 printf("[7] open of %s failed (%s)\n", fname, nt_errstr(status));
5681 status = cli_close(cli1, fnum1);
5682 if (!NT_STATUS_IS_OK(status)) {
5683 printf("[7] close - 2 failed (%s)\n", nt_errstr(status));
5687 printf("seventh delete on close test succeeded.\n");
5690 cli_setatr(cli1, fname, 0, 0);
5691 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5693 if (!torture_open_connection(&cli2, 1)) {
5694 printf("[8] failed to open second connection.\n");
5698 smbXcli_conn_set_sockopt(cli1->conn, sockops);
5700 status = cli_ntcreate(cli1, 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_OVERWRITE_IF, 0, 0, &fnum1, NULL);
5705 if (!NT_STATUS_IS_OK(status)) {
5706 printf("[8] open 1 of %s failed (%s)\n", fname, nt_errstr(status));
5710 status = cli_ntcreate(cli2, fname, 0,
5711 FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
5712 FILE_ATTRIBUTE_NORMAL,
5713 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5714 FILE_OPEN, 0, 0, &fnum2, NULL);
5715 if (!NT_STATUS_IS_OK(status)) {
5716 printf("[8] open 2 of %s failed (%s)\n", fname, nt_errstr(status));
5720 status = cli_nt_delete_on_close(cli1, fnum1, true);
5721 if (!NT_STATUS_IS_OK(status)) {
5722 printf("[8] setting delete_on_close on file failed !\n");
5726 status = cli_close(cli1, fnum1);
5727 if (!NT_STATUS_IS_OK(status)) {
5728 printf("[8] close - 1 failed (%s)\n", nt_errstr(status));
5732 status = cli_close(cli2, fnum2);
5733 if (!NT_STATUS_IS_OK(status)) {
5734 printf("[8] close - 2 failed (%s)\n", nt_errstr(status));
5738 /* This should fail.. */
5739 status = cli_openx(cli1, fname, O_RDONLY, DENY_NONE, &fnum1);
5740 if (NT_STATUS_IS_OK(status)) {
5741 printf("[8] open of %s succeeded should have been deleted on close !\n", fname);
5745 printf("eighth delete on close test succeeded.\n");
5749 /* This should fail - we need to set DELETE_ACCESS. */
5750 status = cli_ntcreate(cli1, fname, 0, FILE_READ_DATA|FILE_WRITE_DATA,
5751 FILE_ATTRIBUTE_NORMAL,
5754 FILE_DELETE_ON_CLOSE, 0, &fnum1, NULL);
5755 if (NT_STATUS_IS_OK(status)) {
5756 printf("[9] open of %s succeeded should have failed!\n", fname);
5760 printf("ninth delete on close test succeeded.\n");
5764 status = cli_ntcreate(cli1, fname, 0,
5765 FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
5766 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
5767 FILE_OVERWRITE_IF, FILE_DELETE_ON_CLOSE,
5769 if (!NT_STATUS_IS_OK(status)) {
5770 printf("[10] open of %s failed (%s)\n", fname, nt_errstr(status));
5774 /* This should delete the file. */
5775 status = cli_close(cli1, fnum1);
5776 if (!NT_STATUS_IS_OK(status)) {
5777 printf("[10] close failed (%s)\n", nt_errstr(status));
5781 /* This should fail.. */
5782 status = cli_openx(cli1, fname, O_RDONLY, DENY_NONE, &fnum1);
5783 if (NT_STATUS_IS_OK(status)) {
5784 printf("[10] open of %s succeeded should have been deleted on close !\n", fname);
5788 printf("tenth delete on close test succeeded.\n");
5792 cli_setatr(cli1, fname, 0, 0);
5793 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5795 /* Can we open a read-only file with delete access? */
5797 /* Create a readonly file. */
5798 status = cli_ntcreate(cli1, fname, 0, FILE_READ_DATA|FILE_WRITE_DATA,
5799 FILE_ATTRIBUTE_READONLY, FILE_SHARE_NONE,
5800 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
5801 if (!NT_STATUS_IS_OK(status)) {
5802 printf("[11] open of %s failed (%s)\n", fname, nt_errstr(status));
5806 status = cli_close(cli1, fnum1);
5807 if (!NT_STATUS_IS_OK(status)) {
5808 printf("[11] close failed (%s)\n", nt_errstr(status));
5812 /* Now try open for delete access. */
5813 status = cli_ntcreate(cli1, fname, 0,
5814 FILE_READ_ATTRIBUTES|DELETE_ACCESS,
5816 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5817 FILE_OPEN, 0, 0, &fnum1, NULL);
5818 if (!NT_STATUS_IS_OK(status)) {
5819 printf("[11] open of %s failed: %s\n", fname, nt_errstr(status));
5823 cli_close(cli1, fnum1);
5825 printf("eleventh delete on close test succeeded.\n");
5829 * like test 4 but with initial delete on close
5832 cli_setatr(cli1, fname, 0, 0);
5833 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5835 status = cli_ntcreate(cli1, fname, 0,
5836 FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
5837 FILE_ATTRIBUTE_NORMAL,
5838 FILE_SHARE_READ|FILE_SHARE_WRITE,
5840 FILE_DELETE_ON_CLOSE, 0, &fnum1, NULL);
5841 if (!NT_STATUS_IS_OK(status)) {
5842 printf("[12] open 1 of %s failed (%s)\n", fname, nt_errstr(status));
5846 status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
5847 FILE_ATTRIBUTE_NORMAL,
5848 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5849 FILE_OPEN, 0, 0, &fnum2, NULL);
5850 if (!NT_STATUS_IS_OK(status)) {
5851 printf("[12] open 2 of %s failed(%s).\n", fname, nt_errstr(status));
5855 status = cli_close(cli1, fnum2);
5856 if (!NT_STATUS_IS_OK(status)) {
5857 printf("[12] close 1 failed (%s)\n", nt_errstr(status));
5861 status = cli_nt_delete_on_close(cli1, fnum1, true);
5862 if (!NT_STATUS_IS_OK(status)) {
5863 printf("[12] setting delete_on_close failed (%s)\n", nt_errstr(status));
5867 /* This should fail - no more opens once delete on close set. */
5868 status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
5869 FILE_ATTRIBUTE_NORMAL,
5870 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5871 FILE_OPEN, 0, 0, &fnum2, NULL);
5872 if (NT_STATUS_IS_OK(status)) {
5873 printf("[12] open 3 of %s succeeded - should fail).\n", fname);
5877 status = cli_nt_delete_on_close(cli1, fnum1, false);
5878 if (!NT_STATUS_IS_OK(status)) {
5879 printf("[12] unsetting delete_on_close failed (%s)\n", nt_errstr(status));
5883 status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
5884 FILE_ATTRIBUTE_NORMAL,
5885 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5886 FILE_OPEN, 0, 0, &fnum2, NULL);
5887 if (!NT_STATUS_IS_OK(status)) {
5888 printf("[12] open 4 of %s failed (%s)\n", fname, nt_errstr(status));
5892 status = cli_close(cli1, fnum2);
5893 if (!NT_STATUS_IS_OK(status)) {
5894 printf("[12] close 2 failed (%s)\n", nt_errstr(status));
5898 status = cli_close(cli1, fnum1);
5899 if (!NT_STATUS_IS_OK(status)) {
5900 printf("[12] close 3 failed (%s)\n", nt_errstr(status));
5905 * setting delete on close on the handle does
5906 * not unset the initial delete on close...
5908 status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
5909 FILE_ATTRIBUTE_NORMAL,
5910 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5911 FILE_OPEN, 0, 0, &fnum2, NULL);
5912 if (NT_STATUS_IS_OK(status)) {
5913 printf("[12] open 5 of %s succeeded - should fail).\n", fname);
5915 } else if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
5916 printf("ntcreate returned %s, expected "
5917 "NT_STATUS_OBJECT_NAME_NOT_FOUND\n",
5922 printf("twelfth delete on close test succeeded.\n");
5925 printf("finished delete test\n");
5930 /* FIXME: This will crash if we aborted before cli2 got
5931 * initialized, because these functions don't handle
5932 * uninitialized connections. */
5934 if (fnum1 != (uint16_t)-1) cli_close(cli1, fnum1);
5935 if (fnum2 != (uint16_t)-1) cli_close(cli1, fnum2);
5936 cli_setatr(cli1, fname, 0, 0);
5937 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5939 if (cli1 && !torture_close_connection(cli1)) {
5942 if (cli2 && !torture_close_connection(cli2)) {
5948 struct delete_stream_state {
5952 static void delete_stream_unlinked(struct tevent_req *subreq);
5953 static void delete_stream_closed(struct tevent_req *subreq);
5955 static struct tevent_req *delete_stream_send(
5956 TALLOC_CTX *mem_ctx,
5957 struct tevent_context *ev,
5958 struct cli_state *cli,
5959 const char *base_fname,
5960 uint16_t stream_fnum)
5962 struct tevent_req *req = NULL, *subreq = NULL;
5963 struct delete_stream_state *state = NULL;
5965 req = tevent_req_create(
5966 mem_ctx, &state, struct delete_stream_state);
5971 subreq = cli_unlink_send(
5976 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5977 if (tevent_req_nomem(subreq, req)) {
5978 return tevent_req_post(req, ev);
5980 tevent_req_set_callback(subreq, delete_stream_unlinked, req);
5982 subreq = cli_close_send(state, ev, cli, stream_fnum, 0);
5983 if (tevent_req_nomem(subreq, req)) {
5984 return tevent_req_post(req, ev);
5986 tevent_req_set_callback(subreq, delete_stream_closed, req);
5991 static void delete_stream_unlinked(struct tevent_req *subreq)
5993 struct tevent_req *req = tevent_req_callback_data(
5994 subreq, struct tevent_req);
5995 struct delete_stream_state *state = tevent_req_data(
5996 req, struct delete_stream_state);
5999 status = cli_unlink_recv(subreq);
6000 TALLOC_FREE(subreq);
6001 if (!NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
6002 printf("cli_unlink returned %s\n",
6004 tevent_req_nterror(req, NT_STATUS_UNSUCCESSFUL);
6007 if (!state->closed) {
6008 /* close reply should have come in first */
6009 printf("Not closed\n");
6010 tevent_req_nterror(req, NT_STATUS_UNSUCCESSFUL);
6013 tevent_req_done(req);
6016 static void delete_stream_closed(struct tevent_req *subreq)
6018 struct tevent_req *req = tevent_req_callback_data(
6019 subreq, struct tevent_req);
6020 struct delete_stream_state *state = tevent_req_data(
6021 req, struct delete_stream_state);
6024 status = cli_close_recv(subreq);
6025 TALLOC_FREE(subreq);
6026 if (tevent_req_nterror(req, status)) {
6029 /* also waiting for the unlink to come back */
6030 state->closed = true;
6033 static NTSTATUS delete_stream_recv(struct tevent_req *req)
6035 return tevent_req_simple_recv_ntstatus(req);
6038 static bool run_delete_stream(int dummy)
6040 struct tevent_context *ev = NULL;
6041 struct tevent_req *req = NULL;
6042 struct cli_state *cli = NULL;
6043 const char fname[] = "delete_stream";
6044 const char fname_stream[] = "delete_stream:Zone.Identifier:$DATA";
6045 uint16_t fnum1, fnum2;
6049 printf("Starting stream delete test\n");
6051 ok = torture_open_connection(&cli, 0);
6056 cli_setatr(cli, fname, 0, 0);
6057 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6059 /* Create the file. */
6060 status = cli_ntcreate(
6064 READ_CONTROL_ACCESS,
6066 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6072 if (!NT_STATUS_IS_OK(status)) {
6074 "cli_ntcreate of %s failed (%s)\n",
6079 status = cli_close(cli, fnum1);
6080 if (!NT_STATUS_IS_OK(status)) {
6082 "cli_close of %s failed (%s)\n",
6088 /* Now create the stream. */
6089 status = cli_ntcreate(
6095 FILE_SHARE_READ|FILE_SHARE_WRITE,
6102 if (!NT_STATUS_IS_OK(status)) {
6104 "cli_ntcreate of %s failed (%s)\n",
6110 /* open it a second time */
6112 status = cli_ntcreate(
6118 FILE_SHARE_READ|FILE_SHARE_WRITE,
6125 if (!NT_STATUS_IS_OK(status)) {
6127 "2nd cli_ntcreate of %s failed (%s)\n",
6133 ev = samba_tevent_context_init(talloc_tos());
6135 d_fprintf(stderr, "samba_tevent_context_init failed\n");
6139 req = delete_stream_send(ev, ev, cli, fname, fnum1);
6141 d_fprintf(stderr, "delete_stream_send failed\n");
6145 ok = tevent_req_poll_ntstatus(req, ev, &status);
6148 "tevent_req_poll_ntstatus failed: %s\n",
6153 status = delete_stream_recv(req);
6155 if (!NT_STATUS_IS_OK(status)) {
6157 "delete_stream failed: %s\n",
6162 status = cli_close(cli, fnum2);
6163 if (!NT_STATUS_IS_OK(status)) {
6165 "close failed: %s\n",
6170 status = cli_unlink(
6171 cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6172 if (!NT_STATUS_IS_OK(status)) {
6174 "unlink failed: %s\n",
6183 Exercise delete on close semantics - use on the PRINT1 share in torture
6186 static bool run_delete_print_test(int dummy)
6188 struct cli_state *cli1 = NULL;
6189 const char *fname = "print_delete.file";
6190 uint16_t fnum1 = (uint16_t)-1;
6191 bool correct = false;
6192 const char *buf = "print file data\n";
6195 printf("starting print delete test\n");
6197 if (!torture_open_connection(&cli1, 0)) {
6201 smbXcli_conn_set_sockopt(cli1->conn, sockops);
6203 status = cli_ntcreate(cli1, fname, 0, GENERIC_ALL_ACCESS|DELETE_ACCESS,
6204 FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
6205 0, 0, &fnum1, NULL);
6206 if (!NT_STATUS_IS_OK(status)) {
6207 printf("open of %s failed (%s)\n",
6213 status = cli_writeall(cli1,
6216 (const uint8_t *)buf,
6218 strlen(buf), /* size */
6220 if (!NT_STATUS_IS_OK(status)) {
6221 printf("writing print file data failed (%s)\n",
6226 status = cli_nt_delete_on_close(cli1, fnum1, true);
6227 if (!NT_STATUS_IS_OK(status)) {
6228 printf("setting delete_on_close failed (%s)\n",
6233 status = cli_close(cli1, fnum1);
6234 if (!NT_STATUS_IS_OK(status)) {
6235 printf("close failed (%s)\n", nt_errstr(status));
6239 printf("finished print delete test\n");
6245 if (fnum1 != (uint16_t)-1) {
6246 cli_close(cli1, fnum1);
6249 if (cli1 && !torture_close_connection(cli1)) {
6255 static bool run_deletetest_ln(int dummy)
6257 struct cli_state *cli;
6258 const char *fname = "\\delete1";
6259 const char *fname_ln = "\\delete1_ln";
6263 bool correct = true;
6266 printf("starting deletetest-ln\n");
6268 if (!torture_open_connection(&cli, 0)) {
6272 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6273 cli_unlink(cli, fname_ln, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6275 smbXcli_conn_set_sockopt(cli->conn, sockops);
6277 /* Create the file. */
6278 status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
6279 if (!NT_STATUS_IS_OK(status)) {
6280 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
6284 status = cli_close(cli, fnum);
6285 if (!NT_STATUS_IS_OK(status)) {
6286 printf("close1 failed (%s)\n", nt_errstr(status));
6290 /* Now create a hardlink. */
6291 status = cli_hardlink(cli, fname, fname_ln);
6292 if (!NT_STATUS_IS_OK(status)) {
6293 printf("nt hardlink failed (%s)\n", nt_errstr(status));
6297 /* Open the original file. */
6298 status = cli_ntcreate(cli, fname, 0, FILE_READ_DATA,
6299 FILE_ATTRIBUTE_NORMAL,
6300 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6301 FILE_OPEN_IF, 0, 0, &fnum, NULL);
6302 if (!NT_STATUS_IS_OK(status)) {
6303 printf("ntcreate of %s failed (%s)\n", fname, nt_errstr(status));
6307 /* Unlink the hard link path. */
6308 status = cli_ntcreate(cli, fname_ln, 0, DELETE_ACCESS,
6309 FILE_ATTRIBUTE_NORMAL,
6310 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6311 FILE_OPEN_IF, 0, 0, &fnum1, NULL);
6312 if (!NT_STATUS_IS_OK(status)) {
6313 printf("ntcreate of %s failed (%s)\n", fname_ln, nt_errstr(status));
6316 status = cli_nt_delete_on_close(cli, fnum1, true);
6317 if (!NT_STATUS_IS_OK(status)) {
6318 d_printf("(%s) failed to set delete_on_close %s: %s\n",
6319 __location__, fname_ln, nt_errstr(status));
6323 status = cli_close(cli, fnum1);
6324 if (!NT_STATUS_IS_OK(status)) {
6325 printf("close %s failed (%s)\n",
6326 fname_ln, nt_errstr(status));
6330 status = cli_close(cli, fnum);
6331 if (!NT_STATUS_IS_OK(status)) {
6332 printf("close %s failed (%s)\n",
6333 fname, nt_errstr(status));
6337 /* Ensure the original file is still there. */
6338 status = cli_getatr(cli, fname, NULL, NULL, &t);
6339 if (!NT_STATUS_IS_OK(status)) {
6340 printf("%s getatr on file %s failed (%s)\n",
6347 /* Ensure the link path is gone. */
6348 status = cli_getatr(cli, fname_ln, NULL, NULL, &t);
6349 if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
6350 printf("%s, getatr for file %s returned wrong error code %s "
6351 "- should have been deleted\n",
6353 fname_ln, nt_errstr(status));
6357 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6358 cli_unlink(cli, fname_ln, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6360 if (!torture_close_connection(cli)) {
6364 printf("finished deletetest-ln\n");
6370 print out server properties
6372 static bool run_properties(int dummy)
6374 struct cli_state *cli;
6375 bool correct = True;
6377 printf("starting properties test\n");
6381 if (!torture_open_connection(&cli, 0)) {
6385 smbXcli_conn_set_sockopt(cli->conn, sockops);
6387 d_printf("Capabilities 0x%08x\n", smb1cli_conn_capabilities(cli->conn));
6389 if (!torture_close_connection(cli)) {
6398 /* FIRST_DESIRED_ACCESS 0xf019f */
6399 #define FIRST_DESIRED_ACCESS FILE_READ_DATA|FILE_WRITE_DATA|FILE_APPEND_DATA|\
6400 FILE_READ_EA| /* 0xf */ \
6401 FILE_WRITE_EA|FILE_READ_ATTRIBUTES| /* 0x90 */ \
6402 FILE_WRITE_ATTRIBUTES| /* 0x100 */ \
6403 DELETE_ACCESS|READ_CONTROL_ACCESS|\
6404 WRITE_DAC_ACCESS|WRITE_OWNER_ACCESS /* 0xf0000 */
6405 /* SECOND_DESIRED_ACCESS 0xe0080 */
6406 #define SECOND_DESIRED_ACCESS FILE_READ_ATTRIBUTES| /* 0x80 */ \
6407 READ_CONTROL_ACCESS|WRITE_DAC_ACCESS|\
6408 WRITE_OWNER_ACCESS /* 0xe0000 */
6411 #define THIRD_DESIRED_ACCESS FILE_READ_ATTRIBUTES| /* 0x80 */ \
6412 READ_CONTROL_ACCESS|WRITE_DAC_ACCESS|\
6414 WRITE_OWNER_ACCESS /* */
6418 Test ntcreate calls made by xcopy
6420 static bool run_xcopy(int dummy)
6422 static struct cli_state *cli1;
6423 const char *fname = "\\test.txt";
6424 bool correct = True;
6425 uint16_t fnum1, fnum2;
6428 printf("starting xcopy test\n");
6430 if (!torture_open_connection(&cli1, 0)) {
6434 status = cli_ntcreate(cli1, fname, 0, FIRST_DESIRED_ACCESS,
6435 FILE_ATTRIBUTE_ARCHIVE, FILE_SHARE_NONE,
6436 FILE_OVERWRITE_IF, 0x4044, 0, &fnum1, NULL);
6437 if (!NT_STATUS_IS_OK(status)) {
6438 printf("First open failed - %s\n", nt_errstr(status));
6442 status = cli_ntcreate(cli1, fname, 0, SECOND_DESIRED_ACCESS, 0,
6443 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6444 FILE_OPEN, 0x200000, 0, &fnum2, NULL);
6445 if (!NT_STATUS_IS_OK(status)) {
6446 printf("second open failed - %s\n", nt_errstr(status));
6450 if (!torture_close_connection(cli1)) {
6458 Test rename on files open with share delete and no share delete.
6460 static bool run_rename(int dummy)
6462 static struct cli_state *cli1;
6463 const char *fname = "\\test.txt";
6464 const char *fname1 = "\\test1.txt";
6465 bool correct = True;
6470 printf("starting rename test\n");
6472 if (!torture_open_connection(&cli1, 0)) {
6476 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6477 cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6479 status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
6480 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ,
6481 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
6482 if (!NT_STATUS_IS_OK(status)) {
6483 printf("First open failed - %s\n", nt_errstr(status));
6487 status = cli_rename(cli1, fname, fname1, false);
6488 if (!NT_STATUS_IS_OK(status)) {
6489 printf("First rename failed (SHARE_READ) (this is correct) - %s\n", nt_errstr(status));
6491 printf("First rename succeeded (SHARE_READ) - this should have failed !\n");
6495 status = cli_close(cli1, fnum1);
6496 if (!NT_STATUS_IS_OK(status)) {
6497 printf("close - 1 failed (%s)\n", nt_errstr(status));
6501 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6502 cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6503 status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS, FILE_ATTRIBUTE_NORMAL,
6505 FILE_SHARE_DELETE|FILE_SHARE_NONE,
6507 FILE_SHARE_DELETE|FILE_SHARE_READ,
6509 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
6510 if (!NT_STATUS_IS_OK(status)) {
6511 printf("Second open failed - %s\n", nt_errstr(status));
6515 status = cli_rename(cli1, fname, fname1, false);
6516 if (!NT_STATUS_IS_OK(status)) {
6517 printf("Second rename failed (SHARE_DELETE | SHARE_READ) - this should have succeeded - %s\n", nt_errstr(status));
6520 printf("Second rename succeeded (SHARE_DELETE | SHARE_READ)\n");
6523 status = cli_close(cli1, fnum1);
6524 if (!NT_STATUS_IS_OK(status)) {
6525 printf("close - 2 failed (%s)\n", nt_errstr(status));
6529 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6530 cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6532 status = cli_ntcreate(cli1, fname, 0, READ_CONTROL_ACCESS,
6533 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
6534 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
6535 if (!NT_STATUS_IS_OK(status)) {
6536 printf("Third open failed - %s\n", nt_errstr(status));
6541 status = cli_rename(cli1, fname, fname1, false);
6542 if (!NT_STATUS_IS_OK(status)) {
6543 printf("Third rename failed (SHARE_NONE) - this should have succeeded - %s\n", nt_errstr(status));
6546 printf("Third rename succeeded (SHARE_NONE)\n");
6549 status = cli_close(cli1, fnum1);
6550 if (!NT_STATUS_IS_OK(status)) {
6551 printf("close - 3 failed (%s)\n", nt_errstr(status));
6555 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6556 cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6560 status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
6561 FILE_ATTRIBUTE_NORMAL,
6562 FILE_SHARE_READ | FILE_SHARE_WRITE,
6563 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
6564 if (!NT_STATUS_IS_OK(status)) {
6565 printf("Fourth open failed - %s\n", nt_errstr(status));
6569 status = cli_rename(cli1, fname, fname1, false);
6570 if (!NT_STATUS_IS_OK(status)) {
6571 printf("Fourth rename failed (SHARE_READ | SHARE_WRITE) (this is correct) - %s\n", nt_errstr(status));
6573 printf("Fourth rename succeeded (SHARE_READ | SHARE_WRITE) - this should have failed !\n");
6577 status = cli_close(cli1, fnum1);
6578 if (!NT_STATUS_IS_OK(status)) {
6579 printf("close - 4 failed (%s)\n", nt_errstr(status));
6583 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6584 cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6588 status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
6589 FILE_ATTRIBUTE_NORMAL,
6590 FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
6591 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
6592 if (!NT_STATUS_IS_OK(status)) {
6593 printf("Fifth open failed - %s\n", nt_errstr(status));
6597 status = cli_rename(cli1, fname, fname1, false);
6598 if (!NT_STATUS_IS_OK(status)) {
6599 printf("Fifth rename failed (SHARE_READ | SHARE_WRITE | SHARE_DELETE) - this should have succeeded - %s ! \n", nt_errstr(status));
6602 printf("Fifth rename succeeded (SHARE_READ | SHARE_WRITE | SHARE_DELETE) (this is correct) - %s\n", nt_errstr(status));
6606 status = cli_close(cli1, fnum1);
6607 if (!NT_STATUS_IS_OK(status)) {
6608 printf("close - 5 failed (%s)\n", nt_errstr(status));
6612 /* Check that the renamed file has FILE_ATTRIBUTE_ARCHIVE. */
6613 status = cli_getatr(cli1, fname1, &attr, NULL, NULL);
6614 if (!NT_STATUS_IS_OK(status)) {
6615 printf("getatr on file %s failed - %s ! \n",
6616 fname1, nt_errstr(status));
6619 if (attr != FILE_ATTRIBUTE_ARCHIVE) {
6620 printf("Renamed file %s has wrong attr 0x%x "
6621 "(should be 0x%x)\n",
6624 (unsigned int)FILE_ATTRIBUTE_ARCHIVE);
6627 printf("Renamed file %s has archive bit set\n", fname1);
6631 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6632 cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6634 if (!torture_close_connection(cli1)) {
6642 Test rename into a directory with an ACL denying it.
6644 static bool run_rename_access(int dummy)
6646 static struct cli_state *cli = NULL;
6647 static struct cli_state *posix_cli = NULL;
6648 const char *src = "test.txt";
6649 const char *dname = "dir";
6650 const char *dst = "dir\\test.txt";
6651 const char *dsrc = "test.dir";
6652 const char *ddst = "dir\\test.dir";
6653 uint16_t fnum = (uint16_t)-1;
6654 struct security_descriptor *sd = NULL;
6655 struct security_descriptor *newsd = NULL;
6657 TALLOC_CTX *frame = NULL;
6659 frame = talloc_stackframe();
6660 printf("starting rename access test\n");
6662 /* Windows connection. */
6663 if (!torture_open_connection(&cli, 0)) {
6667 smbXcli_conn_set_sockopt(cli->conn, sockops);
6669 /* Posix connection. */
6670 if (!torture_open_connection(&posix_cli, 0)) {
6674 smbXcli_conn_set_sockopt(posix_cli->conn, sockops);
6676 status = torture_setup_unix_extensions(posix_cli);
6677 if (!NT_STATUS_IS_OK(status)) {
6681 /* Start with a clean slate. */
6682 cli_unlink(cli, src, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6683 cli_unlink(cli, dst, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6684 cli_rmdir(cli, dsrc);
6685 cli_rmdir(cli, ddst);
6686 cli_rmdir(cli, dname);
6689 * Setup the destination directory with a DENY ACE to
6690 * prevent new files within it.
6692 status = cli_ntcreate(cli,
6695 FILE_READ_ATTRIBUTES|READ_CONTROL_ACCESS|
6696 WRITE_DAC_ACCESS|FILE_READ_DATA|
6698 FILE_ATTRIBUTE_DIRECTORY,
6699 FILE_SHARE_READ|FILE_SHARE_WRITE,
6701 FILE_DIRECTORY_FILE,
6705 if (!NT_STATUS_IS_OK(status)) {
6706 printf("Create of %s - %s\n", dname, nt_errstr(status));
6710 status = cli_query_secdesc(cli,
6714 if (!NT_STATUS_IS_OK(status)) {
6715 printf("cli_query_secdesc failed for %s (%s)\n",
6716 dname, nt_errstr(status));
6720 newsd = security_descriptor_dacl_create(frame,
6725 SEC_ACE_TYPE_ACCESS_DENIED,
6726 SEC_DIR_ADD_FILE|SEC_DIR_ADD_SUBDIR,
6729 if (newsd == NULL) {
6732 sd->dacl = security_acl_concatenate(frame,
6735 if (sd->dacl == NULL) {
6738 status = cli_set_secdesc(cli, fnum, sd);
6739 if (!NT_STATUS_IS_OK(status)) {
6740 printf("cli_set_secdesc failed for %s (%s)\n",
6741 dname, nt_errstr(status));
6744 status = cli_close(cli, fnum);
6745 if (!NT_STATUS_IS_OK(status)) {
6746 printf("close failed for %s (%s)\n",
6747 dname, nt_errstr(status));
6750 /* Now go around the back and chmod to 777 via POSIX. */
6751 status = cli_posix_chmod(posix_cli, dname, 0777);
6752 if (!NT_STATUS_IS_OK(status)) {
6753 printf("cli_posix_chmod failed for %s (%s)\n",
6754 dname, nt_errstr(status));
6758 /* Check we can't create a file within dname via Windows. */
6759 status = cli_openx(cli, dst, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
6760 if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
6761 cli_close(posix_cli, fnum);
6762 printf("Create of %s should be ACCESS denied, was %s\n",
6763 dst, nt_errstr(status));
6767 /* Make the sample file/directory. */
6768 status = cli_openx(cli, src, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
6769 if (!NT_STATUS_IS_OK(status)) {
6770 printf("open of %s failed (%s)\n", src, nt_errstr(status));
6773 status = cli_close(cli, fnum);
6774 if (!NT_STATUS_IS_OK(status)) {
6775 printf("cli_close failed (%s)\n", nt_errstr(status));
6779 status = cli_mkdir(cli, dsrc);
6780 if (!NT_STATUS_IS_OK(status)) {
6781 printf("cli_mkdir of %s failed (%s)\n",
6782 dsrc, nt_errstr(status));
6787 * OK - renames of the new file and directory into the
6788 * dst directory should fail.
6791 status = cli_rename(cli, src, dst, false);
6792 if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
6793 printf("rename of %s -> %s should be ACCESS denied, was %s\n",
6794 src, dst, nt_errstr(status));
6797 status = cli_rename(cli, dsrc, ddst, false);
6798 if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
6799 printf("rename of %s -> %s should be ACCESS denied, was %s\n",
6800 src, dst, nt_errstr(status));
6810 torture_close_connection(posix_cli);
6814 if (fnum != (uint16_t)-1) {
6815 cli_close(cli, fnum);
6817 cli_unlink(cli, src,
6818 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6819 cli_unlink(cli, dst,
6820 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6821 cli_rmdir(cli, dsrc);
6822 cli_rmdir(cli, ddst);
6823 cli_rmdir(cli, dname);
6825 torture_close_connection(cli);
6833 Test owner rights ACE.
6835 static bool run_owner_rights(int dummy)
6837 static struct cli_state *cli = NULL;
6838 const char *fname = "owner_rights.txt";
6839 uint16_t fnum = (uint16_t)-1;
6840 struct security_descriptor *sd = NULL;
6841 struct security_descriptor *newsd = NULL;
6843 TALLOC_CTX *frame = NULL;
6845 frame = talloc_stackframe();
6846 printf("starting owner rights test\n");
6848 /* Windows connection. */
6849 if (!torture_open_connection(&cli, 0)) {
6853 smbXcli_conn_set_sockopt(cli->conn, sockops);
6855 /* Start with a clean slate. */
6856 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6858 /* Create the test file. */
6859 /* Now try and open for read and write-dac. */
6860 status = cli_ntcreate(cli,
6864 FILE_ATTRIBUTE_NORMAL,
6865 FILE_SHARE_READ|FILE_SHARE_WRITE|
6872 if (!NT_STATUS_IS_OK(status)) {
6873 printf("Create of %s - %s\n", fname, nt_errstr(status));
6877 /* Get the original SD. */
6878 status = cli_query_secdesc(cli,
6882 if (!NT_STATUS_IS_OK(status)) {
6883 printf("cli_query_secdesc failed for %s (%s)\n",
6884 fname, nt_errstr(status));
6889 * Add an "owner-rights" ACE denying WRITE_DATA,
6890 * and an "owner-rights" ACE allowing READ_DATA.
6893 newsd = security_descriptor_dacl_create(frame,
6898 SEC_ACE_TYPE_ACCESS_DENIED,
6902 SEC_ACE_TYPE_ACCESS_ALLOWED,
6906 if (newsd == NULL) {
6909 sd->dacl = security_acl_concatenate(frame,
6912 if (sd->dacl == NULL) {
6915 status = cli_set_secdesc(cli, fnum, sd);
6916 if (!NT_STATUS_IS_OK(status)) {
6917 printf("cli_set_secdesc failed for %s (%s)\n",
6918 fname, nt_errstr(status));
6921 status = cli_close(cli, fnum);
6922 if (!NT_STATUS_IS_OK(status)) {
6923 printf("close failed for %s (%s)\n",
6924 fname, nt_errstr(status));
6927 fnum = (uint16_t)-1;
6929 /* Try and open for FILE_WRITE_DATA */
6930 status = cli_ntcreate(cli,
6934 FILE_ATTRIBUTE_NORMAL,
6935 FILE_SHARE_READ|FILE_SHARE_WRITE|
6942 if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
6943 printf("Open of %s - %s\n", fname, nt_errstr(status));
6947 /* Now try and open for FILE_READ_DATA */
6948 status = cli_ntcreate(cli,
6952 FILE_ATTRIBUTE_NORMAL,
6953 FILE_SHARE_READ|FILE_SHARE_WRITE|
6960 if (!NT_STATUS_IS_OK(status)) {
6961 printf("Open of %s - %s\n", fname, nt_errstr(status));
6965 status = cli_close(cli, fnum);
6966 if (!NT_STATUS_IS_OK(status)) {
6967 printf("close failed for %s (%s)\n",
6968 fname, nt_errstr(status));
6972 /* Restore clean slate. */
6974 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6976 /* Create the test file. */
6977 status = cli_ntcreate(cli,
6981 FILE_ATTRIBUTE_NORMAL,
6982 FILE_SHARE_READ|FILE_SHARE_WRITE|
6989 if (!NT_STATUS_IS_OK(status)) {
6990 printf("Create of %s - %s\n", fname, nt_errstr(status));
6994 /* Get the original SD. */
6995 status = cli_query_secdesc(cli,
6999 if (!NT_STATUS_IS_OK(status)) {
7000 printf("cli_query_secdesc failed for %s (%s)\n",
7001 fname, nt_errstr(status));
7006 * Add an "owner-rights ACE denying WRITE_DATA,
7007 * and an "owner-rights ACE allowing READ_DATA|WRITE_DATA.
7010 newsd = security_descriptor_dacl_create(frame,
7015 SEC_ACE_TYPE_ACCESS_DENIED,
7019 SEC_ACE_TYPE_ACCESS_ALLOWED,
7020 FILE_READ_DATA|FILE_WRITE_DATA,
7023 if (newsd == NULL) {
7026 sd->dacl = security_acl_concatenate(frame,
7029 if (sd->dacl == NULL) {
7032 status = cli_set_secdesc(cli, fnum, sd);
7033 if (!NT_STATUS_IS_OK(status)) {
7034 printf("cli_set_secdesc failed for %s (%s)\n",
7035 fname, nt_errstr(status));
7038 status = cli_close(cli, fnum);
7039 if (!NT_STATUS_IS_OK(status)) {
7040 printf("close failed for %s (%s)\n",
7041 fname, nt_errstr(status));
7044 fnum = (uint16_t)-1;
7046 /* Try and open for FILE_WRITE_DATA */
7047 status = cli_ntcreate(cli,
7051 FILE_ATTRIBUTE_NORMAL,
7052 FILE_SHARE_READ|FILE_SHARE_WRITE|
7059 if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
7060 printf("Open of %s - %s\n", fname, nt_errstr(status));
7064 /* Now try and open for FILE_READ_DATA */
7065 status = cli_ntcreate(cli,
7069 FILE_ATTRIBUTE_NORMAL,
7070 FILE_SHARE_READ|FILE_SHARE_WRITE|
7077 if (!NT_STATUS_IS_OK(status)) {
7078 printf("Open of %s - %s\n", fname, nt_errstr(status));
7082 status = cli_close(cli, fnum);
7083 if (!NT_STATUS_IS_OK(status)) {
7084 printf("close failed for %s (%s)\n",
7085 fname, nt_errstr(status));
7089 /* Restore clean slate. */
7091 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7094 /* Create the test file. */
7095 status = cli_ntcreate(cli,
7099 FILE_ATTRIBUTE_NORMAL,
7100 FILE_SHARE_READ|FILE_SHARE_WRITE|
7107 if (!NT_STATUS_IS_OK(status)) {
7108 printf("Create of %s - %s\n", fname, nt_errstr(status));
7112 /* Get the original SD. */
7113 status = cli_query_secdesc(cli,
7117 if (!NT_STATUS_IS_OK(status)) {
7118 printf("cli_query_secdesc failed for %s (%s)\n",
7119 fname, nt_errstr(status));
7124 * Add an "authenticated users" ACE allowing READ_DATA,
7125 * add an "owner-rights" denying READ_DATA,
7126 * and an "authenticated users" ACE allowing WRITE_DATA.
7129 newsd = security_descriptor_dacl_create(frame,
7133 SID_NT_AUTHENTICATED_USERS,
7134 SEC_ACE_TYPE_ACCESS_ALLOWED,
7138 SEC_ACE_TYPE_ACCESS_DENIED,
7141 SID_NT_AUTHENTICATED_USERS,
7142 SEC_ACE_TYPE_ACCESS_ALLOWED,
7146 if (newsd == NULL) {
7147 printf("newsd == NULL\n");
7150 sd->dacl = security_acl_concatenate(frame,
7153 if (sd->dacl == NULL) {
7154 printf("sd->dacl == NULL\n");
7157 status = cli_set_secdesc(cli, fnum, sd);
7158 if (!NT_STATUS_IS_OK(status)) {
7159 printf("cli_set_secdesc failed for %s (%s)\n",
7160 fname, nt_errstr(status));
7163 status = cli_close(cli, fnum);
7164 if (!NT_STATUS_IS_OK(status)) {
7165 printf("close failed for %s (%s)\n",
7166 fname, nt_errstr(status));
7169 fnum = (uint16_t)-1;
7171 /* Now try and open for FILE_READ_DATA|FILE_WRITE_DATA */
7172 status = cli_ntcreate(cli,
7175 FILE_READ_DATA|FILE_WRITE_DATA,
7176 FILE_ATTRIBUTE_NORMAL,
7177 FILE_SHARE_READ|FILE_SHARE_WRITE|
7184 if (!NT_STATUS_IS_OK(status)) {
7185 printf("Open of %s - %s\n", fname, nt_errstr(status));
7189 status = cli_close(cli, fnum);
7190 if (!NT_STATUS_IS_OK(status)) {
7191 printf("close failed for %s (%s)\n",
7192 fname, nt_errstr(status));
7196 cli_unlink(cli, fname,
7197 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7205 if (fnum != (uint16_t)-1) {
7206 cli_close(cli, fnum);
7208 cli_unlink(cli, fname,
7209 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7210 torture_close_connection(cli);
7218 * Test SMB1-specific open with SEC_FLAG_SYSTEM_SECURITY.
7219 * Note this test only works with a user with SeSecurityPrivilege set.
7221 * NB. This is also tested in samba3.base.createx_access
7222 * but this makes it very explicit what we're looking for.
7224 static bool run_smb1_system_security(int dummy)
7226 static struct cli_state *cli = NULL;
7227 const char *fname = "system_security.txt";
7228 uint16_t fnum = (uint16_t)-1;
7230 TALLOC_CTX *frame = NULL;
7232 frame = talloc_stackframe();
7233 printf("starting smb1 system security test\n");
7235 /* SMB1 connection - torture_open_connection() forces this. */
7236 if (!torture_open_connection(&cli, 0)) {
7240 smbXcli_conn_set_sockopt(cli->conn, sockops);
7242 /* Start with a clean slate. */
7243 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7245 /* Create the test file. */
7246 status = cli_ntcreate(cli,
7250 FILE_ATTRIBUTE_NORMAL,
7251 FILE_SHARE_READ|FILE_SHARE_WRITE|
7258 if (!NT_STATUS_IS_OK(status)) {
7259 printf("Create of %s - %s\n", fname, nt_errstr(status));
7263 status = cli_close(cli, fnum);
7265 /* Open with SEC_FLAG_SYSTEM_SECURITY only. */
7267 * On SMB1 this succeeds - SMB2 it fails,
7268 * see the SMB2-SACL test.
7270 status = cli_ntcreate(cli,
7273 SEC_FLAG_SYSTEM_SECURITY,
7274 FILE_ATTRIBUTE_NORMAL,
7275 FILE_SHARE_READ|FILE_SHARE_WRITE|
7282 if (!NT_STATUS_IS_OK(status)) {
7283 printf("Open of %s - %s\n", fname, nt_errstr(status));
7287 status = cli_close(cli, fnum);
7289 cli_unlink(cli, fname,
7290 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7292 torture_close_connection(cli);
7299 if (fnum != (uint16_t)-1) {
7300 cli_close(cli, fnum);
7302 cli_unlink(cli, fname,
7303 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7304 torture_close_connection(cli);
7311 static bool run_pipe_number(int dummy)
7313 struct cli_state *cli1;
7314 const char *pipe_name = "\\SPOOLSS";
7319 printf("starting pipenumber test\n");
7320 if (!torture_open_connection(&cli1, 0)) {
7324 smbXcli_conn_set_sockopt(cli1->conn, sockops);
7326 status = cli_ntcreate(cli1, pipe_name, 0, FILE_READ_DATA,
7327 FILE_ATTRIBUTE_NORMAL,
7328 FILE_SHARE_READ|FILE_SHARE_WRITE,
7329 FILE_OPEN_IF, 0, 0, &fnum, NULL);
7330 if (!NT_STATUS_IS_OK(status)) {
7331 printf("Open of pipe %s failed with error (%s)\n", pipe_name, nt_errstr(status));
7335 printf("\r%6d", num_pipes);
7338 printf("pipe_number test - we can open %d %s pipes.\n", num_pipes, pipe_name );
7339 torture_close_connection(cli1);
7344 Test open mode returns on read-only files.
7346 static bool run_opentest(int dummy)
7348 static struct cli_state *cli1;
7349 static struct cli_state *cli2;
7350 const char *fname = "\\readonly.file";
7351 uint16_t fnum1, fnum2;
7354 bool correct = True;
7358 printf("starting open test\n");
7360 if (!torture_open_connection(&cli1, 0)) {
7364 cli_setatr(cli1, fname, 0, 0);
7365 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7367 smbXcli_conn_set_sockopt(cli1->conn, sockops);
7369 status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
7370 if (!NT_STATUS_IS_OK(status)) {
7371 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
7375 status = cli_close(cli1, fnum1);
7376 if (!NT_STATUS_IS_OK(status)) {
7377 printf("close2 failed (%s)\n", nt_errstr(status));
7381 status = cli_setatr(cli1, fname, FILE_ATTRIBUTE_READONLY, 0);
7382 if (!NT_STATUS_IS_OK(status)) {
7383 printf("cli_setatr failed (%s)\n", nt_errstr(status));
7387 status = cli_openx(cli1, fname, O_RDONLY, DENY_WRITE, &fnum1);
7388 if (!NT_STATUS_IS_OK(status)) {
7389 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
7393 /* This will fail - but the error should be ERRnoaccess, not ERRbadshare. */
7394 status = cli_openx(cli1, fname, O_RDWR, DENY_ALL, &fnum2);
7396 if (check_error(__LINE__, status, ERRDOS, ERRnoaccess,
7397 NT_STATUS_ACCESS_DENIED)) {
7398 printf("correct error code ERRDOS/ERRnoaccess returned\n");
7401 printf("finished open test 1\n");
7403 cli_close(cli1, fnum1);
7405 /* Now try not readonly and ensure ERRbadshare is returned. */
7407 cli_setatr(cli1, fname, 0, 0);
7409 status = cli_openx(cli1, fname, O_RDONLY, DENY_WRITE, &fnum1);
7410 if (!NT_STATUS_IS_OK(status)) {
7411 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
7415 /* This will fail - but the error should be ERRshare. */
7416 status = cli_openx(cli1, fname, O_RDWR, DENY_ALL, &fnum2);
7418 if (check_error(__LINE__, status, ERRDOS, ERRbadshare,
7419 NT_STATUS_SHARING_VIOLATION)) {
7420 printf("correct error code ERRDOS/ERRbadshare returned\n");
7423 status = cli_close(cli1, fnum1);
7424 if (!NT_STATUS_IS_OK(status)) {
7425 printf("close2 failed (%s)\n", nt_errstr(status));
7429 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7431 printf("finished open test 2\n");
7433 /* Test truncate open disposition on file opened for read. */
7434 status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
7435 if (!NT_STATUS_IS_OK(status)) {
7436 printf("(3) open (1) of %s failed (%s)\n", fname, nt_errstr(status));
7440 /* write 20 bytes. */
7442 memset(buf, '\0', 20);
7444 status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 0, 20, NULL);
7445 if (!NT_STATUS_IS_OK(status)) {
7446 printf("write failed (%s)\n", nt_errstr(status));
7450 status = cli_close(cli1, fnum1);
7451 if (!NT_STATUS_IS_OK(status)) {
7452 printf("(3) close1 failed (%s)\n", nt_errstr(status));
7456 /* Ensure size == 20. */
7457 status = cli_getatr(cli1, fname, NULL, &fsize, NULL);
7458 if (!NT_STATUS_IS_OK(status)) {
7459 printf("(3) getatr failed (%s)\n", nt_errstr(status));
7464 printf("(3) file size != 20\n");
7468 /* Now test if we can truncate a file opened for readonly. */
7469 status = cli_openx(cli1, fname, O_RDONLY|O_TRUNC, DENY_NONE, &fnum1);
7470 if (!NT_STATUS_IS_OK(status)) {
7471 printf("(3) open (2) of %s failed (%s)\n", fname, nt_errstr(status));
7475 status = cli_close(cli1, fnum1);
7476 if (!NT_STATUS_IS_OK(status)) {
7477 printf("close2 failed (%s)\n", nt_errstr(status));
7481 /* Ensure size == 0. */
7482 status = cli_getatr(cli1, fname, NULL, &fsize, NULL);
7483 if (!NT_STATUS_IS_OK(status)) {
7484 printf("(3) getatr failed (%s)\n", nt_errstr(status));
7489 printf("(3) file size != 0\n");
7492 printf("finished open test 3\n");
7494 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7496 printf("Do ctemp tests\n");
7497 status = cli_ctemp(cli1, talloc_tos(), "\\", &fnum1, &tmp_path);
7498 if (!NT_STATUS_IS_OK(status)) {
7499 printf("ctemp failed (%s)\n", nt_errstr(status));
7503 printf("ctemp gave path %s\n", tmp_path);
7504 status = cli_close(cli1, fnum1);
7505 if (!NT_STATUS_IS_OK(status)) {
7506 printf("close of temp failed (%s)\n", nt_errstr(status));
7509 status = cli_unlink(cli1, tmp_path, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7510 if (!NT_STATUS_IS_OK(status)) {
7511 printf("unlink of temp failed (%s)\n", nt_errstr(status));
7514 /* Test the non-io opens... */
7516 if (!torture_open_connection(&cli2, 1)) {
7520 cli_setatr(cli2, fname, 0, 0);
7521 cli_unlink(cli2, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7523 smbXcli_conn_set_sockopt(cli2->conn, sockops);
7525 printf("TEST #1 testing 2 non-io opens (no delete)\n");
7526 status = cli_ntcreate(cli1, fname, 0, FILE_READ_ATTRIBUTES,
7527 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7528 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
7529 if (!NT_STATUS_IS_OK(status)) {
7530 printf("TEST #1 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
7534 status = cli_ntcreate(cli2, fname, 0, FILE_READ_ATTRIBUTES,
7535 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7536 FILE_OPEN_IF, 0, 0, &fnum2, NULL);
7537 if (!NT_STATUS_IS_OK(status)) {
7538 printf("TEST #1 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
7542 status = cli_close(cli1, fnum1);
7543 if (!NT_STATUS_IS_OK(status)) {
7544 printf("TEST #1 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
7548 status = cli_close(cli2, fnum2);
7549 if (!NT_STATUS_IS_OK(status)) {
7550 printf("TEST #1 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
7554 printf("non-io open test #1 passed.\n");
7556 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7558 printf("TEST #2 testing 2 non-io opens (first with delete)\n");
7560 status = cli_ntcreate(cli1, fname, 0,
7561 DELETE_ACCESS|FILE_READ_ATTRIBUTES,
7562 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7563 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
7564 if (!NT_STATUS_IS_OK(status)) {
7565 printf("TEST #2 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
7569 status = cli_ntcreate(cli2, fname, 0, FILE_READ_ATTRIBUTES,
7570 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7571 FILE_OPEN_IF, 0, 0, &fnum2, NULL);
7572 if (!NT_STATUS_IS_OK(status)) {
7573 printf("TEST #2 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
7577 status = cli_close(cli1, fnum1);
7578 if (!NT_STATUS_IS_OK(status)) {
7579 printf("TEST #2 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
7583 status = cli_close(cli2, fnum2);
7584 if (!NT_STATUS_IS_OK(status)) {
7585 printf("TEST #2 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
7589 printf("non-io open test #2 passed.\n");
7591 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7593 printf("TEST #3 testing 2 non-io opens (second with delete)\n");
7595 status = cli_ntcreate(cli1, fname, 0, FILE_READ_ATTRIBUTES,
7596 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7597 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
7598 if (!NT_STATUS_IS_OK(status)) {
7599 printf("TEST #3 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
7603 status = cli_ntcreate(cli2, fname, 0,
7604 DELETE_ACCESS|FILE_READ_ATTRIBUTES,
7605 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7606 FILE_OPEN_IF, 0, 0, &fnum2, NULL);
7607 if (!NT_STATUS_IS_OK(status)) {
7608 printf("TEST #3 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
7612 status = cli_close(cli1, fnum1);
7613 if (!NT_STATUS_IS_OK(status)) {
7614 printf("TEST #3 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
7618 status = cli_close(cli2, fnum2);
7619 if (!NT_STATUS_IS_OK(status)) {
7620 printf("TEST #3 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
7624 printf("non-io open test #3 passed.\n");
7626 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7628 printf("TEST #4 testing 2 non-io opens (both with delete)\n");
7630 status = cli_ntcreate(cli1, fname, 0,
7631 DELETE_ACCESS|FILE_READ_ATTRIBUTES,
7632 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7633 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
7634 if (!NT_STATUS_IS_OK(status)) {
7635 printf("TEST #4 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
7639 status = cli_ntcreate(cli2, fname, 0,
7640 DELETE_ACCESS|FILE_READ_ATTRIBUTES,
7641 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7642 FILE_OPEN_IF, 0, 0, &fnum2, NULL);
7643 if (NT_STATUS_IS_OK(status)) {
7644 printf("TEST #4 open 2 of %s SUCCEEDED - should have failed (%s)\n", fname, nt_errstr(status));
7648 printf("TEST #4 open 2 of %s gave %s (correct error should be %s)\n", fname, nt_errstr(status), "sharing violation");
7650 status = cli_close(cli1, fnum1);
7651 if (!NT_STATUS_IS_OK(status)) {
7652 printf("TEST #4 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
7656 printf("non-io open test #4 passed.\n");
7658 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7660 printf("TEST #5 testing 2 non-io opens (both with delete - both with file share delete)\n");
7662 status = cli_ntcreate(cli1, fname, 0,
7663 DELETE_ACCESS|FILE_READ_ATTRIBUTES,
7664 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_DELETE,
7665 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
7666 if (!NT_STATUS_IS_OK(status)) {
7667 printf("TEST #5 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
7671 status = cli_ntcreate(cli2, fname, 0,
7672 DELETE_ACCESS|FILE_READ_ATTRIBUTES,
7673 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_DELETE,
7674 FILE_OPEN_IF, 0, 0, &fnum2, NULL);
7675 if (!NT_STATUS_IS_OK(status)) {
7676 printf("TEST #5 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
7680 status = cli_close(cli1, fnum1);
7681 if (!NT_STATUS_IS_OK(status)) {
7682 printf("TEST #5 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
7686 status = cli_close(cli2, fnum2);
7687 if (!NT_STATUS_IS_OK(status)) {
7688 printf("TEST #5 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
7692 printf("non-io open test #5 passed.\n");
7694 printf("TEST #6 testing 1 non-io open, one io open\n");
7696 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7698 status = cli_ntcreate(cli1, fname, 0, FILE_READ_DATA,
7699 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7700 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
7701 if (!NT_STATUS_IS_OK(status)) {
7702 printf("TEST #6 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
7706 status = cli_ntcreate(cli2, fname, 0, FILE_READ_ATTRIBUTES,
7707 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ,
7708 FILE_OPEN_IF, 0, 0, &fnum2, NULL);
7709 if (!NT_STATUS_IS_OK(status)) {
7710 printf("TEST #6 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
7714 status = cli_close(cli1, fnum1);
7715 if (!NT_STATUS_IS_OK(status)) {
7716 printf("TEST #6 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
7720 status = cli_close(cli2, fnum2);
7721 if (!NT_STATUS_IS_OK(status)) {
7722 printf("TEST #6 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
7726 printf("non-io open test #6 passed.\n");
7728 printf("TEST #7 testing 1 non-io open, one io open with delete\n");
7730 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7732 status = cli_ntcreate(cli1, fname, 0, FILE_READ_DATA,
7733 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7734 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
7735 if (!NT_STATUS_IS_OK(status)) {
7736 printf("TEST #7 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
7740 status = cli_ntcreate(cli2, fname, 0,
7741 DELETE_ACCESS|FILE_READ_ATTRIBUTES,
7742 FILE_ATTRIBUTE_NORMAL,
7743 FILE_SHARE_READ|FILE_SHARE_DELETE,
7744 FILE_OPEN_IF, 0, 0, &fnum2, NULL);
7745 if (NT_STATUS_IS_OK(status)) {
7746 printf("TEST #7 open 2 of %s SUCCEEDED - should have failed (%s)\n", fname, nt_errstr(status));
7750 printf("TEST #7 open 2 of %s gave %s (correct error should be %s)\n", fname, nt_errstr(status), "sharing violation");
7752 status = cli_close(cli1, fnum1);
7753 if (!NT_STATUS_IS_OK(status)) {
7754 printf("TEST #7 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
7758 printf("non-io open test #7 passed.\n");
7760 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7762 printf("TEST #8 testing open without WRITE_ATTRIBUTES, updating close write time.\n");
7763 status = cli_ntcreate(cli1, fname, 0, FILE_WRITE_DATA, FILE_ATTRIBUTE_NORMAL,
7764 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
7765 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
7766 if (!NT_STATUS_IS_OK(status)) {
7767 printf("TEST #8 open of %s failed (%s)\n", fname, nt_errstr(status));
7772 /* Write to ensure we have to update the file time. */
7773 status = cli_writeall(cli1, fnum1, 0, (const uint8_t *)"TEST DATA\n", 0, 10,
7775 if (!NT_STATUS_IS_OK(status)) {
7776 printf("TEST #8 cli_write failed: %s\n", nt_errstr(status));
7781 status = cli_close(cli1, fnum1);
7782 if (!NT_STATUS_IS_OK(status)) {
7783 printf("TEST #8 close of %s failed (%s)\n", fname, nt_errstr(status));
7789 if (!torture_close_connection(cli1)) {
7792 if (!torture_close_connection(cli2)) {
7799 NTSTATUS torture_setup_unix_extensions(struct cli_state *cli)
7801 uint16_t major, minor;
7802 uint32_t caplow, caphigh;
7805 if (!SERVER_HAS_UNIX_CIFS(cli)) {
7806 printf("Server doesn't support UNIX CIFS extensions.\n");
7807 return NT_STATUS_NOT_SUPPORTED;
7810 status = cli_unix_extensions_version(cli, &major, &minor, &caplow,
7812 if (!NT_STATUS_IS_OK(status)) {
7813 printf("Server didn't return UNIX CIFS extensions: %s\n",
7818 status = cli_set_unix_extensions_capabilities(cli, major, minor,
7820 if (!NT_STATUS_IS_OK(status)) {
7821 printf("Server doesn't support setting UNIX CIFS extensions: "
7822 "%s.\n", nt_errstr(status));
7826 return NT_STATUS_OK;
7830 Test POSIX open /mkdir calls.
7832 static bool run_simple_posix_open_test(int dummy)
7834 static struct cli_state *cli1;
7835 const char *fname = "posix:file";
7836 const char *hname = "posix:hlink";
7837 const char *sname = "posix:symlink";
7838 const char *dname = "posix:dir";
7840 char *target = NULL;
7841 uint16_t fnum1 = (uint16_t)-1;
7842 SMB_STRUCT_STAT sbuf;
7843 bool correct = false;
7846 const char *fname_windows = "windows_file";
7847 uint16_t fnum2 = (uint16_t)-1;
7850 printf("Starting simple POSIX open test\n");
7852 if (!torture_open_connection(&cli1, 0)) {
7856 smbXcli_conn_set_sockopt(cli1->conn, sockops);
7858 status = torture_setup_unix_extensions(cli1);
7859 if (!NT_STATUS_IS_OK(status)) {
7863 cli_setatr(cli1, fname, 0, 0);
7864 cli_posix_unlink(cli1, fname);
7865 cli_setatr(cli1, dname, 0, 0);
7866 cli_posix_rmdir(cli1, dname);
7867 cli_setatr(cli1, hname, 0, 0);
7868 cli_posix_unlink(cli1, hname);
7869 cli_setatr(cli1, sname, 0, 0);
7870 cli_posix_unlink(cli1, sname);
7871 cli_setatr(cli1, fname_windows, 0, 0);
7872 cli_posix_unlink(cli1, fname_windows);
7874 /* Create a directory. */
7875 status = cli_posix_mkdir(cli1, dname, 0777);
7876 if (!NT_STATUS_IS_OK(status)) {
7877 printf("POSIX mkdir of %s failed (%s)\n", dname, nt_errstr(status));
7881 status = cli_posix_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL,
7883 if (!NT_STATUS_IS_OK(status)) {
7884 printf("POSIX create of %s failed (%s)\n", fname, nt_errstr(status));
7888 /* Test ftruncate - set file size. */
7889 status = cli_ftruncate(cli1, fnum1, 1000);
7890 if (!NT_STATUS_IS_OK(status)) {
7891 printf("ftruncate failed (%s)\n", nt_errstr(status));
7895 /* Ensure st_size == 1000 */
7896 status = cli_posix_stat(cli1, fname, &sbuf);
7897 if (!NT_STATUS_IS_OK(status)) {
7898 printf("stat failed (%s)\n", nt_errstr(status));
7902 if (sbuf.st_ex_size != 1000) {
7903 printf("ftruncate - stat size (%u) != 1000\n", (unsigned int)sbuf.st_ex_size);
7907 /* Ensure st_mode == 0600 */
7908 if ((sbuf.st_ex_mode & 07777) != 0600) {
7909 printf("posix_open - bad permissions 0%o != 0600\n",
7910 (unsigned int)(sbuf.st_ex_mode & 07777));
7914 /* Test ftruncate - set file size back to zero. */
7915 status = cli_ftruncate(cli1, fnum1, 0);
7916 if (!NT_STATUS_IS_OK(status)) {
7917 printf("ftruncate failed (%s)\n", nt_errstr(status));
7921 status = cli_close(cli1, fnum1);
7922 if (!NT_STATUS_IS_OK(status)) {
7923 printf("close failed (%s)\n", nt_errstr(status));
7927 /* Now open the file again for read only. */
7928 status = cli_posix_open(cli1, fname, O_RDONLY, 0, &fnum1);
7929 if (!NT_STATUS_IS_OK(status)) {
7930 printf("POSIX open of %s failed (%s)\n", fname, nt_errstr(status));
7934 /* Now unlink while open. */
7935 status = cli_posix_unlink(cli1, fname);
7936 if (!NT_STATUS_IS_OK(status)) {
7937 printf("POSIX unlink of %s failed (%s)\n", fname, nt_errstr(status));
7941 status = cli_close(cli1, fnum1);
7942 if (!NT_STATUS_IS_OK(status)) {
7943 printf("close(2) failed (%s)\n", nt_errstr(status));
7947 /* Ensure the file has gone. */
7948 status = cli_posix_open(cli1, fname, O_RDONLY, 0, &fnum1);
7949 if (NT_STATUS_IS_OK(status)) {
7950 printf("POSIX open of %s succeeded, should have been deleted.\n", fname);
7954 /* Create again to test open with O_TRUNC. */
7955 status = cli_posix_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL, 0600, &fnum1);
7956 if (!NT_STATUS_IS_OK(status)) {
7957 printf("POSIX create of %s failed (%s)\n", fname, nt_errstr(status));
7961 /* Test ftruncate - set file size. */
7962 status = cli_ftruncate(cli1, fnum1, 1000);
7963 if (!NT_STATUS_IS_OK(status)) {
7964 printf("ftruncate failed (%s)\n", nt_errstr(status));
7968 /* Ensure st_size == 1000 */
7969 status = cli_posix_stat(cli1, fname, &sbuf);
7970 if (!NT_STATUS_IS_OK(status)) {
7971 printf("stat failed (%s)\n", nt_errstr(status));
7975 if (sbuf.st_ex_size != 1000) {
7976 printf("ftruncate - stat size (%u) != 1000\n", (unsigned int)sbuf.st_ex_size);
7980 status = cli_close(cli1, fnum1);
7981 if (!NT_STATUS_IS_OK(status)) {
7982 printf("close(2) failed (%s)\n", nt_errstr(status));
7986 /* Re-open with O_TRUNC. */
7987 status = cli_posix_open(cli1, fname, O_WRONLY|O_TRUNC, 0600, &fnum1);
7988 if (!NT_STATUS_IS_OK(status)) {
7989 printf("POSIX create of %s failed (%s)\n", fname, nt_errstr(status));
7993 /* Ensure st_size == 0 */
7994 status = cli_posix_stat(cli1, fname, &sbuf);
7995 if (!NT_STATUS_IS_OK(status)) {
7996 printf("stat failed (%s)\n", nt_errstr(status));
8000 if (sbuf.st_ex_size != 0) {
8001 printf("O_TRUNC - stat size (%u) != 0\n", (unsigned int)sbuf.st_ex_size);
8005 status = cli_close(cli1, fnum1);
8006 if (!NT_STATUS_IS_OK(status)) {
8007 printf("close failed (%s)\n", nt_errstr(status));
8011 status = cli_posix_unlink(cli1, fname);
8012 if (!NT_STATUS_IS_OK(status)) {
8013 printf("POSIX unlink of %s failed (%s)\n", fname, nt_errstr(status));
8017 status = cli_posix_open(cli1, dname, O_RDONLY, 0, &fnum1);
8018 if (!NT_STATUS_IS_OK(status)) {
8019 printf("POSIX open directory O_RDONLY of %s failed (%s)\n",
8020 dname, nt_errstr(status));
8024 cli_close(cli1, fnum1);
8026 /* What happens when we try and POSIX open a directory for write ? */
8027 status = cli_posix_open(cli1, dname, O_RDWR, 0, &fnum1);
8028 if (NT_STATUS_IS_OK(status)) {
8029 printf("POSIX open of directory %s succeeded, "
8030 "should have failed.\n",
8034 if (!check_both_error(__LINE__, status, ERRDOS, EISDIR,
8035 NT_STATUS_FILE_IS_A_DIRECTORY)) {
8040 /* Create the file. */
8041 status = cli_posix_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL,
8043 if (!NT_STATUS_IS_OK(status)) {
8044 printf("POSIX create of %s failed (%s)\n", fname, nt_errstr(status));
8048 /* Write some data into it. */
8049 status = cli_writeall(cli1, fnum1, 0, (const uint8_t *)"TEST DATA\n", 0, 10,
8051 if (!NT_STATUS_IS_OK(status)) {
8052 printf("cli_write failed: %s\n", nt_errstr(status));
8056 cli_close(cli1, fnum1);
8058 /* Now create a hardlink. */
8059 status = cli_posix_hardlink(cli1, fname, hname);
8060 if (!NT_STATUS_IS_OK(status)) {
8061 printf("POSIX hardlink of %s failed (%s)\n", hname, nt_errstr(status));
8065 /* Now create a symlink. */
8066 status = cli_posix_symlink(cli1, fname, sname);
8067 if (!NT_STATUS_IS_OK(status)) {
8068 printf("POSIX symlink of %s failed (%s)\n", sname, nt_errstr(status));
8072 /* Open the hardlink for read. */
8073 status = cli_posix_open(cli1, hname, O_RDONLY, 0, &fnum1);
8074 if (!NT_STATUS_IS_OK(status)) {
8075 printf("POSIX open of %s failed (%s)\n", hname, nt_errstr(status));
8079 status = cli_read(cli1, fnum1, buf, 0, 10, &nread);
8080 if (!NT_STATUS_IS_OK(status)) {
8081 printf("POSIX read of %s failed (%s)\n", hname,
8084 } else if (nread != 10) {
8085 printf("POSIX read of %s failed. Received %ld, expected %d\n",
8086 hname, (unsigned long)nread, 10);
8090 if (memcmp(buf, "TEST DATA\n", 10)) {
8091 printf("invalid data read from hardlink\n");
8095 /* Do a POSIX lock/unlock. */
8096 status = cli_posix_lock(cli1, fnum1, 0, 100, true, READ_LOCK);
8097 if (!NT_STATUS_IS_OK(status)) {
8098 printf("POSIX lock failed %s\n", nt_errstr(status));
8102 /* Punch a hole in the locked area. */
8103 status = cli_posix_unlock(cli1, fnum1, 10, 80);
8104 if (!NT_STATUS_IS_OK(status)) {
8105 printf("POSIX unlock failed %s\n", nt_errstr(status));
8109 cli_close(cli1, fnum1);
8111 /* Open the symlink for read - this should fail. A POSIX
8112 client should not be doing opens on a symlink. */
8113 status = cli_posix_open(cli1, sname, O_RDONLY, 0, &fnum1);
8114 if (NT_STATUS_IS_OK(status)) {
8115 printf("POSIX open of %s succeeded (should have failed)\n", sname);
8118 ok = check_both_error(
8119 __LINE__, status, ERRDOS, ERRbadpath,
8120 NT_STATUS_OBJECT_NAME_NOT_FOUND);
8122 printf("POSIX open of %s should have failed "
8123 "with NT_STATUS_OBJECT_NAME_NOT_FOUND, "
8124 "failed with %s instead.\n",
8125 sname, nt_errstr(status));
8129 status = cli_readlink(cli1, sname, talloc_tos(), &target, NULL, NULL);
8130 if (!NT_STATUS_IS_OK(status)) {
8131 printf("POSIX readlink on %s failed (%s)\n", sname, nt_errstr(status));
8135 if (strcmp(target, fname) != 0) {
8136 printf("POSIX readlink on %s failed to match name %s (read %s)\n",
8137 sname, fname, target);
8141 status = cli_posix_rmdir(cli1, dname);
8142 if (!NT_STATUS_IS_OK(status)) {
8143 printf("POSIX rmdir failed (%s)\n", nt_errstr(status));
8147 /* Check directory opens with a specific permission. */
8148 status = cli_posix_mkdir(cli1, dname, 0700);
8149 if (!NT_STATUS_IS_OK(status)) {
8150 printf("POSIX mkdir of %s failed (%s)\n", dname, nt_errstr(status));
8154 /* Ensure st_mode == 0700 */
8155 status = cli_posix_stat(cli1, dname, &sbuf);
8156 if (!NT_STATUS_IS_OK(status)) {
8157 printf("stat failed (%s)\n", nt_errstr(status));
8161 if ((sbuf.st_ex_mode & 07777) != 0700) {
8162 printf("posix_mkdir - bad permissions 0%o != 0700\n",
8163 (unsigned int)(sbuf.st_ex_mode & 07777));
8168 * Now create a Windows file, and attempt a POSIX unlink.
8169 * This should fail with a sharing violation but due to:
8171 * [Bug 9571] Unlink after open causes smbd to panic
8173 * ensure we've fixed the lock ordering violation.
8176 status = cli_ntcreate(cli1, fname_windows, 0,
8177 FILE_READ_DATA|FILE_WRITE_DATA, 0,
8178 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
8180 0x0, 0x0, &fnum2, NULL);
8181 if (!NT_STATUS_IS_OK(status)) {
8182 printf("Windows create of %s failed (%s)\n", fname_windows,
8187 /* Now try posix_unlink. */
8188 status = cli_posix_unlink(cli1, fname_windows);
8189 if (!NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
8190 printf("POSIX unlink of %s should fail "
8191 "with NT_STATUS_SHARING_VIOLATION "
8192 "got %s instead !\n",
8198 cli_close(cli1, fnum2);
8200 printf("Simple POSIX open test passed\n");
8205 if (fnum1 != (uint16_t)-1) {
8206 cli_close(cli1, fnum1);
8207 fnum1 = (uint16_t)-1;
8210 if (fnum2 != (uint16_t)-1) {
8211 cli_close(cli1, fnum2);
8212 fnum2 = (uint16_t)-1;
8215 cli_setatr(cli1, sname, 0, 0);
8216 cli_posix_unlink(cli1, sname);
8217 cli_setatr(cli1, hname, 0, 0);
8218 cli_posix_unlink(cli1, hname);
8219 cli_setatr(cli1, fname, 0, 0);
8220 cli_posix_unlink(cli1, fname);
8221 cli_setatr(cli1, dname, 0, 0);
8222 cli_posix_rmdir(cli1, dname);
8223 cli_setatr(cli1, fname_windows, 0, 0);
8224 cli_posix_unlink(cli1, fname_windows);
8226 if (!torture_close_connection(cli1)) {
8234 Test POSIX and Windows ACLs are rejected on symlinks.
8236 static bool run_acl_symlink_test(int dummy)
8238 static struct cli_state *cli;
8239 const char *fname = "posix_file";
8240 const char *sname = "posix_symlink";
8241 uint16_t fnum = (uint16_t)-1;
8242 bool correct = false;
8244 char *posix_acl = NULL;
8245 size_t posix_acl_len = 0;
8246 char *posix_acl_sym = NULL;
8247 size_t posix_acl_len_sym = 0;
8248 struct security_descriptor *sd = NULL;
8249 TALLOC_CTX *frame = NULL;
8251 frame = talloc_stackframe();
8253 printf("Starting acl symlink test\n");
8255 if (!torture_open_connection(&cli, 0)) {
8260 smbXcli_conn_set_sockopt(cli->conn, sockops);
8262 status = torture_setup_unix_extensions(cli);
8263 if (!NT_STATUS_IS_OK(status)) {
8268 cli_setatr(cli, fname, 0, 0);
8269 cli_posix_unlink(cli, fname);
8270 cli_setatr(cli, sname, 0, 0);
8271 cli_posix_unlink(cli, sname);
8273 status = cli_ntcreate(cli,
8276 READ_CONTROL_ACCESS,
8278 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
8285 if (!NT_STATUS_IS_OK(status)) {
8286 printf("cli_ntcreate of %s failed (%s)\n",
8292 /* Get the Windows ACL on the file. */
8293 status = cli_query_secdesc(cli,
8297 if (!NT_STATUS_IS_OK(status)) {
8298 printf("cli_query_secdesc failed (%s)\n",
8303 /* Get the POSIX ACL on the file. */
8304 status = cli_posix_getacl(cli,
8310 if (!NT_STATUS_IS_OK(status)) {
8311 printf("cli_posix_getacl failed (%s)\n",
8316 status = cli_close(cli, fnum);
8317 if (!NT_STATUS_IS_OK(status)) {
8318 printf("close failed (%s)\n", nt_errstr(status));
8321 fnum = (uint16_t)-1;
8323 /* Now create a symlink. */
8324 status = cli_posix_symlink(cli, fname, sname);
8325 if (!NT_STATUS_IS_OK(status)) {
8326 printf("cli_posix_symlink of %s -> %s failed (%s)\n",
8333 /* Open a handle on the symlink for SD set/get should fail. */
8334 status = cli_ntcreate(cli,
8337 READ_CONTROL_ACCESS|SEC_STD_WRITE_DAC,
8339 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
8346 if (NT_STATUS_IS_OK(status)) {
8347 printf("Symlink open for getsd/setsd of %s "
8348 "succeeded (should fail)\n",
8353 /* Try a stat-open on the symlink, should also fail. */
8354 status = cli_ntcreate(cli,
8357 FILE_READ_ATTRIBUTES|FILE_WRITE_ATTRIBUTES,
8359 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
8366 if (NT_STATUS_IS_OK(status)) {
8367 printf("Stat-open of symlink succeeded (should fail)\n");
8371 /* Get the POSIX ACL on the symlink pathname. Should fail. */
8372 status = cli_posix_getacl(cli,
8378 if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
8379 printf("cli_posix_getacl on a symlink gave %s. "
8380 "Should be NT_STATUS_ACCESS_DENIED.\n",
8385 /* Set the POSIX ACL on the symlink pathname. Should fail. */
8386 status = cli_posix_setacl(cli,
8391 if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
8392 printf("cli_posix_setacl on a symlink gave %s. "
8393 "Should be NT_STATUS_ACCESS_DENIED.\n",
8398 printf("ACL symlink test passed\n");
8403 if (fnum != (uint16_t)-1) {
8404 cli_close(cli, fnum);
8405 fnum = (uint16_t)-1;
8408 cli_setatr(cli, sname, 0, 0);
8409 cli_posix_unlink(cli, sname);
8410 cli_setatr(cli, fname, 0, 0);
8411 cli_posix_unlink(cli, fname);
8413 if (!torture_close_connection(cli)) {
8422 Test POSIX can delete a file containing streams.
8424 static bool run_posix_stream_delete(int dummy)
8426 struct cli_state *cli1 = NULL;
8427 struct cli_state *cli2 = NULL;
8428 const char *fname = "streamfile";
8429 const char *stream_fname = "streamfile:Zone.Identifier:$DATA";
8430 uint16_t fnum1 = (uint16_t)-1;
8431 bool correct = false;
8433 TALLOC_CTX *frame = NULL;
8435 frame = talloc_stackframe();
8437 printf("Starting POSIX stream delete test\n");
8439 if (!torture_open_connection(&cli1, 0) ||
8440 !torture_open_connection(&cli2, 1)) {
8445 smbXcli_conn_set_sockopt(cli1->conn, sockops);
8446 smbXcli_conn_set_sockopt(cli2->conn, sockops);
8448 status = torture_setup_unix_extensions(cli2);
8449 if (!NT_STATUS_IS_OK(status)) {
8453 cli_setatr(cli1, fname, 0, 0);
8454 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
8456 /* Create the file. */
8457 status = cli_ntcreate(cli1,
8460 READ_CONTROL_ACCESS,
8462 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
8469 if (!NT_STATUS_IS_OK(status)) {
8470 printf("cli_ntcreate of %s failed (%s)\n",
8476 status = cli_close(cli1, fnum1);
8477 if (!NT_STATUS_IS_OK(status)) {
8478 printf("cli_close of %s failed (%s)\n",
8483 fnum1 = (uint16_t)-1;
8485 /* Now create the stream. */
8486 status = cli_ntcreate(cli1,
8491 FILE_SHARE_READ|FILE_SHARE_WRITE,
8498 if (!NT_STATUS_IS_OK(status)) {
8499 printf("cli_ntcreate of %s failed (%s)\n",
8505 /* Leave the stream handle open... */
8507 /* POSIX unlink should fail. */
8508 status = cli_posix_unlink(cli2, fname);
8509 if (NT_STATUS_IS_OK(status)) {
8510 printf("cli_posix_unlink of %s succeeded, should have failed\n",
8515 if (!NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
8516 printf("cli_posix_unlink of %s failed with (%s) "
8517 "should have been NT_STATUS_SHARING_VIOLATION\n",
8523 /* Close the stream handle. */
8524 status = cli_close(cli1, fnum1);
8525 if (!NT_STATUS_IS_OK(status)) {
8526 printf("cli_close of %s failed (%s)\n",
8531 fnum1 = (uint16_t)-1;
8533 /* POSIX unlink after stream handle closed should succeed. */
8534 status = cli_posix_unlink(cli2, fname);
8535 if (!NT_STATUS_IS_OK(status)) {
8536 printf("cli_posix_unlink of %s failed (%s)\n",
8542 printf("POSIX stream delete test passed\n");
8547 if (fnum1 != (uint16_t)-1) {
8548 cli_close(cli1, fnum1);
8549 fnum1 = (uint16_t)-1;
8552 cli_setatr(cli1, fname, 0, 0);
8553 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
8555 if (!torture_close_connection(cli1)) {
8558 if (!torture_close_connection(cli2)) {
8567 Test setting EA's are rejected on symlinks.
8569 static bool run_ea_symlink_test(int dummy)
8571 static struct cli_state *cli;
8572 const char *fname = "posix_file_ea";
8573 const char *sname = "posix_symlink_ea";
8574 const char *ea_name = "testea_name";
8575 const char *ea_value = "testea_value";
8576 uint16_t fnum = (uint16_t)-1;
8577 bool correct = false;
8580 struct ea_struct *eas = NULL;
8581 TALLOC_CTX *frame = NULL;
8583 frame = talloc_stackframe();
8585 printf("Starting EA symlink test\n");
8587 if (!torture_open_connection(&cli, 0)) {
8592 smbXcli_conn_set_sockopt(cli->conn, sockops);
8594 status = torture_setup_unix_extensions(cli);
8595 if (!NT_STATUS_IS_OK(status)) {
8600 cli_setatr(cli, fname, 0, 0);
8601 cli_posix_unlink(cli, fname);
8602 cli_setatr(cli, sname, 0, 0);
8603 cli_posix_unlink(cli, sname);
8605 status = cli_ntcreate(cli,
8608 READ_CONTROL_ACCESS,
8610 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
8617 if (!NT_STATUS_IS_OK(status)) {
8618 printf("cli_ntcreate of %s failed (%s)\n",
8624 status = cli_close(cli, fnum);
8625 if (!NT_STATUS_IS_OK(status)) {
8626 printf("close failed (%s)\n",
8630 fnum = (uint16_t)-1;
8632 /* Set an EA on the path. */
8633 status = cli_set_ea_path(cli,
8637 strlen(ea_value)+1);
8639 if (!NT_STATUS_IS_OK(status)) {
8640 printf("cli_set_ea_path failed (%s)\n",
8645 /* Now create a symlink. */
8646 status = cli_posix_symlink(cli, fname, sname);
8647 if (!NT_STATUS_IS_OK(status)) {
8648 printf("cli_posix_symlink of %s -> %s failed (%s)\n",
8655 /* Get the EA list on the path. Should return value set. */
8656 status = cli_get_ea_list_path(cli,
8662 if (!NT_STATUS_IS_OK(status)) {
8663 printf("cli_get_ea_list_path failed (%s)\n",
8668 /* Ensure the EA we set is there. */
8669 for (i=0; i<num_eas; i++) {
8670 if (strcmp(eas[i].name, ea_name) == 0 &&
8671 eas[i].value.length == strlen(ea_value)+1 &&
8672 memcmp(eas[i].value.data,
8674 eas[i].value.length) == 0) {
8680 printf("Didn't find EA on pathname %s\n",
8688 /* Get the EA list on the symlink. Should return empty list. */
8689 status = cli_get_ea_list_path(cli,
8695 if (!NT_STATUS_IS_OK(status)) {
8696 printf("cli_get_ea_list_path failed (%s)\n",
8702 printf("cli_get_ea_list_path failed (%s)\n",
8707 /* Set an EA on the symlink. Should fail. */
8708 status = cli_set_ea_path(cli,
8712 strlen(ea_value)+1);
8714 if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
8715 printf("cli_set_ea_path on a symlink gave %s. "
8716 "Should be NT_STATUS_ACCESS_DENIED.\n",
8721 printf("EA symlink test passed\n");
8726 if (fnum != (uint16_t)-1) {
8727 cli_close(cli, fnum);
8728 fnum = (uint16_t)-1;
8731 cli_setatr(cli, sname, 0, 0);
8732 cli_posix_unlink(cli, sname);
8733 cli_setatr(cli, fname, 0, 0);
8734 cli_posix_unlink(cli, fname);
8736 if (!torture_close_connection(cli)) {
8745 Test POSIX locks are OFD-locks.
8747 static bool run_posix_ofd_lock_test(int dummy)
8749 static struct cli_state *cli;
8750 const char *fname = "posix_file";
8751 uint16_t fnum1 = (uint16_t)-1;
8752 uint16_t fnum2 = (uint16_t)-1;
8753 bool correct = false;
8755 TALLOC_CTX *frame = NULL;
8757 frame = talloc_stackframe();
8759 printf("Starting POSIX ofd-lock test\n");
8761 if (!torture_open_connection(&cli, 0)) {
8766 smbXcli_conn_set_sockopt(cli->conn, sockops);
8768 status = torture_setup_unix_extensions(cli);
8769 if (!NT_STATUS_IS_OK(status)) {
8774 cli_setatr(cli, fname, 0, 0);
8775 cli_posix_unlink(cli, fname);
8777 /* Open the file twice. */
8778 status = cli_posix_open(cli, fname, O_RDWR|O_CREAT|O_EXCL,
8780 if (!NT_STATUS_IS_OK(status)) {
8781 printf("First POSIX open of %s failed\n", fname);
8785 status = cli_posix_open(cli, fname, O_RDWR, 0, &fnum2);
8786 if (!NT_STATUS_IS_OK(status)) {
8787 printf("First POSIX open of %s failed\n", fname);
8791 /* Set a 0-50 lock on fnum1. */
8792 status = cli_posix_lock(cli, fnum1, 0, 50, false, WRITE_LOCK);
8793 if (!NT_STATUS_IS_OK(status)) {
8794 printf("POSIX lock (1) failed %s\n", nt_errstr(status));
8798 /* Set a 60-100 lock on fnum2. */
8799 status = cli_posix_lock(cli, fnum2, 60, 100, false, WRITE_LOCK);
8800 if (!NT_STATUS_IS_OK(status)) {
8801 printf("POSIX lock (2) failed %s\n", nt_errstr(status));
8805 /* close fnum1 - 0-50 lock should go away. */
8806 status = cli_close(cli, fnum1);
8807 if (!NT_STATUS_IS_OK(status)) {
8808 printf("close failed (%s)\n",
8812 fnum1 = (uint16_t)-1;
8814 /* Change the lock context. */
8815 cli_setpid(cli, cli_getpid(cli) + 1);
8817 /* Re-open fnum1. */
8818 status = cli_posix_open(cli, fname, O_RDWR, 0, &fnum1);
8819 if (!NT_STATUS_IS_OK(status)) {
8820 printf("Third POSIX open of %s failed\n", fname);
8824 /* 60-100 lock should still be there. */
8825 status = cli_posix_lock(cli, fnum1, 60, 100, false, WRITE_LOCK);
8826 if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
8827 printf("POSIX lock 60-100 not there %s\n", nt_errstr(status));
8831 /* 0-50 lock should be gone. */
8832 status = cli_posix_lock(cli, fnum1, 0, 50, false, WRITE_LOCK);
8833 if (!NT_STATUS_IS_OK(status)) {
8834 printf("POSIX lock 0-50 failed %s\n", nt_errstr(status));
8838 printf("POSIX OFD lock test passed\n");
8843 if (fnum1 != (uint16_t)-1) {
8844 cli_close(cli, fnum1);
8845 fnum1 = (uint16_t)-1;
8847 if (fnum2 != (uint16_t)-1) {
8848 cli_close(cli, fnum2);
8849 fnum2 = (uint16_t)-1;
8852 cli_setatr(cli, fname, 0, 0);
8853 cli_posix_unlink(cli, fname);
8855 if (!torture_close_connection(cli)) {
8863 struct posix_blocking_state {
8864 struct tevent_context *ev;
8865 struct cli_state *cli1;
8867 struct cli_state *cli2;
8873 static void posix_blocking_locked(struct tevent_req *subreq);
8874 static void posix_blocking_gotblocked(struct tevent_req *subreq);
8875 static void posix_blocking_gotecho(struct tevent_req *subreq);
8876 static void posix_blocking_unlocked(struct tevent_req *subreq);
8878 static struct tevent_req *posix_blocking_send(
8879 TALLOC_CTX *mem_ctx,
8880 struct tevent_context *ev,
8881 struct cli_state *cli1,
8883 struct cli_state *cli2,
8886 struct tevent_req *req = NULL, *subreq = NULL;
8887 struct posix_blocking_state *state = NULL;
8889 req = tevent_req_create(mem_ctx, &state, struct posix_blocking_state);
8895 state->fnum1 = fnum1;
8897 state->fnum2 = fnum2;
8899 subreq = cli_posix_lock_send(
8908 if (tevent_req_nomem(subreq, req)) {
8909 return tevent_req_post(req, ev);
8911 tevent_req_set_callback(subreq, posix_blocking_locked, req);
8915 static void posix_blocking_locked(struct tevent_req *subreq)
8917 struct tevent_req *req = tevent_req_callback_data(
8918 subreq, struct tevent_req);
8919 struct posix_blocking_state *state = tevent_req_data(
8920 req, struct posix_blocking_state);
8923 status = cli_posix_lock_recv(subreq);
8924 TALLOC_FREE(subreq);
8925 if (tevent_req_nterror(req, status)) {
8929 subreq = cli_posix_lock_send(
8938 if (tevent_req_nomem(subreq, req)) {
8941 tevent_req_set_callback(subreq, posix_blocking_gotblocked, req);
8943 /* Make sure the blocking request is delivered */
8944 subreq = cli_echo_send(
8949 (DATA_BLOB) { .data = (uint8_t *)state, .length = 1 });
8950 if (tevent_req_nomem(subreq, req)) {
8953 tevent_req_set_callback(subreq, posix_blocking_gotecho, req);
8956 static void posix_blocking_gotblocked(struct tevent_req *subreq)
8958 struct tevent_req *req = tevent_req_callback_data(
8959 subreq, struct tevent_req);
8960 struct posix_blocking_state *state = tevent_req_data(
8961 req, struct posix_blocking_state);
8964 status = cli_posix_lock_recv(subreq);
8965 TALLOC_FREE(subreq);
8966 if (tevent_req_nterror(req, status)) {
8969 if (!state->gotecho) {
8970 printf("blocked req got through before echo\n");
8971 tevent_req_nterror(req, NT_STATUS_INVALID_LOCK_SEQUENCE);
8974 tevent_req_done(req);
8977 static void posix_blocking_gotecho(struct tevent_req *subreq)
8979 struct tevent_req *req = tevent_req_callback_data(
8980 subreq, struct tevent_req);
8981 struct posix_blocking_state *state = tevent_req_data(
8982 req, struct posix_blocking_state);
8985 status = cli_echo_recv(subreq);
8986 TALLOC_FREE(subreq);
8987 if (tevent_req_nterror(req, status)) {
8990 if (state->gotblocked) {
8991 printf("blocked req got through before echo\n");
8992 tevent_req_nterror(req, NT_STATUS_INVALID_LOCK_SEQUENCE);
8995 state->gotecho = true;
8997 subreq = cli_posix_lock_send(
9006 if (tevent_req_nomem(subreq, req)) {
9009 tevent_req_set_callback(subreq, posix_blocking_unlocked, req);
9012 static void posix_blocking_unlocked(struct tevent_req *subreq)
9014 struct tevent_req *req = tevent_req_callback_data(
9015 subreq, struct tevent_req);
9018 status = cli_posix_lock_recv(subreq);
9019 TALLOC_FREE(subreq);
9020 if (tevent_req_nterror(req, status)) {
9023 /* tevent_req_done in posix_blocking_gotlocked */
9026 static NTSTATUS posix_blocking_recv(struct tevent_req *req)
9028 return tevent_req_simple_recv_ntstatus(req);
9031 static bool run_posix_blocking_lock(int dummy)
9033 struct tevent_context *ev = NULL;
9034 struct cli_state *cli1 = NULL, *cli2 = NULL;
9035 const char *fname = "posix_blocking";
9036 uint16_t fnum1 = UINT16_MAX, fnum2 = UINT16_MAX;
9037 struct tevent_req *req = NULL;
9042 printf("Starting posix blocking lock test\n");
9044 ev = samba_tevent_context_init(NULL);
9049 ok = torture_open_connection(&cli1, 0);
9053 ok = torture_open_connection(&cli2, 0);
9058 smbXcli_conn_set_sockopt(cli1->conn, sockops);
9060 status = torture_setup_unix_extensions(cli1);
9061 if (!NT_STATUS_IS_OK(status)) {
9065 status = torture_setup_unix_extensions(cli2);
9066 if (!NT_STATUS_IS_OK(status)) {
9070 cli_setatr(cli1, fname, 0, 0);
9071 cli_posix_unlink(cli1, fname);
9073 status = cli_posix_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL,
9075 if (!NT_STATUS_IS_OK(status)) {
9076 printf("First POSIX open of %s failed: %s\n",
9082 status = cli_posix_open(cli2, fname, O_RDWR, 0600, &fnum2);
9083 if (!NT_STATUS_IS_OK(status)) {
9084 printf("Second POSIX open of %s failed: %s\n",
9090 req = posix_blocking_send(ev, ev, cli1, fnum1, cli2, fnum2);
9092 printf("cli_posix_blocking failed\n");
9096 ok = tevent_req_poll_ntstatus(req, ev, &status);
9098 printf("tevent_req_poll_ntstatus failed: %s\n",
9102 status = posix_blocking_recv(req);
9104 if (!NT_STATUS_IS_OK(status)) {
9105 printf("posix_blocking_recv returned %s\n",
9113 if (fnum1 != UINT16_MAX) {
9114 cli_close(cli1, fnum1);
9117 if (fnum2 != UINT16_MAX) {
9118 cli_close(cli2, fnum2);
9123 cli_setatr(cli1, fname, 0, 0);
9124 cli_posix_unlink(cli1, fname);
9130 ok &= torture_close_connection(cli1);
9134 ok &= torture_close_connection(cli2);
9146 Test POSIX mkdir is case-sensitive.
9148 static bool run_posix_mkdir_test(int dummy)
9150 static struct cli_state *cli;
9151 const char *fname_foo = "POSIX_foo";
9152 const char *fname_foo_Foo = "POSIX_foo/Foo";
9153 const char *fname_foo_foo = "POSIX_foo/foo";
9154 const char *fname_Foo = "POSIX_Foo";
9155 const char *fname_Foo_Foo = "POSIX_Foo/Foo";
9156 const char *fname_Foo_foo = "POSIX_Foo/foo";
9157 bool correct = false;
9159 TALLOC_CTX *frame = NULL;
9160 uint16_t fnum = (uint16_t)-1;
9162 frame = talloc_stackframe();
9164 printf("Starting POSIX mkdir test\n");
9166 if (!torture_open_connection(&cli, 0)) {
9171 smbXcli_conn_set_sockopt(cli->conn, sockops);
9173 status = torture_setup_unix_extensions(cli);
9174 if (!NT_STATUS_IS_OK(status)) {
9179 cli_posix_rmdir(cli, fname_foo_foo);
9180 cli_posix_rmdir(cli, fname_foo_Foo);
9181 cli_posix_rmdir(cli, fname_foo);
9183 cli_posix_rmdir(cli, fname_Foo_foo);
9184 cli_posix_rmdir(cli, fname_Foo_Foo);
9185 cli_posix_rmdir(cli, fname_Foo);
9188 * Create a file POSIX_foo then try
9189 * and use it in a directory path by
9190 * doing mkdir POSIX_foo/bar.
9191 * The mkdir should fail with
9192 * NT_STATUS_OBJECT_PATH_NOT_FOUND
9195 status = cli_posix_open(cli,
9200 if (!NT_STATUS_IS_OK(status)) {
9201 printf("cli_posix_open of %s failed error %s\n",
9207 status = cli_posix_mkdir(cli, fname_foo_foo, 0777);
9208 if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_PATH_NOT_FOUND)) {
9209 printf("cli_posix_mkdir of %s should fail with "
9210 "NT_STATUS_OBJECT_PATH_NOT_FOUND got "
9217 status = cli_close(cli, fnum);
9218 if (!NT_STATUS_IS_OK(status)) {
9219 printf("cli_close failed %s\n", nt_errstr(status));
9222 fnum = (uint16_t)-1;
9224 status = cli_posix_unlink(cli, fname_foo);
9225 if (!NT_STATUS_IS_OK(status)) {
9226 printf("cli_posix_unlink of %s failed error %s\n",
9233 * Now we've deleted everything, posix_mkdir, posix_rmdir,
9234 * posix_open, posix_unlink, on
9235 * POSIX_foo/foo should return NT_STATUS_OBJECT_PATH_NOT_FOUND
9236 * not silently create POSIX_foo/foo.
9239 status = cli_posix_mkdir(cli, fname_foo_foo, 0777);
9240 if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_PATH_NOT_FOUND)) {
9241 printf("cli_posix_mkdir of %s should fail with "
9242 "NT_STATUS_OBJECT_PATH_NOT_FOUND got "
9249 status = cli_posix_rmdir(cli, fname_foo_foo);
9250 if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_PATH_NOT_FOUND)) {
9251 printf("cli_posix_rmdir of %s should fail with "
9252 "NT_STATUS_OBJECT_PATH_NOT_FOUND got "
9259 status = cli_posix_open(cli,
9264 if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_PATH_NOT_FOUND)) {
9265 printf("cli_posix_open of %s should fail with "
9266 "NT_STATUS_OBJECT_PATH_NOT_FOUND got "
9273 status = cli_posix_unlink(cli, fname_foo_foo);
9274 if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_PATH_NOT_FOUND)) {
9275 printf("cli_posix_unlink of %s should fail with "
9276 "NT_STATUS_OBJECT_PATH_NOT_FOUND got "
9283 status = cli_posix_mkdir(cli, fname_foo, 0777);
9284 if (!NT_STATUS_IS_OK(status)) {
9285 printf("cli_posix_mkdir of %s failed\n", fname_foo);
9289 status = cli_posix_mkdir(cli, fname_Foo, 0777);
9290 if (!NT_STATUS_IS_OK(status)) {
9291 printf("cli_posix_mkdir of %s failed\n", fname_Foo);
9295 status = cli_posix_mkdir(cli, fname_foo_foo, 0777);
9296 if (!NT_STATUS_IS_OK(status)) {
9297 printf("cli_posix_mkdir of %s failed\n", fname_foo_foo);
9301 status = cli_posix_mkdir(cli, fname_foo_Foo, 0777);
9302 if (!NT_STATUS_IS_OK(status)) {
9303 printf("cli_posix_mkdir of %s failed\n", fname_foo_Foo);
9307 status = cli_posix_mkdir(cli, fname_Foo_foo, 0777);
9308 if (!NT_STATUS_IS_OK(status)) {
9309 printf("cli_posix_mkdir of %s failed\n", fname_Foo_foo);
9313 status = cli_posix_mkdir(cli, fname_Foo_Foo, 0777);
9314 if (!NT_STATUS_IS_OK(status)) {
9315 printf("cli_posix_mkdir of %s failed\n", fname_Foo_Foo);
9319 printf("POSIX mkdir test passed\n");
9324 if (fnum != (uint16_t)-1) {
9325 cli_close(cli, fnum);
9326 fnum = (uint16_t)-1;
9329 cli_posix_rmdir(cli, fname_foo_foo);
9330 cli_posix_rmdir(cli, fname_foo_Foo);
9331 cli_posix_rmdir(cli, fname_foo);
9333 cli_posix_rmdir(cli, fname_Foo_foo);
9334 cli_posix_rmdir(cli, fname_Foo_Foo);
9335 cli_posix_rmdir(cli, fname_Foo);
9337 if (!torture_close_connection(cli)) {
9345 struct posix_acl_oplock_state {
9346 struct tevent_context *ev;
9347 struct cli_state *cli;
9353 static void posix_acl_oplock_got_break(struct tevent_req *req)
9355 struct posix_acl_oplock_state *state = tevent_req_callback_data(
9356 req, struct posix_acl_oplock_state);
9361 status = cli_smb_oplock_break_waiter_recv(req, &fnum, &level);
9363 if (!NT_STATUS_IS_OK(status)) {
9364 printf("cli_smb_oplock_break_waiter_recv returned %s\n",
9368 *state->got_break = true;
9370 req = cli_oplock_ack_send(state, state->ev, state->cli, fnum,
9373 printf("cli_oplock_ack_send failed\n");
9378 static void posix_acl_oplock_got_acl(struct tevent_req *req)
9380 struct posix_acl_oplock_state *state = tevent_req_callback_data(
9381 req, struct posix_acl_oplock_state);
9382 size_t ret_size = 0;
9383 char *ret_data = NULL;
9385 state->status = cli_posix_getacl_recv(req,
9390 if (!NT_STATUS_IS_OK(state->status)) {
9391 printf("cli_posix_getacl_recv returned %s\n",
9392 nt_errstr(state->status));
9394 *state->acl_ret = true;
9397 static bool run_posix_acl_oplock_test(int dummy)
9399 struct tevent_context *ev;
9400 struct cli_state *cli1, *cli2;
9401 struct tevent_req *oplock_req, *getacl_req;
9402 const char *fname = "posix_acl_oplock";
9404 int saved_use_oplocks = use_oplocks;
9406 bool correct = true;
9407 bool got_break = false;
9408 bool acl_ret = false;
9410 struct posix_acl_oplock_state *state;
9412 printf("starting posix_acl_oplock test\n");
9414 if (!torture_open_connection(&cli1, 0)) {
9415 use_level_II_oplocks = false;
9416 use_oplocks = saved_use_oplocks;
9420 if (!torture_open_connection(&cli2, 1)) {
9421 use_level_II_oplocks = false;
9422 use_oplocks = saved_use_oplocks;
9426 /* Setup posix on cli2 only. */
9427 status = torture_setup_unix_extensions(cli2);
9428 if (!NT_STATUS_IS_OK(status)) {
9432 smbXcli_conn_set_sockopt(cli1->conn, sockops);
9433 smbXcli_conn_set_sockopt(cli2->conn, sockops);
9435 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
9437 /* Create the file on the Windows connection. */
9438 status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
9440 if (!NT_STATUS_IS_OK(status)) {
9441 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
9445 status = cli_close(cli1, fnum);
9446 if (!NT_STATUS_IS_OK(status)) {
9447 printf("close1 failed (%s)\n", nt_errstr(status));
9451 cli1->use_oplocks = true;
9453 /* Open with oplock. */
9454 status = cli_ntcreate(cli1,
9458 FILE_ATTRIBUTE_NORMAL,
9459 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
9466 if (!NT_STATUS_IS_OK(status)) {
9467 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
9471 ev = samba_tevent_context_init(talloc_tos());
9473 printf("tevent_context_init failed\n");
9477 state = talloc_zero(ev, struct posix_acl_oplock_state);
9478 if (state == NULL) {
9479 printf("talloc failed\n");
9484 state->got_break = &got_break;
9485 state->acl_ret = &acl_ret;
9487 oplock_req = cli_smb_oplock_break_waiter_send(
9488 talloc_tos(), ev, cli1);
9489 if (oplock_req == NULL) {
9490 printf("cli_smb_oplock_break_waiter_send failed\n");
9493 tevent_req_set_callback(oplock_req, posix_acl_oplock_got_break, state);
9495 /* Get ACL on POSIX connection - should break oplock. */
9496 getacl_req = cli_posix_getacl_send(talloc_tos(),
9500 if (getacl_req == NULL) {
9501 printf("cli_posix_getacl_send failed\n");
9504 tevent_req_set_callback(getacl_req, posix_acl_oplock_got_acl, state);
9506 while (!got_break || !acl_ret) {
9508 ret = tevent_loop_once(ev);
9510 printf("tevent_loop_once failed: %s\n",
9516 if (!NT_STATUS_IS_OK(state->status)) {
9517 printf("getacl failed (%s)\n", nt_errstr(state->status));
9521 status = cli_close(cli1, fnum);
9522 if (!NT_STATUS_IS_OK(status)) {
9523 printf("close2 failed (%s)\n", nt_errstr(status));
9527 status = cli_unlink(cli1,
9529 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
9530 if (!NT_STATUS_IS_OK(status)) {
9531 printf("unlink failed (%s)\n", nt_errstr(status));
9535 if (!torture_close_connection(cli1)) {
9538 if (!torture_close_connection(cli2)) {
9546 printf("finished posix acl oplock test\n");
9551 static bool run_posix_acl_shareroot_test(int dummy)
9553 struct cli_state *cli;
9555 bool correct = false;
9556 char *posix_acl = NULL;
9557 size_t posix_acl_len = 0;
9558 uint16_t num_file_acls = 0;
9559 uint16_t num_dir_acls = 0;
9561 uint32_t expected_size = 0;
9562 bool got_user = false;
9563 bool got_group = false;
9564 bool got_other = false;
9565 TALLOC_CTX *frame = NULL;
9567 frame = talloc_stackframe();
9569 printf("starting posix_acl_shareroot test\n");
9571 if (!torture_open_connection(&cli, 0)) {
9576 smbXcli_conn_set_sockopt(cli->conn, sockops);
9578 status = torture_setup_unix_extensions(cli);
9579 if (!NT_STATUS_IS_OK(status)) {
9580 printf("Failed to setup unix extensions\n");
9584 /* Get the POSIX ACL on the root of the share. */
9585 status = cli_posix_getacl(cli,
9591 if (!NT_STATUS_IS_OK(status)) {
9592 printf("cli_posix_getacl of '.' failed (%s)\n",
9597 if (posix_acl_len < 6 ||
9598 SVAL(posix_acl,0) != SMB_POSIX_ACL_VERSION) {
9599 printf("getfacl ., unknown POSIX acl version %u.\n",
9600 (unsigned int)CVAL(posix_acl,0) );
9604 num_file_acls = SVAL(posix_acl,2);
9605 num_dir_acls = SVAL(posix_acl,4);
9606 expected_size = SMB_POSIX_ACL_HEADER_SIZE +
9607 SMB_POSIX_ACL_ENTRY_SIZE*
9608 (num_file_acls+num_dir_acls);
9610 if (posix_acl_len != expected_size) {
9611 printf("incorrect POSIX acl buffer size "
9612 "(should be %u, was %u).\n",
9613 (unsigned int)expected_size,
9614 (unsigned int)posix_acl_len);
9619 * We don't need to know what the ACL's are
9620 * we just need to know we have at least 3
9621 * file entries (u,g,o).
9624 for (i = 0; i < num_file_acls; i++) {
9625 unsigned char tagtype =
9627 SMB_POSIX_ACL_HEADER_SIZE+
9628 (i*SMB_POSIX_ACL_ENTRY_SIZE));
9631 case SMB_POSIX_ACL_USER_OBJ:
9634 case SMB_POSIX_ACL_GROUP_OBJ:
9637 case SMB_POSIX_ACL_OTHER:
9646 printf("Missing user entry\n");
9651 printf("Missing group entry\n");
9656 printf("Missing other entry\n");
9664 if (!torture_close_connection(cli)) {
9668 printf("finished posix acl shareroot test\n");
9674 static uint32_t open_attrs_table[] = {
9675 FILE_ATTRIBUTE_NORMAL,
9676 FILE_ATTRIBUTE_ARCHIVE,
9677 FILE_ATTRIBUTE_READONLY,
9678 FILE_ATTRIBUTE_HIDDEN,
9679 FILE_ATTRIBUTE_SYSTEM,
9681 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY,
9682 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN,
9683 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM,
9684 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN,
9685 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM,
9686 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM,
9688 FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN,
9689 FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM,
9690 FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM,
9691 FILE_ATTRIBUTE_HIDDEN,FILE_ATTRIBUTE_SYSTEM,
9694 struct trunc_open_results {
9697 uint32_t trunc_attr;
9698 uint32_t result_attr;
9701 static struct trunc_open_results attr_results[] = {
9702 { 0, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_ARCHIVE },
9703 { 1, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_ARCHIVE },
9704 { 2, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_READONLY, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY },
9705 { 16, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_ARCHIVE },
9706 { 17, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_ARCHIVE },
9707 { 18, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_READONLY, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY },
9708 { 51, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
9709 { 54, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
9710 { 56, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN },
9711 { 68, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
9712 { 71, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
9713 { 73, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM },
9714 { 99, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_HIDDEN,FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
9715 { 102, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
9716 { 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 },
9717 { 116, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
9718 { 119, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
9719 { 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 },
9720 { 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 },
9721 { 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 },
9722 { 227, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
9723 { 230, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
9724 { 232, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN },
9725 { 244, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
9726 { 247, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
9727 { 249, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM }
9730 static bool run_openattrtest(int dummy)
9732 static struct cli_state *cli1;
9733 const char *fname = "\\openattr.file";
9735 bool correct = True;
9737 unsigned int i, j, k, l;
9740 printf("starting open attr test\n");
9742 if (!torture_open_connection(&cli1, 0)) {
9746 smbXcli_conn_set_sockopt(cli1->conn, sockops);
9748 for (k = 0, i = 0; i < sizeof(open_attrs_table)/sizeof(uint32_t); i++) {
9749 cli_setatr(cli1, fname, 0, 0);
9750 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
9752 status = cli_ntcreate(cli1, fname, 0, FILE_WRITE_DATA,
9753 open_attrs_table[i], FILE_SHARE_NONE,
9754 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
9755 if (!NT_STATUS_IS_OK(status)) {
9756 printf("open %d (1) of %s failed (%s)\n", i, fname, nt_errstr(status));
9760 status = cli_close(cli1, fnum1);
9761 if (!NT_STATUS_IS_OK(status)) {
9762 printf("close %d (1) of %s failed (%s)\n", i, fname, nt_errstr(status));
9766 for (j = 0; j < sizeof(open_attrs_table)/sizeof(uint32_t); j++) {
9767 status = cli_ntcreate(cli1, fname, 0,
9768 FILE_READ_DATA|FILE_WRITE_DATA,
9769 open_attrs_table[j],
9770 FILE_SHARE_NONE, FILE_OVERWRITE,
9771 0, 0, &fnum1, NULL);
9772 if (!NT_STATUS_IS_OK(status)) {
9773 for (l = 0; l < sizeof(attr_results)/sizeof(struct trunc_open_results); l++) {
9774 if (attr_results[l].num == k) {
9775 printf("[%d] trunc open 0x%x -> 0x%x of %s failed - should have succeeded !(0x%x:%s)\n",
9776 k, open_attrs_table[i],
9777 open_attrs_table[j],
9778 fname, NT_STATUS_V(status), nt_errstr(status));
9783 if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
9784 printf("[%d] trunc open 0x%x -> 0x%x failed with wrong error code %s\n",
9785 k, open_attrs_table[i], open_attrs_table[j],
9790 printf("[%d] trunc open 0x%x -> 0x%x failed\n", k, open_attrs_table[i], open_attrs_table[j]);
9796 status = cli_close(cli1, fnum1);
9797 if (!NT_STATUS_IS_OK(status)) {
9798 printf("close %d (2) of %s failed (%s)\n", j, fname, nt_errstr(status));
9802 status = cli_getatr(cli1, fname, &attr, NULL, NULL);
9803 if (!NT_STATUS_IS_OK(status)) {
9804 printf("getatr(2) failed (%s)\n", nt_errstr(status));
9809 printf("[%d] getatr check [0x%x] trunc [0x%x] got attr 0x%x\n",
9810 k, open_attrs_table[i], open_attrs_table[j], attr );
9813 for (l = 0; l < sizeof(attr_results)/sizeof(struct trunc_open_results); l++) {
9814 if (attr_results[l].num == k) {
9815 if (attr != attr_results[l].result_attr ||
9816 open_attrs_table[i] != attr_results[l].init_attr ||
9817 open_attrs_table[j] != attr_results[l].trunc_attr) {
9818 printf("getatr check failed. [0x%x] trunc [0x%x] got attr 0x%x, should be 0x%x\n",
9819 open_attrs_table[i],
9820 open_attrs_table[j],
9822 attr_results[l].result_attr);
9832 cli_setatr(cli1, fname, 0, 0);
9833 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
9835 printf("open attr test %s.\n", correct ? "passed" : "failed");
9837 if (!torture_close_connection(cli1)) {
9843 static NTSTATUS list_fn(struct file_info *finfo,
9844 const char *name, void *state)
9846 int *matched = (int *)state;
9847 if (matched != NULL) {
9850 return NT_STATUS_OK;
9854 test directory listing speed
9856 static bool run_dirtest(int dummy)
9859 static struct cli_state *cli;
9861 struct timeval core_start;
9862 bool correct = True;
9865 printf("starting directory test\n");
9867 if (!torture_open_connection(&cli, 0)) {
9871 smbXcli_conn_set_sockopt(cli->conn, sockops);
9874 for (i=0;i<torture_numops;i++) {
9876 slprintf(fname, sizeof(fname), "\\%x", (int)random());
9877 if (!NT_STATUS_IS_OK(cli_openx(cli, fname, O_RDWR|O_CREAT, DENY_NONE, &fnum))) {
9878 fprintf(stderr,"Failed to open %s\n", fname);
9881 cli_close(cli, fnum);
9884 core_start = timeval_current();
9887 cli_list(cli, "a*.*", 0, list_fn, &matched);
9888 printf("Matched %d\n", matched);
9891 cli_list(cli, "b*.*", 0, list_fn, &matched);
9892 printf("Matched %d\n", matched);
9895 cli_list(cli, "xyzabc", 0, list_fn, &matched);
9896 printf("Matched %d\n", matched);
9898 printf("dirtest core %g seconds\n", timeval_elapsed(&core_start));
9901 for (i=0;i<torture_numops;i++) {
9903 slprintf(fname, sizeof(fname), "\\%x", (int)random());
9904 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
9907 if (!torture_close_connection(cli)) {
9911 printf("finished dirtest\n");
9916 static NTSTATUS del_fn(struct file_info *finfo, const char *mask,
9919 struct cli_state *pcli = (struct cli_state *)state;
9921 slprintf(fname, sizeof(fname), "\\LISTDIR\\%s", finfo->name);
9923 if (strcmp(finfo->name, ".") == 0 || strcmp(finfo->name, "..") == 0)
9924 return NT_STATUS_OK;
9926 if (finfo->attr & FILE_ATTRIBUTE_DIRECTORY) {
9927 if (!NT_STATUS_IS_OK(cli_rmdir(pcli, fname)))
9928 printf("del_fn: failed to rmdir %s\n,", fname );
9930 if (!NT_STATUS_IS_OK(cli_unlink(pcli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN)))
9931 printf("del_fn: failed to unlink %s\n,", fname );
9933 return NT_STATUS_OK;
9938 send a raw ioctl - used by the torture code
9940 static NTSTATUS cli_raw_ioctl(struct cli_state *cli,
9948 PUSH_LE_U16(vwv + 0, 0, fnum);
9949 PUSH_LE_U16(vwv + 1, 0, code >> 16);
9950 PUSH_LE_U16(vwv + 2, 0, (code & 0xFFFF));
9952 status = cli_smb(talloc_tos(),
9966 if (!NT_STATUS_IS_OK(status)) {
9969 *blob = data_blob_null;
9970 return NT_STATUS_OK;
9974 sees what IOCTLs are supported
9976 bool torture_ioctl_test(int dummy)
9978 static struct cli_state *cli;
9979 uint16_t device, function;
9981 const char *fname = "\\ioctl.dat";
9985 if (!torture_open_connection(&cli, 0)) {
9989 printf("starting ioctl test\n");
9991 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
9993 status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
9994 if (!NT_STATUS_IS_OK(status)) {
9995 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
9999 status = cli_raw_ioctl(cli, fnum, 0x2d0000 | (0x0420<<2), &blob);
10000 printf("ioctl device info: %s\n", nt_errstr(status));
10002 status = cli_raw_ioctl(cli, fnum, IOCTL_QUERY_JOB_INFO, &blob);
10003 printf("ioctl job info: %s\n", nt_errstr(status));
10005 for (device=0;device<0x100;device++) {
10006 printf("ioctl test with device = 0x%x\n", device);
10007 for (function=0;function<0x100;function++) {
10008 uint32_t code = (device<<16) | function;
10010 status = cli_raw_ioctl(cli, fnum, code, &blob);
10012 if (NT_STATUS_IS_OK(status)) {
10013 printf("ioctl 0x%x OK : %d bytes\n", (int)code,
10015 data_blob_free(&blob);
10020 if (!torture_close_connection(cli)) {
10029 tries variants of chkpath
10031 bool torture_chkpath_test(int dummy)
10033 static struct cli_state *cli;
10038 if (!torture_open_connection(&cli, 0)) {
10042 printf("starting chkpath test\n");
10044 /* cleanup from an old run */
10045 torture_deltree(cli, "\\chkpath.dir");
10047 status = cli_mkdir(cli, "\\chkpath.dir");
10048 if (!NT_STATUS_IS_OK(status)) {
10049 printf("mkdir1 failed : %s\n", nt_errstr(status));
10053 status = cli_mkdir(cli, "\\chkpath.dir\\dir2");
10054 if (!NT_STATUS_IS_OK(status)) {
10055 printf("mkdir2 failed : %s\n", nt_errstr(status));
10059 status = cli_openx(cli, "\\chkpath.dir\\foo.txt", O_RDWR|O_CREAT|O_EXCL,
10061 if (!NT_STATUS_IS_OK(status)) {
10062 printf("open1 failed (%s)\n", nt_errstr(status));
10065 cli_close(cli, fnum);
10067 status = cli_chkpath(cli, "\\chkpath.dir");
10068 if (!NT_STATUS_IS_OK(status)) {
10069 printf("chkpath1 failed: %s\n", nt_errstr(status));
10073 status = cli_chkpath(cli, "\\chkpath.dir\\dir2");
10074 if (!NT_STATUS_IS_OK(status)) {
10075 printf("chkpath2 failed: %s\n", nt_errstr(status));
10079 status = cli_chkpath(cli, "\\chkpath.dir\\foo.txt");
10080 if (!NT_STATUS_IS_OK(status)) {
10081 ret = check_error(__LINE__, status, ERRDOS, ERRbadpath,
10082 NT_STATUS_NOT_A_DIRECTORY);
10084 printf("* chkpath on a file should fail\n");
10088 status = cli_chkpath(cli, "\\chkpath.dir\\bar.txt");
10089 if (!NT_STATUS_IS_OK(status)) {
10090 ret = check_error(__LINE__, status, ERRDOS, ERRbadfile,
10091 NT_STATUS_OBJECT_NAME_NOT_FOUND);
10093 printf("* chkpath on a non existent file should fail\n");
10097 status = cli_chkpath(cli, "\\chkpath.dir\\dirxx\\bar.txt");
10098 if (!NT_STATUS_IS_OK(status)) {
10099 ret = check_error(__LINE__, status, ERRDOS, ERRbadpath,
10100 NT_STATUS_OBJECT_PATH_NOT_FOUND);
10102 printf("* chkpath on a non existent component should fail\n");
10106 torture_deltree(cli, "\\chkpath.dir");
10108 if (!torture_close_connection(cli)) {
10115 static bool run_eatest(int dummy)
10117 static struct cli_state *cli;
10118 const char *fname = "\\eatest.txt";
10119 bool correct = True;
10122 struct ea_struct *ea_list = NULL;
10123 TALLOC_CTX *mem_ctx = talloc_init("eatest");
10126 printf("starting eatest\n");
10128 if (!torture_open_connection(&cli, 0)) {
10129 talloc_destroy(mem_ctx);
10133 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
10135 status = cli_ntcreate(cli, fname, 0,
10136 FIRST_DESIRED_ACCESS, FILE_ATTRIBUTE_ARCHIVE,
10137 FILE_SHARE_NONE, FILE_OVERWRITE_IF,
10138 0x4044, 0, &fnum, NULL);
10139 if (!NT_STATUS_IS_OK(status)) {
10140 printf("open failed - %s\n", nt_errstr(status));
10141 talloc_destroy(mem_ctx);
10145 for (i = 0; i < 10; i++) {
10146 fstring ea_name, ea_val;
10148 slprintf(ea_name, sizeof(ea_name), "EA_%zu", i);
10149 memset(ea_val, (char)i+1, i+1);
10150 status = cli_set_ea_fnum(cli, fnum, ea_name, ea_val, i+1);
10151 if (!NT_STATUS_IS_OK(status)) {
10152 printf("ea_set of name %s failed - %s\n", ea_name,
10153 nt_errstr(status));
10154 talloc_destroy(mem_ctx);
10159 cli_close(cli, fnum);
10160 for (i = 0; i < 10; i++) {
10161 fstring ea_name, ea_val;
10163 slprintf(ea_name, sizeof(ea_name), "EA_%zu", i+10);
10164 memset(ea_val, (char)i+1, i+1);
10165 status = cli_set_ea_path(cli, fname, ea_name, ea_val, i+1);
10166 if (!NT_STATUS_IS_OK(status)) {
10167 printf("ea_set of name %s failed - %s\n", ea_name,
10168 nt_errstr(status));
10169 talloc_destroy(mem_ctx);
10174 status = cli_get_ea_list_path(cli, fname, mem_ctx, &num_eas, &ea_list);
10175 if (!NT_STATUS_IS_OK(status)) {
10176 printf("ea_get list failed - %s\n", nt_errstr(status));
10180 printf("num_eas = %d\n", (int)num_eas);
10182 if (num_eas != 20) {
10183 printf("Should be 20 EA's stored... failing.\n");
10187 for (i = 0; i < num_eas; i++) {
10188 printf("%zu: ea_name = %s. Val = ", i, ea_list[i].name);
10189 dump_data(0, ea_list[i].value.data,
10190 ea_list[i].value.length);
10193 /* Setting EA's to zero length deletes them. Test this */
10194 printf("Now deleting all EA's - case independent....\n");
10197 cli_set_ea_path(cli, fname, "", "", 0);
10199 for (i = 0; i < 20; i++) {
10201 slprintf(ea_name, sizeof(ea_name), "ea_%d", i);
10202 status = cli_set_ea_path(cli, fname, ea_name, "", 0);
10203 if (!NT_STATUS_IS_OK(status)) {
10204 printf("ea_set of name %s failed - %s\n", ea_name,
10205 nt_errstr(status));
10206 talloc_destroy(mem_ctx);
10212 status = cli_get_ea_list_path(cli, fname, mem_ctx, &num_eas, &ea_list);
10213 if (!NT_STATUS_IS_OK(status)) {
10214 printf("ea_get list failed - %s\n", nt_errstr(status));
10218 printf("num_eas = %d\n", (int)num_eas);
10219 for (i = 0; i < num_eas; i++) {
10220 printf("%zu: ea_name = %s. Val = ", i, ea_list[i].name);
10221 dump_data(0, ea_list[i].value.data,
10222 ea_list[i].value.length);
10225 if (num_eas != 0) {
10226 printf("deleting EA's failed.\n");
10230 /* Try and delete a non existent EA. */
10231 status = cli_set_ea_path(cli, fname, "foo", "", 0);
10232 if (!NT_STATUS_IS_OK(status)) {
10233 printf("deleting non-existent EA 'foo' should succeed. %s\n",
10234 nt_errstr(status));
10238 talloc_destroy(mem_ctx);
10239 if (!torture_close_connection(cli)) {
10246 static bool run_dirtest1(int dummy)
10249 static struct cli_state *cli;
10252 bool correct = True;
10254 printf("starting directory test\n");
10256 if (!torture_open_connection(&cli, 0)) {
10260 smbXcli_conn_set_sockopt(cli->conn, sockops);
10262 cli_list(cli, "\\LISTDIR\\*", 0, del_fn, cli);
10263 cli_list(cli, "\\LISTDIR\\*", FILE_ATTRIBUTE_DIRECTORY, del_fn, cli);
10264 cli_rmdir(cli, "\\LISTDIR");
10265 cli_mkdir(cli, "\\LISTDIR");
10267 /* Create 1000 files and 1000 directories. */
10268 for (i=0;i<1000;i++) {
10270 slprintf(fname, sizeof(fname), "\\LISTDIR\\f%d", i);
10271 if (!NT_STATUS_IS_OK(cli_ntcreate(cli, fname, 0, GENERIC_ALL_ACCESS, FILE_ATTRIBUTE_ARCHIVE,
10272 FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OVERWRITE_IF,
10273 0, 0, &fnum, NULL))) {
10274 fprintf(stderr,"Failed to open %s\n", fname);
10277 cli_close(cli, fnum);
10279 for (i=0;i<1000;i++) {
10281 slprintf(fname, sizeof(fname), "\\LISTDIR\\d%d", i);
10282 if (!NT_STATUS_IS_OK(cli_mkdir(cli, fname))) {
10283 fprintf(stderr,"Failed to open %s\n", fname);
10288 /* Now ensure that doing an old list sees both files and directories. */
10290 cli_list_old(cli, "\\LISTDIR\\*", FILE_ATTRIBUTE_DIRECTORY, list_fn, &num_seen);
10291 printf("num_seen = %d\n", num_seen );
10292 /* We should see 100 files + 1000 directories + . and .. */
10293 if (num_seen != 2002)
10296 /* Ensure if we have the "must have" bits we only see the
10297 * relevant entries.
10300 cli_list_old(cli, "\\LISTDIR\\*", (FILE_ATTRIBUTE_DIRECTORY<<8)|FILE_ATTRIBUTE_DIRECTORY, list_fn, &num_seen);
10301 printf("num_seen = %d\n", num_seen );
10302 if (num_seen != 1002)
10306 cli_list_old(cli, "\\LISTDIR\\*", (FILE_ATTRIBUTE_ARCHIVE<<8)|FILE_ATTRIBUTE_DIRECTORY, list_fn, &num_seen);
10307 printf("num_seen = %d\n", num_seen );
10308 if (num_seen != 1000)
10311 /* Delete everything. */
10312 cli_list(cli, "\\LISTDIR\\*", 0, del_fn, cli);
10313 cli_list(cli, "\\LISTDIR\\*", FILE_ATTRIBUTE_DIRECTORY, del_fn, cli);
10314 cli_rmdir(cli, "\\LISTDIR");
10317 printf("Matched %d\n", cli_list(cli, "a*.*", 0, list_fn, NULL));
10318 printf("Matched %d\n", cli_list(cli, "b*.*", 0, list_fn, NULL));
10319 printf("Matched %d\n", cli_list(cli, "xyzabc", 0, list_fn, NULL));
10322 if (!torture_close_connection(cli)) {
10326 printf("finished dirtest1\n");
10331 static bool run_error_map_extract(int dummy) {
10333 static struct cli_state *c_dos;
10334 static struct cli_state *c_nt;
10342 NTSTATUS nt_status;
10346 /* NT-Error connection */
10348 disable_spnego = true;
10349 if (!(c_nt = open_nbt_connection())) {
10350 disable_spnego = false;
10353 disable_spnego = false;
10355 status = smbXcli_negprot(c_nt->conn,
10363 if (!NT_STATUS_IS_OK(status)) {
10364 printf("%s rejected the NT-error negprot (%s)\n", host,
10365 nt_errstr(status));
10366 cli_shutdown(c_nt);
10370 status = cli_session_setup_anon(c_nt);
10371 if (!NT_STATUS_IS_OK(status)) {
10372 printf("%s rejected the NT-error initial session setup (%s)\n",host, nt_errstr(status));
10376 /* DOS-Error connection */
10378 disable_spnego = true;
10379 force_dos_errors = true;
10380 if (!(c_dos = open_nbt_connection())) {
10381 disable_spnego = false;
10382 force_dos_errors = false;
10385 disable_spnego = false;
10386 force_dos_errors = false;
10388 status = smbXcli_negprot(c_dos->conn,
10395 if (!NT_STATUS_IS_OK(status)) {
10396 printf("%s rejected the DOS-error negprot (%s)\n", host,
10397 nt_errstr(status));
10398 cli_shutdown(c_dos);
10402 status = cli_session_setup_anon(c_dos);
10403 if (!NT_STATUS_IS_OK(status)) {
10404 printf("%s rejected the DOS-error initial session setup (%s)\n",
10405 host, nt_errstr(status));
10409 c_nt->map_dos_errors = false;
10410 c_dos->map_dos_errors = false;
10412 for (error=(0xc0000000 | 0x1); error < (0xc0000000| 0xFFF); error++) {
10413 struct cli_credentials *user_creds = NULL;
10415 fstr_sprintf(user, "%X", error);
10417 user_creds = cli_session_creds_init(talloc_tos(),
10422 false, /* use_kerberos */
10423 false, /* fallback_after_kerberos */
10424 false, /* use_ccache */
10425 false); /* password_is_nt_hash */
10426 if (user_creds == NULL) {
10427 printf("cli_session_creds_init(%s) failed\n", user);
10431 status = cli_session_setup_creds(c_nt, user_creds);
10432 if (NT_STATUS_IS_OK(status)) {
10433 printf("/** Session setup succeeded. This shouldn't happen...*/\n");
10436 /* Case #1: 32-bit NT errors */
10437 if (!NT_STATUS_IS_DOS(status)) {
10438 nt_status = status;
10440 printf("/** Dos error on NT connection! (%s) */\n",
10441 nt_errstr(status));
10442 nt_status = NT_STATUS(0xc0000000);
10445 status = cli_session_setup_creds(c_dos, user_creds);
10446 if (NT_STATUS_IS_OK(status)) {
10447 printf("/** Session setup succeeded. This shouldn't happen...*/\n");
10450 /* Case #1: 32-bit NT errors */
10451 if (NT_STATUS_IS_DOS(status)) {
10452 printf("/** NT error on DOS connection! (%s) */\n",
10453 nt_errstr(status));
10454 errnum = errclass = 0;
10456 errclass = NT_STATUS_DOS_CLASS(status);
10457 errnum = NT_STATUS_DOS_CODE(status);
10460 if (NT_STATUS_V(nt_status) != error) {
10461 printf("/*\t{ This NT error code was 'sqashed'\n\t from %s to %s \n\t during the session setup }\n*/\n",
10462 get_nt_error_c_code(talloc_tos(), NT_STATUS(error)),
10463 get_nt_error_c_code(talloc_tos(), nt_status));
10466 printf("\t{%s,\t%s,\t%s},\n",
10467 smb_dos_err_class(errclass),
10468 smb_dos_err_name(errclass, errnum),
10469 get_nt_error_c_code(talloc_tos(), NT_STATUS(error)));
10471 TALLOC_FREE(user_creds);
10476 static bool run_sesssetup_bench(int dummy)
10478 static struct cli_state *c;
10479 const char *fname = "\\file.dat";
10484 if (!torture_open_connection(&c, 0)) {
10488 status = cli_ntcreate(c, fname, 0, GENERIC_ALL_ACCESS|DELETE_ACCESS,
10489 FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
10490 FILE_DELETE_ON_CLOSE, 0, &fnum, NULL);
10491 if (!NT_STATUS_IS_OK(status)) {
10492 d_printf("open %s failed: %s\n", fname, nt_errstr(status));
10496 for (i=0; i<torture_numops; i++) {
10497 status = cli_session_setup_creds(c, torture_creds);
10498 if (!NT_STATUS_IS_OK(status)) {
10499 d_printf("(%s) cli_session_setup_creds failed: %s\n",
10500 __location__, nt_errstr(status));
10504 d_printf("\r%d ", (int)cli_state_get_uid(c));
10506 status = cli_ulogoff(c);
10507 if (!NT_STATUS_IS_OK(status)) {
10508 d_printf("(%s) cli_ulogoff failed: %s\n",
10509 __location__, nt_errstr(status));
10517 static bool subst_test(const char *str, const char *user, const char *domain,
10518 uid_t uid, gid_t gid, const char *expected)
10521 bool result = true;
10523 subst = talloc_sub_specified(talloc_tos(), str, user, NULL, domain, uid, gid);
10525 if (strcmp(subst, expected) != 0) {
10526 printf("sub_specified(%s, %s, %s, %d, %d) returned [%s], expected "
10527 "[%s]\n", str, user, domain, (int)uid, (int)gid, subst,
10532 TALLOC_FREE(subst);
10536 static void chain1_open_completion(struct tevent_req *req)
10540 status = cli_openx_recv(req, &fnum);
10543 d_printf("cli_openx_recv returned %s: %d\n",
10545 NT_STATUS_IS_OK(status) ? fnum : -1);
10548 static void chain1_write_completion(struct tevent_req *req)
10552 status = cli_write_andx_recv(req, &written);
10555 d_printf("cli_write_andx_recv returned %s: %d\n",
10557 NT_STATUS_IS_OK(status) ? (int)written : -1);
10560 static void chain1_close_completion(struct tevent_req *req)
10563 bool *done = (bool *)tevent_req_callback_data_void(req);
10565 status = cli_close_recv(req);
10570 d_printf("cli_close returned %s\n", nt_errstr(status));
10573 static bool run_chain1(int dummy)
10575 struct cli_state *cli1;
10576 struct tevent_context *evt = samba_tevent_context_init(NULL);
10577 struct tevent_req *reqs[3], *smbreqs[3];
10579 const char *str = "foobar";
10580 const char *fname = "\\test_chain";
10583 printf("starting chain1 test\n");
10584 if (!torture_open_connection(&cli1, 0)) {
10588 smbXcli_conn_set_sockopt(cli1->conn, sockops);
10590 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
10592 reqs[0] = cli_openx_create(talloc_tos(), evt, cli1, fname,
10593 O_CREAT|O_RDWR, 0, &smbreqs[0]);
10594 if (reqs[0] == NULL) return false;
10595 tevent_req_set_callback(reqs[0], chain1_open_completion, NULL);
10598 reqs[1] = cli_write_andx_create(talloc_tos(), evt, cli1, 0, 0,
10599 (const uint8_t *)str, 0, strlen(str)+1,
10600 smbreqs, 1, &smbreqs[1]);
10601 if (reqs[1] == NULL) return false;
10602 tevent_req_set_callback(reqs[1], chain1_write_completion, NULL);
10604 reqs[2] = cli_smb1_close_create(talloc_tos(), evt, cli1, 0, &smbreqs[2]);
10605 if (reqs[2] == NULL) return false;
10606 tevent_req_set_callback(reqs[2], chain1_close_completion, &done);
10608 status = smb1cli_req_chain_submit(smbreqs, ARRAY_SIZE(smbreqs));
10609 if (!NT_STATUS_IS_OK(status)) {
10614 tevent_loop_once(evt);
10617 torture_close_connection(cli1);
10621 static void chain2_sesssetup_completion(struct tevent_req *req)
10624 status = cli_session_setup_guest_recv(req);
10625 d_printf("sesssetup returned %s\n", nt_errstr(status));
10628 static void chain2_tcon_completion(struct tevent_req *req)
10630 bool *done = (bool *)tevent_req_callback_data_void(req);
10632 status = cli_tcon_andx_recv(req);
10633 d_printf("tcon_and_x returned %s\n", nt_errstr(status));
10637 static bool run_chain2(int dummy)
10639 struct cli_state *cli1;
10640 struct tevent_context *evt = samba_tevent_context_init(NULL);
10641 struct tevent_req *reqs[2], *smbreqs[2];
10644 int flags = CLI_FULL_CONNECTION_FORCE_SMB1;
10646 printf("starting chain2 test\n");
10647 status = cli_start_connection(&cli1, lp_netbios_name(), host, NULL,
10648 port_to_use, SMB_SIGNING_DEFAULT, flags);
10649 if (!NT_STATUS_IS_OK(status)) {
10653 smbXcli_conn_set_sockopt(cli1->conn, sockops);
10655 reqs[0] = cli_session_setup_guest_create(talloc_tos(), evt, cli1,
10657 if (reqs[0] == NULL) return false;
10658 tevent_req_set_callback(reqs[0], chain2_sesssetup_completion, NULL);
10660 reqs[1] = cli_tcon_andx_create(talloc_tos(), evt, cli1, "IPC$",
10661 "?????", NULL, 0, &smbreqs[1]);
10662 if (reqs[1] == NULL) return false;
10663 tevent_req_set_callback(reqs[1], chain2_tcon_completion, &done);
10665 status = smb1cli_req_chain_submit(smbreqs, ARRAY_SIZE(smbreqs));
10666 if (!NT_STATUS_IS_OK(status)) {
10671 tevent_loop_once(evt);
10674 torture_close_connection(cli1);
10679 struct torture_createdel_state {
10680 struct tevent_context *ev;
10681 struct cli_state *cli;
10684 static void torture_createdel_created(struct tevent_req *subreq);
10685 static void torture_createdel_closed(struct tevent_req *subreq);
10687 static struct tevent_req *torture_createdel_send(TALLOC_CTX *mem_ctx,
10688 struct tevent_context *ev,
10689 struct cli_state *cli,
10692 struct tevent_req *req, *subreq;
10693 struct torture_createdel_state *state;
10695 req = tevent_req_create(mem_ctx, &state,
10696 struct torture_createdel_state);
10703 subreq = cli_ntcreate_send(
10704 state, ev, cli, name, 0,
10705 FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
10706 FILE_ATTRIBUTE_NORMAL,
10707 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
10708 FILE_OPEN_IF, FILE_DELETE_ON_CLOSE,
10709 SMB2_IMPERSONATION_IMPERSONATION, 0);
10711 if (tevent_req_nomem(subreq, req)) {
10712 return tevent_req_post(req, ev);
10714 tevent_req_set_callback(subreq, torture_createdel_created, req);
10718 static void torture_createdel_created(struct tevent_req *subreq)
10720 struct tevent_req *req = tevent_req_callback_data(
10721 subreq, struct tevent_req);
10722 struct torture_createdel_state *state = tevent_req_data(
10723 req, struct torture_createdel_state);
10727 status = cli_ntcreate_recv(subreq, &fnum, NULL);
10728 TALLOC_FREE(subreq);
10729 if (tevent_req_nterror(req, status)) {
10730 DEBUG(10, ("cli_ntcreate_recv returned %s\n",
10731 nt_errstr(status)));
10735 subreq = cli_close_send(state, state->ev, state->cli, fnum, 0);
10736 if (tevent_req_nomem(subreq, req)) {
10739 tevent_req_set_callback(subreq, torture_createdel_closed, req);
10742 static void torture_createdel_closed(struct tevent_req *subreq)
10744 struct tevent_req *req = tevent_req_callback_data(
10745 subreq, struct tevent_req);
10748 status = cli_close_recv(subreq);
10749 if (tevent_req_nterror(req, status)) {
10750 DEBUG(10, ("cli_close_recv returned %s\n", nt_errstr(status)));
10753 tevent_req_done(req);
10756 static NTSTATUS torture_createdel_recv(struct tevent_req *req)
10758 return tevent_req_simple_recv_ntstatus(req);
10761 struct torture_createdels_state {
10762 struct tevent_context *ev;
10763 struct cli_state *cli;
10764 const char *base_name;
10768 struct tevent_req **reqs;
10771 static void torture_createdels_done(struct tevent_req *subreq);
10773 static struct tevent_req *torture_createdels_send(TALLOC_CTX *mem_ctx,
10774 struct tevent_context *ev,
10775 struct cli_state *cli,
10776 const char *base_name,
10780 struct tevent_req *req;
10781 struct torture_createdels_state *state;
10784 req = tevent_req_create(mem_ctx, &state,
10785 struct torture_createdels_state);
10791 state->base_name = talloc_strdup(state, base_name);
10792 if (tevent_req_nomem(state->base_name, req)) {
10793 return tevent_req_post(req, ev);
10795 state->num_files = MAX(num_parallel, num_files);
10797 state->received = 0;
10799 state->reqs = talloc_array(state, struct tevent_req *, num_parallel);
10800 if (tevent_req_nomem(state->reqs, req)) {
10801 return tevent_req_post(req, ev);
10804 for (i=0; i<num_parallel; i++) {
10807 name = talloc_asprintf(state, "%s%8.8d", state->base_name,
10809 if (tevent_req_nomem(name, req)) {
10810 return tevent_req_post(req, ev);
10812 state->reqs[i] = torture_createdel_send(
10813 state->reqs, state->ev, state->cli, name);
10814 if (tevent_req_nomem(state->reqs[i], req)) {
10815 return tevent_req_post(req, ev);
10817 name = talloc_move(state->reqs[i], &name);
10818 tevent_req_set_callback(state->reqs[i],
10819 torture_createdels_done, req);
10825 static void torture_createdels_done(struct tevent_req *subreq)
10827 struct tevent_req *req = tevent_req_callback_data(
10828 subreq, struct tevent_req);
10829 struct torture_createdels_state *state = tevent_req_data(
10830 req, struct torture_createdels_state);
10831 size_t i, num_parallel = talloc_array_length(state->reqs);
10835 status = torture_createdel_recv(subreq);
10836 if (!NT_STATUS_IS_OK(status)){
10837 DEBUG(10, ("torture_createdel_recv returned %s\n",
10838 nt_errstr(status)));
10839 TALLOC_FREE(subreq);
10840 tevent_req_nterror(req, status);
10844 for (i=0; i<num_parallel; i++) {
10845 if (subreq == state->reqs[i]) {
10849 if (i == num_parallel) {
10850 DEBUG(10, ("received something we did not send\n"));
10851 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
10854 TALLOC_FREE(state->reqs[i]);
10856 if (state->sent >= state->num_files) {
10857 tevent_req_done(req);
10861 name = talloc_asprintf(state, "%s%8.8d", state->base_name,
10863 if (tevent_req_nomem(name, req)) {
10866 state->reqs[i] = torture_createdel_send(state->reqs, state->ev,
10868 if (tevent_req_nomem(state->reqs[i], req)) {
10871 name = talloc_move(state->reqs[i], &name);
10872 tevent_req_set_callback(state->reqs[i], torture_createdels_done, req);
10876 static NTSTATUS torture_createdels_recv(struct tevent_req *req)
10878 return tevent_req_simple_recv_ntstatus(req);
10881 struct swallow_notify_state {
10882 struct tevent_context *ev;
10883 struct cli_state *cli;
10885 uint32_t completion_filter;
10887 bool (*fn)(uint32_t action, const char *name, void *priv);
10891 static void swallow_notify_done(struct tevent_req *subreq);
10893 static struct tevent_req *swallow_notify_send(TALLOC_CTX *mem_ctx,
10894 struct tevent_context *ev,
10895 struct cli_state *cli,
10897 uint32_t completion_filter,
10899 bool (*fn)(uint32_t action,
10904 struct tevent_req *req, *subreq;
10905 struct swallow_notify_state *state;
10907 req = tevent_req_create(mem_ctx, &state,
10908 struct swallow_notify_state);
10914 state->fnum = fnum;
10915 state->completion_filter = completion_filter;
10916 state->recursive = recursive;
10918 state->priv = priv;
10920 subreq = cli_notify_send(state, state->ev, state->cli, state->fnum,
10921 0xffff, state->completion_filter,
10923 if (tevent_req_nomem(subreq, req)) {
10924 return tevent_req_post(req, ev);
10926 tevent_req_set_callback(subreq, swallow_notify_done, req);
10930 static void swallow_notify_done(struct tevent_req *subreq)
10932 struct tevent_req *req = tevent_req_callback_data(
10933 subreq, struct tevent_req);
10934 struct swallow_notify_state *state = tevent_req_data(
10935 req, struct swallow_notify_state);
10937 uint32_t i, num_changes;
10938 struct notify_change *changes;
10940 status = cli_notify_recv(subreq, state, &num_changes, &changes);
10941 TALLOC_FREE(subreq);
10942 if (!NT_STATUS_IS_OK(status)) {
10943 DEBUG(10, ("cli_notify_recv returned %s\n",
10944 nt_errstr(status)));
10945 tevent_req_nterror(req, status);
10949 for (i=0; i<num_changes; i++) {
10950 state->fn(changes[i].action, changes[i].name, state->priv);
10952 TALLOC_FREE(changes);
10954 subreq = cli_notify_send(state, state->ev, state->cli, state->fnum,
10955 0xffff, state->completion_filter,
10957 if (tevent_req_nomem(subreq, req)) {
10960 tevent_req_set_callback(subreq, swallow_notify_done, req);
10963 static bool print_notifies(uint32_t action, const char *name, void *priv)
10965 if (DEBUGLEVEL > 5) {
10966 d_printf("%d %s\n", (int)action, name);
10971 static void notify_bench_done(struct tevent_req *req)
10973 int *num_finished = (int *)tevent_req_callback_data_void(req);
10974 *num_finished += 1;
10977 static bool run_notify_bench(int dummy)
10979 const char *dname = "\\notify-bench";
10980 struct tevent_context *ev;
10983 struct tevent_req *req1;
10984 struct tevent_req *req2 = NULL;
10985 int i, num_unc_names;
10986 int num_finished = 0;
10988 printf("starting notify-bench test\n");
10990 if (use_multishare_conn) {
10992 unc_list = file_lines_load(multishare_conn_fname,
10993 &num_unc_names, 0, NULL);
10994 if (!unc_list || num_unc_names <= 0) {
10995 d_printf("Failed to load unc names list from '%s'\n",
10996 multishare_conn_fname);
10999 TALLOC_FREE(unc_list);
11004 ev = samba_tevent_context_init(talloc_tos());
11006 d_printf("tevent_context_init failed\n");
11010 for (i=0; i<num_unc_names; i++) {
11011 struct cli_state *cli;
11014 base_fname = talloc_asprintf(talloc_tos(), "%s\\file%3.3d.",
11016 if (base_fname == NULL) {
11020 if (!torture_open_connection(&cli, i)) {
11024 status = cli_ntcreate(cli, dname, 0,
11025 MAXIMUM_ALLOWED_ACCESS,
11026 0, FILE_SHARE_READ|FILE_SHARE_WRITE|
11028 FILE_OPEN_IF, FILE_DIRECTORY_FILE, 0,
11031 if (!NT_STATUS_IS_OK(status)) {
11032 d_printf("Could not create %s: %s\n", dname,
11033 nt_errstr(status));
11037 req1 = swallow_notify_send(talloc_tos(), ev, cli, dnum,
11038 FILE_NOTIFY_CHANGE_FILE_NAME |
11039 FILE_NOTIFY_CHANGE_DIR_NAME |
11040 FILE_NOTIFY_CHANGE_ATTRIBUTES |
11041 FILE_NOTIFY_CHANGE_LAST_WRITE,
11042 false, print_notifies, NULL);
11043 if (req1 == NULL) {
11044 d_printf("Could not create notify request\n");
11048 req2 = torture_createdels_send(talloc_tos(), ev, cli,
11049 base_fname, 10, torture_numops);
11050 if (req2 == NULL) {
11051 d_printf("Could not create createdels request\n");
11054 TALLOC_FREE(base_fname);
11056 tevent_req_set_callback(req2, notify_bench_done,
11060 while (num_finished < num_unc_names) {
11062 ret = tevent_loop_once(ev);
11064 d_printf("tevent_loop_once failed\n");
11069 if (!tevent_req_poll(req2, ev)) {
11070 d_printf("tevent_req_poll failed\n");
11073 status = torture_createdels_recv(req2);
11074 d_printf("torture_createdels_recv returned %s\n", nt_errstr(status));
11079 static bool run_mangle1(int dummy)
11081 struct cli_state *cli;
11082 const char *fname = "this_is_a_long_fname_to_be_mangled.txt";
11087 printf("starting mangle1 test\n");
11088 if (!torture_open_connection(&cli, 0)) {
11092 smbXcli_conn_set_sockopt(cli->conn, sockops);
11094 status = cli_ntcreate(cli, fname, 0, GENERIC_ALL_ACCESS|DELETE_ACCESS,
11095 FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
11096 0, 0, &fnum, NULL);
11097 if (!NT_STATUS_IS_OK(status)) {
11098 d_printf("open %s failed: %s\n", fname, nt_errstr(status));
11101 cli_close(cli, fnum);
11103 status = cli_qpathinfo_alt_name(cli, fname, alt_name);
11104 if (!NT_STATUS_IS_OK(status)) {
11105 d_printf("cli_qpathinfo_alt_name failed: %s\n",
11106 nt_errstr(status));
11109 d_printf("alt_name: %s\n", alt_name);
11111 status = cli_openx(cli, alt_name, O_RDONLY, DENY_NONE, &fnum);
11112 if (!NT_STATUS_IS_OK(status)) {
11113 d_printf("cli_openx(%s) failed: %s\n", alt_name,
11114 nt_errstr(status));
11117 cli_close(cli, fnum);
11119 status = cli_qpathinfo1(cli, alt_name, NULL, NULL, NULL, NULL, NULL);
11120 if (!NT_STATUS_IS_OK(status)) {
11121 d_printf("cli_qpathinfo1(%s) failed: %s\n", alt_name,
11122 nt_errstr(status));
11129 static NTSTATUS mangle_illegal_list_shortname_fn(struct file_info *f,
11133 if (f->short_name == NULL) {
11134 return NT_STATUS_OK;
11137 if (strlen(f->short_name) == 0) {
11138 return NT_STATUS_OK;
11141 printf("unexpected shortname: %s\n", f->short_name);
11143 return NT_STATUS_OBJECT_NAME_INVALID;
11146 static NTSTATUS mangle_illegal_list_name_fn(struct file_info *f,
11150 char *name = state;
11152 printf("name: %s\n", f->name);
11153 fstrcpy(name, f->name);
11154 return NT_STATUS_OK;
11157 static bool run_mangle_illegal(int dummy)
11159 struct cli_state *cli = NULL;
11160 struct cli_state *cli_posix = NULL;
11161 const char *fname = "\\MANGLE_ILLEGAL\\this_is_a_long_fname_to_be_mangled.txt";
11162 const char *illegal_fname = "MANGLE_ILLEGAL/foo:bar";
11163 char *mangled_path = NULL;
11169 printf("starting mangle-illegal test\n");
11171 if (!torture_open_connection(&cli, 0)) {
11175 smbXcli_conn_set_sockopt(cli->conn, sockops);
11177 if (!torture_open_connection(&cli_posix, 0)) {
11181 smbXcli_conn_set_sockopt(cli_posix->conn, sockops);
11183 status = torture_setup_unix_extensions(cli_posix);
11184 if (!NT_STATUS_IS_OK(status)) {
11188 cli_rmdir(cli, "\\MANGLE_ILLEGAL");
11189 status = cli_mkdir(cli, "\\MANGLE_ILLEGAL");
11190 if (!NT_STATUS_IS_OK(status)) {
11191 printf("mkdir1 failed : %s\n", nt_errstr(status));
11196 * Create a file with illegal NTFS characters and test that we
11197 * get a usable mangled name
11200 cli_setatr(cli_posix, illegal_fname, 0, 0);
11201 cli_posix_unlink(cli_posix, illegal_fname);
11203 status = cli_posix_open(cli_posix, illegal_fname, O_RDWR|O_CREAT|O_EXCL,
11205 if (!NT_STATUS_IS_OK(status)) {
11206 printf("POSIX create of %s failed (%s)\n",
11207 illegal_fname, nt_errstr(status));
11211 status = cli_close(cli_posix, fnum);
11212 if (!NT_STATUS_IS_OK(status)) {
11213 printf("close failed (%s)\n", nt_errstr(status));
11217 status = cli_list(cli, "\\MANGLE_ILLEGAL\\*", 0, mangle_illegal_list_name_fn, &name);
11218 if (!NT_STATUS_IS_OK(status)) {
11219 d_printf("cli_list failed: %s\n", nt_errstr(status));
11223 mangled_path = talloc_asprintf(talloc_tos(), "\\MANGLE_ILLEGAL\\%s", name);
11224 if (mangled_path == NULL) {
11228 status = cli_openx(cli, mangled_path, O_RDONLY, DENY_NONE, &fnum);
11229 if (!NT_STATUS_IS_OK(status)) {
11230 d_printf("cli_openx(%s) failed: %s\n", mangled_path, nt_errstr(status));
11231 TALLOC_FREE(mangled_path);
11234 TALLOC_FREE(mangled_path);
11235 cli_close(cli, fnum);
11237 cli_setatr(cli_posix, illegal_fname, 0, 0);
11238 cli_posix_unlink(cli_posix, illegal_fname);
11241 * Create a file with a long name and check that we got *no* short name.
11244 status = cli_ntcreate(cli, fname, 0, GENERIC_ALL_ACCESS|DELETE_ACCESS,
11245 FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
11246 0, 0, &fnum, NULL);
11247 if (!NT_STATUS_IS_OK(status)) {
11248 d_printf("open %s failed: %s\n", fname, nt_errstr(status));
11251 cli_close(cli, fnum);
11253 status = cli_list(cli, fname, 0, mangle_illegal_list_shortname_fn, &alt_name);
11254 if (!NT_STATUS_IS_OK(status)) {
11255 d_printf("cli_list failed\n");
11259 cli_unlink(cli, fname, 0);
11260 cli_rmdir(cli, "\\MANGLE_ILLEGAL");
11262 if (!torture_close_connection(cli_posix)) {
11266 if (!torture_close_connection(cli)) {
11273 static size_t null_source(uint8_t *buf, size_t n, void *priv)
11275 size_t *to_pull = (size_t *)priv;
11276 size_t thistime = *to_pull;
11278 thistime = MIN(thistime, n);
11279 if (thistime == 0) {
11283 memset(buf, 0, thistime);
11284 *to_pull -= thistime;
11288 static bool run_windows_write(int dummy)
11290 struct cli_state *cli1;
11294 const char *fname = "\\writetest.txt";
11295 struct timeval start_time;
11300 printf("starting windows_write test\n");
11301 if (!torture_open_connection(&cli1, 0)) {
11305 status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
11306 if (!NT_STATUS_IS_OK(status)) {
11307 printf("open failed (%s)\n", nt_errstr(status));
11311 smbXcli_conn_set_sockopt(cli1->conn, sockops);
11313 start_time = timeval_current();
11315 for (i=0; i<torture_numops; i++) {
11317 off_t start = i * torture_blocksize;
11318 size_t to_pull = torture_blocksize - 1;
11320 status = cli_writeall(cli1, fnum, 0, &c,
11321 start + torture_blocksize - 1, 1, NULL);
11322 if (!NT_STATUS_IS_OK(status)) {
11323 printf("cli_write failed: %s\n", nt_errstr(status));
11327 status = cli_push(cli1, fnum, 0, i * torture_blocksize, torture_blocksize,
11328 null_source, &to_pull);
11329 if (!NT_STATUS_IS_OK(status)) {
11330 printf("cli_push returned: %s\n", nt_errstr(status));
11335 seconds = timeval_elapsed(&start_time);
11336 kbytes = (double)torture_blocksize * torture_numops;
11339 printf("Wrote %d kbytes in %.2f seconds: %d kb/sec\n", (int)kbytes,
11340 (double)seconds, (int)(kbytes/seconds));
11344 cli_close(cli1, fnum);
11345 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
11346 torture_close_connection(cli1);
11350 static size_t calc_expected_return(struct cli_state *cli, size_t len_requested)
11352 size_t max_pdu = 0x1FFFF;
11354 if (cli->server_posix_capabilities & CIFS_UNIX_LARGE_READ_CAP) {
11355 max_pdu = 0xFFFFFF;
11358 if (smb1cli_conn_signing_is_active(cli->conn)) {
11362 if (smb1cli_conn_encryption_on(cli->conn)) {
11363 max_pdu = CLI_BUFFER_SIZE;
11366 if ((len_requested & 0xFFFF0000) == 0xFFFF0000) {
11367 len_requested &= 0xFFFF;
11370 return MIN(len_requested,
11371 max_pdu - (MIN_SMB_SIZE + VWV(12) + 1 /* padding byte */));
11374 static bool check_read_call(struct cli_state *cli,
11377 size_t len_requested)
11380 struct tevent_req *subreq = NULL;
11381 ssize_t len_read = 0;
11382 size_t len_expected = 0;
11383 struct tevent_context *ev = NULL;
11385 ev = samba_tevent_context_init(talloc_tos());
11390 subreq = cli_read_andx_send(talloc_tos(),
11397 if (!tevent_req_poll_ntstatus(subreq, ev, &status)) {
11401 status = cli_read_andx_recv(subreq, &len_read, &buf);
11402 if (!NT_STATUS_IS_OK(status)) {
11403 d_printf("cli_read_andx_recv failed: %s\n", nt_errstr(status));
11407 TALLOC_FREE(subreq);
11410 len_expected = calc_expected_return(cli, len_requested);
11412 if (len_expected > 0x10000 && len_read == 0x10000) {
11413 /* Windows servers only return a max of 0x10000,
11414 doesn't matter if you set CAP_LARGE_READX in
11415 the client sessionsetupX call or not. */
11416 d_printf("Windows server - returned 0x10000 on a read of 0x%x\n",
11417 (unsigned int)len_requested);
11418 } else if (len_read != len_expected) {
11419 d_printf("read of 0x%x failed: got 0x%x, expected 0x%x\n",
11420 (unsigned int)len_requested,
11421 (unsigned int)len_read,
11422 (unsigned int)len_expected);
11425 d_printf("Correct read reply.\n");
11431 /* Test large readX variants. */
11432 static bool large_readx_tests(struct cli_state *cli,
11436 /* A read of 0xFFFF0001 should *always* return 1 byte. */
11437 if (check_read_call(cli, fnum, buf, 0xFFFF0001) == false) {
11440 /* A read of 0x10000 should return 0x10000 bytes. */
11441 if (check_read_call(cli, fnum, buf, 0x10000) == false) {
11444 /* A read of 0x10000 should return 0x10001 bytes. */
11445 if (check_read_call(cli, fnum, buf, 0x10001) == false) {
11448 /* A read of 0x1FFFF - (MIN_SMB_SIZE + VWV(12) should return
11449 the requested number of bytes. */
11450 if (check_read_call(cli, fnum, buf, 0x1FFFF - (MIN_SMB_SIZE + VWV(12))) == false) {
11453 /* A read of 1MB should return 1MB bytes (on Samba). */
11454 if (check_read_call(cli, fnum, buf, 0x100000) == false) {
11458 if (check_read_call(cli, fnum, buf, 0x20001) == false) {
11461 if (check_read_call(cli, fnum, buf, 0x22000001) == false) {
11464 if (check_read_call(cli, fnum, buf, 0xFFFE0001) == false) {
11470 static bool run_large_readx(int dummy)
11472 uint8_t *buf = NULL;
11473 struct cli_state *cli1 = NULL;
11474 struct cli_state *cli2 = NULL;
11475 bool correct = false;
11476 const char *fname = "\\large_readx.dat";
11478 uint16_t fnum1 = UINT16_MAX;
11479 uint32_t normal_caps = 0;
11480 size_t file_size = 20*1024*1024;
11481 TALLOC_CTX *frame = talloc_stackframe();
11485 enum smb_signing_setting signing_setting;
11486 enum protocol_types protocol;
11490 .signing_setting = SMB_SIGNING_IF_REQUIRED,
11491 .protocol = PROTOCOL_NT1,
11493 .name = "NT1 - SIGNING_REQUIRED",
11494 .signing_setting = SMB_SIGNING_REQUIRED,
11495 .protocol = PROTOCOL_NT1,
11499 printf("starting large_readx test\n");
11501 if (!torture_open_connection(&cli1, 0)) {
11505 normal_caps = smb1cli_conn_capabilities(cli1->conn);
11507 if (!(normal_caps & CAP_LARGE_READX)) {
11508 d_printf("Server doesn't have CAP_LARGE_READX 0x%x\n",
11509 (unsigned int)normal_caps);
11513 /* Create a file of size 4MB. */
11514 status = cli_ntcreate(cli1, fname, 0, GENERIC_ALL_ACCESS,
11515 FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
11516 0, 0, &fnum1, NULL);
11518 if (!NT_STATUS_IS_OK(status)) {
11519 d_printf("open %s failed: %s\n", fname, nt_errstr(status));
11523 /* Write file_size bytes. */
11524 buf = talloc_zero_array(frame, uint8_t, file_size);
11529 status = cli_writeall(cli1,
11536 if (!NT_STATUS_IS_OK(status)) {
11537 d_printf("cli_writeall failed: %s\n", nt_errstr(status));
11541 status = cli_close(cli1, fnum1);
11542 if (!NT_STATUS_IS_OK(status)) {
11543 d_printf("cli_close failed: %s\n", nt_errstr(status));
11547 fnum1 = UINT16_MAX;
11549 for (i=0; i < ARRAY_SIZE(runs); i++) {
11550 enum smb_signing_setting saved_signing_setting = signing_state;
11551 uint16_t fnum2 = -1;
11554 (runs[i].signing_setting == SMB_SIGNING_REQUIRED))
11556 d_printf("skip[%u] - %s\n", (unsigned)i, runs[i].name);
11560 d_printf("run[%u] - %s\n", (unsigned)i, runs[i].name);
11562 signing_state = runs[i].signing_setting;
11563 cli2 = open_nbt_connection();
11564 signing_state = saved_signing_setting;
11565 if (cli2 == NULL) {
11569 status = smbXcli_negprot(cli2->conn,
11576 if (!NT_STATUS_IS_OK(status)) {
11580 status = cli_session_setup_creds(cli2, torture_creds);
11581 if (!NT_STATUS_IS_OK(status)) {
11585 status = cli_tree_connect(cli2,
11589 if (!NT_STATUS_IS_OK(status)) {
11593 cli_set_timeout(cli2, 120000); /* set a really long timeout (2 minutes) */
11595 normal_caps = smb1cli_conn_capabilities(cli2->conn);
11597 if (!(normal_caps & CAP_LARGE_READX)) {
11598 d_printf("Server doesn't have CAP_LARGE_READX 0x%x\n",
11599 (unsigned int)normal_caps);
11604 if (force_cli_encryption(cli2, share) == false) {
11607 } else if (SERVER_HAS_UNIX_CIFS(cli2)) {
11608 uint16_t major, minor;
11609 uint32_t caplow, caphigh;
11611 status = cli_unix_extensions_version(cli2,
11613 &caplow, &caphigh);
11614 if (!NT_STATUS_IS_OK(status)) {
11619 status = cli_ntcreate(cli2, fname, 0, FILE_READ_DATA,
11620 FILE_ATTRIBUTE_NORMAL, 0, FILE_OPEN,
11621 0, 0, &fnum2, NULL);
11622 if (!NT_STATUS_IS_OK(status)) {
11623 d_printf("Second open %s failed: %s\n", fname, nt_errstr(status));
11627 /* All reads must return less than file_size bytes. */
11628 if (!large_readx_tests(cli2, fnum2, buf)) {
11632 status = cli_close(cli2, fnum2);
11633 if (!NT_STATUS_IS_OK(status)) {
11634 d_printf("cli_close failed: %s\n", nt_errstr(status));
11639 if (!torture_close_connection(cli2)) {
11646 printf("Success on large_readx test\n");
11651 if (!torture_close_connection(cli2)) {
11657 if (fnum1 != UINT16_MAX) {
11658 status = cli_close(cli1, fnum1);
11659 if (!NT_STATUS_IS_OK(status)) {
11660 d_printf("cli_close failed: %s\n", nt_errstr(status));
11662 fnum1 = UINT16_MAX;
11665 status = cli_unlink(cli1, fname,
11666 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
11667 if (!NT_STATUS_IS_OK(status)) {
11668 printf("unlink failed (%s)\n", nt_errstr(status));
11671 if (!torture_close_connection(cli1)) {
11676 TALLOC_FREE(frame);
11678 printf("finished large_readx test\n");
11682 static NTSTATUS msdfs_attribute_list_fn(struct file_info *finfo,
11684 void *private_data)
11686 uint32_t *p_attr = (uint32_t *)private_data;
11688 if (strequal(finfo->name, test_filename)) {
11689 *p_attr = finfo->attr;
11692 return NT_STATUS_OK;
11695 static bool run_msdfs_attribute(int dummy)
11697 static struct cli_state *cli;
11698 bool correct = false;
11702 printf("Starting MSDFS-ATTRIBUTE test\n");
11704 if (test_filename == NULL || test_filename[0] == '\0') {
11705 printf("MSDFS-ATTRIBUTE test "
11706 "needs -f filename-of-msdfs-link\n");
11711 * NB. We use torture_open_connection_flags() not
11712 * torture_open_connection() as the latter forces
11715 if (!torture_open_connection_flags(&cli, 0, 0)) {
11719 smbXcli_conn_set_sockopt(cli->conn, sockops);
11721 status = cli_list(cli,
11723 FILE_ATTRIBUTE_DIRECTORY,
11724 msdfs_attribute_list_fn,
11727 if (!NT_STATUS_IS_OK(status)) {
11728 printf("cli_list failed with %s\n",
11729 nt_errstr(status));
11732 if ((attr & FILE_ATTRIBUTE_REPARSE_POINT) == 0) {
11733 printf("file %s should have "
11734 "FILE_ATTRIBUTE_REPARSE_POINT set. attr = 0x%x\n",
11736 (unsigned int)attr);
11740 if ((attr & FILE_ATTRIBUTE_DIRECTORY) == 0) {
11741 printf("file %s should have "
11742 "FILE_ATTRIBUTE_DIRECTORY set. attr = 0x%x\n",
11744 (unsigned int)attr);
11752 torture_close_connection(cli);
11756 static bool run_cli_echo(int dummy)
11758 struct cli_state *cli;
11761 printf("starting cli_echo test\n");
11762 if (!torture_open_connection(&cli, 0)) {
11765 smbXcli_conn_set_sockopt(cli->conn, sockops);
11767 status = cli_echo(cli, 5, data_blob_const("hello", 5));
11769 d_printf("cli_echo returned %s\n", nt_errstr(status));
11771 torture_close_connection(cli);
11772 return NT_STATUS_IS_OK(status);
11775 static int splice_status(off_t written, void *priv)
11780 static bool run_cli_splice(int dummy)
11782 uint8_t *buf = NULL;
11783 struct cli_state *cli1 = NULL;
11784 bool correct = false;
11785 const char *fname_src = "\\splice_src.dat";
11786 const char *fname_dst = "\\splice_dst.dat";
11788 uint16_t fnum1 = UINT16_MAX;
11789 uint16_t fnum2 = UINT16_MAX;
11790 size_t file_size = 2*1024*1024;
11791 size_t splice_size = 1*1024*1024 + 713;
11792 uint8_t digest1[16], digest2[16];
11795 TALLOC_CTX *frame = talloc_stackframe();
11797 printf("starting cli_splice test\n");
11799 if (!torture_open_connection(&cli1, 0)) {
11803 cli_unlink(cli1, fname_src,
11804 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
11805 cli_unlink(cli1, fname_dst,
11806 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
11808 /* Create a file */
11809 status = cli_ntcreate(cli1, fname_src, 0, GENERIC_ALL_ACCESS,
11810 FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
11811 0, 0, &fnum1, NULL);
11813 if (!NT_STATUS_IS_OK(status)) {
11814 d_printf("open %s failed: %s\n", fname_src, nt_errstr(status));
11818 /* Write file_size bytes - must be bigger than splice_size. */
11819 buf = talloc_zero_array(frame, uint8_t, file_size);
11821 d_printf("talloc_fail\n");
11825 /* Fill it with random numbers. */
11826 generate_random_buffer(buf, file_size);
11828 /* MD5 the first 1MB + 713 bytes. */
11829 gnutls_hash_fast(GNUTLS_DIG_MD5,
11834 status = cli_writeall(cli1,
11841 if (!NT_STATUS_IS_OK(status)) {
11842 d_printf("cli_writeall failed: %s\n", nt_errstr(status));
11846 status = cli_ntcreate(cli1, fname_dst, 0, GENERIC_ALL_ACCESS,
11847 FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
11848 0, 0, &fnum2, NULL);
11850 if (!NT_STATUS_IS_OK(status)) {
11851 d_printf("open %s failed: %s\n", fname_dst, nt_errstr(status));
11855 /* Now splice 1MB + 713 bytes. */
11856 status = cli_splice(cli1,
11867 if (!NT_STATUS_IS_OK(status)) {
11868 d_printf("cli_splice failed: %s\n", nt_errstr(status));
11872 /* Clear the old buffer. */
11873 memset(buf, '\0', file_size);
11875 /* Read the new file. */
11876 status = cli_read(cli1, fnum2, (char *)buf, 0, splice_size, &nread);
11877 if (!NT_STATUS_IS_OK(status)) {
11878 d_printf("cli_read failed: %s\n", nt_errstr(status));
11881 if (nread != splice_size) {
11882 d_printf("bad read of 0x%x, should be 0x%x\n",
11883 (unsigned int)nread,
11884 (unsigned int)splice_size);
11888 /* MD5 the first 1MB + 713 bytes. */
11889 gnutls_hash_fast(GNUTLS_DIG_MD5,
11894 /* Must be the same. */
11895 if (memcmp(digest1, digest2, 16) != 0) {
11896 d_printf("bad MD5 compare\n");
11901 printf("Success on cli_splice test\n");
11906 if (fnum1 != UINT16_MAX) {
11907 cli_close(cli1, fnum1);
11909 if (fnum2 != UINT16_MAX) {
11910 cli_close(cli1, fnum2);
11913 cli_unlink(cli1, fname_src,
11914 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
11915 cli_unlink(cli1, fname_dst,
11916 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
11918 if (!torture_close_connection(cli1)) {
11923 TALLOC_FREE(frame);
11927 static bool run_uid_regression_test(int dummy)
11929 static struct cli_state *cli;
11932 bool correct = True;
11933 struct smbXcli_tcon *tcon_copy = NULL;
11936 printf("starting uid regression test\n");
11938 if (!torture_open_connection(&cli, 0)) {
11942 smbXcli_conn_set_sockopt(cli->conn, sockops);
11944 /* Ok - now save then logoff our current user. */
11945 old_vuid = cli_state_get_uid(cli);
11947 status = cli_ulogoff(cli);
11948 if (!NT_STATUS_IS_OK(status)) {
11949 d_printf("(%s) cli_ulogoff failed: %s\n",
11950 __location__, nt_errstr(status));
11955 cli_state_set_uid(cli, old_vuid);
11957 /* Try an operation. */
11958 status = cli_mkdir(cli, "\\uid_reg_test");
11959 if (NT_STATUS_IS_OK(status)) {
11960 d_printf("(%s) cli_mkdir succeeded\n",
11965 /* Should be bad uid. */
11966 if (!check_error(__LINE__, status, ERRSRV, ERRbaduid,
11967 NT_STATUS_USER_SESSION_DELETED)) {
11973 old_cnum = cli_state_get_tid(cli);
11975 * This is an SMB1-only test.
11976 * Copy the tcon, not "save/restore".
11978 * In SMB1 the cli_tdis() below frees
11979 * cli->smb1.tcon so we need a copy
11980 * of the struct to put back for the
11981 * second tdis call with invalid vuid.
11983 * This is a test-only hack. Real client code
11984 * uses cli_state_save_tcon_share()/cli_state_restore_tcon_share().
11986 tcon_copy = smbXcli_tcon_copy(cli, cli->smb1.tcon);
11987 if (tcon_copy == NULL) {
11992 /* Now try a SMBtdis with the invalid vuid set to zero. */
11993 cli_state_set_uid(cli, 0);
11995 /* This should succeed. */
11996 status = cli_tdis(cli);
11998 if (NT_STATUS_IS_OK(status)) {
11999 d_printf("First tdis with invalid vuid should succeed.\n");
12001 d_printf("First tdis failed (%s)\n", nt_errstr(status));
12003 cli->smb1.tcon = tcon_copy;
12007 cli->smb1.tcon = tcon_copy;
12008 cli_state_set_uid(cli, old_vuid);
12009 cli_state_set_tid(cli, old_cnum);
12011 /* This should fail. */
12012 status = cli_tdis(cli);
12013 if (NT_STATUS_IS_OK(status)) {
12014 d_printf("Second tdis with invalid vuid should fail - succeeded instead !.\n");
12018 /* Should be bad tid. */
12019 if (!check_error(__LINE__, status, ERRSRV, ERRinvnid,
12020 NT_STATUS_NETWORK_NAME_DELETED)) {
12026 cli_rmdir(cli, "\\uid_reg_test");
12035 static const char *illegal_chars = "*\\/?<>|\":";
12036 static char force_shortname_chars[] = " +,.[];=\177";
12038 static NTSTATUS shortname_del_fn(struct file_info *finfo,
12039 const char *mask, void *state)
12041 struct cli_state *pcli = (struct cli_state *)state;
12043 NTSTATUS status = NT_STATUS_OK;
12045 slprintf(fname, sizeof(fname), "\\shortname\\%s", finfo->name);
12047 if (strcmp(finfo->name, ".") == 0 || strcmp(finfo->name, "..") == 0)
12048 return NT_STATUS_OK;
12050 if (finfo->attr & FILE_ATTRIBUTE_DIRECTORY) {
12051 status = cli_rmdir(pcli, fname);
12052 if (!NT_STATUS_IS_OK(status)) {
12053 printf("del_fn: failed to rmdir %s\n,", fname );
12056 status = cli_unlink(pcli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
12057 if (!NT_STATUS_IS_OK(status)) {
12058 printf("del_fn: failed to unlink %s\n,", fname );
12070 static NTSTATUS shortname_list_fn(struct file_info *finfo,
12071 const char *name, void *state)
12073 struct sn_state *s = (struct sn_state *)state;
12077 printf("shortname list: i = %d, name = |%s|, shortname = |%s|\n",
12078 i, finfo->name, finfo->short_name);
12081 if (strchr(force_shortname_chars, i)) {
12082 if (!finfo->short_name) {
12083 /* Shortname not created when it should be. */
12084 d_printf("(%s) ERROR: Shortname was not created for file %s containing %d\n",
12085 __location__, finfo->name, i);
12088 } else if (finfo->short_name){
12089 /* Shortname created when it should not be. */
12090 d_printf("(%s) ERROR: Shortname %s was created for file %s\n",
12091 __location__, finfo->short_name, finfo->name);
12095 return NT_STATUS_OK;
12098 static bool run_shortname_test(int dummy)
12100 static struct cli_state *cli;
12101 bool correct = True;
12107 printf("starting shortname test\n");
12109 if (!torture_open_connection(&cli, 0)) {
12113 smbXcli_conn_set_sockopt(cli->conn, sockops);
12115 cli_list(cli, "\\shortname\\*", 0, shortname_del_fn, cli);
12116 cli_list(cli, "\\shortname\\*", FILE_ATTRIBUTE_DIRECTORY, shortname_del_fn, cli);
12117 cli_rmdir(cli, "\\shortname");
12119 status = cli_mkdir(cli, "\\shortname");
12120 if (!NT_STATUS_IS_OK(status)) {
12121 d_printf("(%s) cli_mkdir of \\shortname failed: %s\n",
12122 __location__, nt_errstr(status));
12127 if (strlcpy(fname, "\\shortname\\", sizeof(fname)) >= sizeof(fname)) {
12131 if (strlcat(fname, "test .txt", sizeof(fname)) >= sizeof(fname)) {
12138 for (i = 32; i < 128; i++) {
12139 uint16_t fnum = (uint16_t)-1;
12143 if (strchr(illegal_chars, i)) {
12148 status = cli_ntcreate(cli, fname, 0, GENERIC_ALL_ACCESS, FILE_ATTRIBUTE_NORMAL,
12149 FILE_SHARE_READ|FILE_SHARE_WRITE,
12150 FILE_OVERWRITE_IF, 0, 0, &fnum, NULL);
12151 if (!NT_STATUS_IS_OK(status)) {
12152 d_printf("(%s) cli_nt_create of %s failed: %s\n",
12153 __location__, fname, nt_errstr(status));
12157 cli_close(cli, fnum);
12160 status = cli_list(cli, "\\shortname\\test*.*", 0,
12161 shortname_list_fn, &s);
12162 if (s.matched != 1) {
12163 d_printf("(%s) failed to list %s: %s\n",
12164 __location__, fname, nt_errstr(status));
12169 status = cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
12170 if (!NT_STATUS_IS_OK(status)) {
12171 d_printf("(%s) failed to delete %s: %s\n",
12172 __location__, fname, nt_errstr(status));
12185 cli_list(cli, "\\shortname\\*", 0, shortname_del_fn, cli);
12186 cli_list(cli, "\\shortname\\*", FILE_ATTRIBUTE_DIRECTORY, shortname_del_fn, cli);
12187 cli_rmdir(cli, "\\shortname");
12188 torture_close_connection(cli);
12192 TLDAPRC callback_code;
12194 static void pagedsearch_cb(struct tevent_req *req)
12197 struct tldap_message *msg;
12200 rc = tldap_search_paged_recv(req, talloc_tos(), &msg);
12201 if (!TLDAP_RC_IS_SUCCESS(rc)) {
12202 d_printf("tldap_search_paged_recv failed: %s\n",
12203 tldap_rc2string(rc));
12204 callback_code = rc;
12207 if (tldap_msg_type(msg) != TLDAP_RES_SEARCH_ENTRY) {
12211 if (!tldap_entry_dn(msg, &dn)) {
12212 d_printf("tldap_entry_dn failed\n");
12215 d_printf("%s\n", dn);
12219 enum tldap_extended_val {
12226 * Construct an extended dn control with either no value, 0 or 1
12228 * No value and 0 are equivalent (non-hyphenated GUID)
12229 * 1 has the hyphenated GUID
12231 static struct tldap_control *
12232 tldap_build_extended_control(enum tldap_extended_val val)
12234 struct tldap_control empty_control;
12235 struct asn1_data *data;
12237 ZERO_STRUCT(empty_control);
12239 if (val != EXTENDED_NONE) {
12240 data = asn1_init(talloc_tos(), ASN1_MAX_TREE_DEPTH);
12246 if (!asn1_push_tag(data, ASN1_SEQUENCE(0))) {
12250 if (!asn1_write_Integer(data, (int)val)) {
12254 if (!asn1_pop_tag(data)) {
12258 if (!asn1_blob(data, &empty_control.value)) {
12263 empty_control.oid = "1.2.840.113556.1.4.529";
12264 empty_control.critical = true;
12266 return tldap_add_control(talloc_tos(), NULL, 0, &empty_control);
12270 static bool tldap_test_dn_guid_format(struct tldap_context *ld, const char *basedn,
12271 enum tldap_extended_val control_val)
12273 struct tldap_control *control = tldap_build_extended_control(control_val);
12275 struct tldap_message **msg;
12278 rc = tldap_search(ld, basedn, TLDAP_SCOPE_BASE,
12279 "(objectClass=*)", NULL, 0, 0,
12281 0, 0, 0, 0, talloc_tos(), &msg);
12282 if (!TLDAP_RC_IS_SUCCESS(rc)) {
12283 d_printf("tldap_search for domain DN failed: %s\n",
12284 tldap_errstr(talloc_tos(), ld, rc));
12288 if (!tldap_entry_dn(msg[0], &dn)) {
12289 d_printf("tldap_search domain DN fetch failed: %s\n",
12290 tldap_errstr(talloc_tos(), ld, rc));
12294 d_printf("%s\n", dn);
12297 uint32_t time_mid, time_hi_and_version;
12298 uint32_t clock_seq[2];
12302 switch (control_val) {
12303 case EXTENDED_NONE:
12304 case EXTENDED_ZERO:
12306 * When reading GUIDs with hyphens, scanf will treat
12307 * hyphen as a hex character (and counts as part of the
12308 * width). This creates leftover GUID string which we
12309 * check will for with 'next' and closing '>'.
12311 if (12 == sscanf(dn, "<GUID=%08x%04x%04x%02x%02x%02x%02x%02x%02x%02x%02x>%c",
12312 &time_low, &time_mid,
12313 &time_hi_and_version, &clock_seq[0],
12314 &clock_seq[1], &node[0], &node[1],
12315 &node[2], &node[3], &node[4],
12316 &node[5], &next)) {
12317 /* This GUID is good */
12319 d_printf("GUID format in control (no hyphens) doesn't match output\n");
12325 if (12 == sscanf(dn,
12326 "<GUID=%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x>%c",
12327 &time_low, &time_mid,
12328 &time_hi_and_version, &clock_seq[0],
12329 &clock_seq[1], &node[0], &node[1],
12330 &node[2], &node[3], &node[4],
12331 &node[5], &next)) {
12332 /* This GUID is good */
12334 d_printf("GUID format in control (with hyphens) doesn't match output\n");
12347 static bool run_tldap(int dummy)
12349 struct tldap_context *ld;
12353 struct sockaddr_storage addr;
12354 struct tevent_context *ev;
12355 struct tevent_req *req;
12357 const char *filter;
12358 struct loadparm_context *lp_ctx = NULL;
12359 int tcp_port = 389;
12360 bool use_tls = false;
12361 bool use_starttls = false;
12362 int wrap_flags = -1;
12363 uint32_t gensec_features = 0;
12365 lp_ctx = loadparm_init_s3(talloc_tos(), loadparm_s3_helpers());
12367 wrap_flags = lpcfg_client_ldap_sasl_wrapping(lp_ctx);
12369 if (wrap_flags & ADS_AUTH_SASL_LDAPS) {
12372 } else if (wrap_flags & ADS_AUTH_SASL_STARTTLS) {
12374 use_starttls = true;
12376 if (wrap_flags & ADS_AUTH_SASL_SEAL) {
12377 gensec_features |= GENSEC_FEATURE_SEAL;
12379 if (wrap_flags & ADS_AUTH_SASL_SIGN) {
12380 gensec_features |= GENSEC_FEATURE_SIGN;
12383 if (gensec_features != 0) {
12384 gensec_features |= GENSEC_FEATURE_LDAP_STYLE;
12387 if (!resolve_name(host, &addr, 0, false)) {
12388 d_printf("could not find host %s\n", host);
12391 status = open_socket_out(&addr, tcp_port, 9999, &fd);
12392 if (!NT_STATUS_IS_OK(status)) {
12393 d_printf("open_socket_out failed: %s\n", nt_errstr(status));
12397 ld = tldap_context_create(talloc_tos(), fd);
12400 d_printf("tldap_context_create failed\n");
12404 if (use_tls && !tldap_has_tls_tstream(ld)) {
12405 tldap_set_starttls_needed(ld, use_starttls);
12407 rc = tldap_tls_connect(ld, lp_ctx, host);
12408 if (!TLDAP_RC_IS_SUCCESS(rc)) {
12409 DBG_ERR("tldap_tls_connect(%s) failed: %s\n",
12410 host, tldap_errstr(talloc_tos(), ld, rc));
12415 rc = tldap_fetch_rootdse(ld);
12416 if (!TLDAP_RC_IS_SUCCESS(rc)) {
12417 d_printf("tldap_fetch_rootdse failed: %s\n",
12418 tldap_errstr(talloc_tos(), ld, rc));
12422 basedn = tldap_talloc_single_attribute(
12423 tldap_rootdse(ld), "defaultNamingContext", talloc_tos());
12424 if (basedn == NULL) {
12425 d_printf("no defaultNamingContext\n");
12428 d_printf("defaultNamingContext: %s\n", basedn);
12430 ev = samba_tevent_context_init(talloc_tos());
12432 d_printf("tevent_context_init failed\n");
12436 rc = tldap_gensec_bind(ld, torture_creds, "ldap", host, NULL,
12437 lp_ctx, gensec_features);
12438 if (!TLDAP_RC_IS_SUCCESS(rc)) {
12439 d_printf("tldap_gensec_bind failed\n");
12443 callback_code = TLDAP_SUCCESS;
12445 req = tldap_search_paged_send(talloc_tos(), ev, ld, basedn,
12446 TLDAP_SCOPE_SUB, "(objectclass=*)",
12448 NULL, 0, NULL, 0, 0, 0, 0, 5);
12450 d_printf("tldap_search_paged_send failed\n");
12453 tevent_req_set_callback(req, pagedsearch_cb, NULL);
12455 tevent_req_poll(req, ev);
12459 rc = callback_code;
12461 if (!TLDAP_RC_IS_SUCCESS(rc)) {
12462 d_printf("tldap_search with paging failed: %s\n",
12463 tldap_errstr(talloc_tos(), ld, rc));
12467 /* test search filters against rootDSE */
12468 filter = "(&(|(name=samba)(nextRid<=10000000)(usnChanged>=10)(samba~=ambas)(!(name=s*m*a)))"
12469 "(|(name:=samba)(name:dn:2.5.13.5:=samba)(:dn:2.5.13.5:=samba)(!(name=*samba))))";
12471 rc = tldap_search(ld, "", TLDAP_SCOPE_BASE, filter,
12472 NULL, 0, 0, NULL, 0, NULL, 0, 0, 0, 0,
12473 talloc_tos(), NULL);
12474 if (!TLDAP_RC_IS_SUCCESS(rc)) {
12475 d_printf("tldap_search with complex filter failed: %s\n",
12476 tldap_errstr(talloc_tos(), ld, rc));
12481 * Tests to check for regression of:
12483 * https://bugzilla.samba.org/show_bug.cgi?id=14029
12485 * TLDAP used here to pick apart the original string DN (with GUID)
12487 if (!tldap_test_dn_guid_format(ld, basedn, EXTENDED_NONE)) {
12488 d_printf("tldap_search with extended dn (no val) failed: %s\n",
12489 tldap_errstr(talloc_tos(), ld, rc));
12492 if (!tldap_test_dn_guid_format(ld, basedn, EXTENDED_ZERO)) {
12493 d_printf("tldap_search with extended dn (0) failed: %s\n",
12494 tldap_errstr(talloc_tos(), ld, rc));
12497 if (!tldap_test_dn_guid_format(ld, basedn, EXTENDED_ONE)) {
12498 d_printf("tldap_search with extended dn (1) failed: %s\n",
12499 tldap_errstr(talloc_tos(), ld, rc));
12507 /* Torture test to ensure no regression of :
12508 https://bugzilla.samba.org/show_bug.cgi?id=7084
12511 static bool run_dir_createtime(int dummy)
12513 struct cli_state *cli;
12514 const char *dname = "\\testdir_createtime";
12515 const char *fname = "\\testdir_createtime\\testfile";
12517 struct timespec create_time;
12518 struct timespec create_time1;
12523 if (!torture_open_connection(&cli, 0)) {
12527 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
12528 /* Ensure ino is zero, SMB2 gets a real one. */
12531 /* Ensure ino is -1, SMB1 never gets a real one. */
12532 ino = (uint64_t)-1;
12535 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
12536 cli_rmdir(cli, dname);
12538 status = cli_mkdir(cli, dname);
12539 if (!NT_STATUS_IS_OK(status)) {
12540 printf("mkdir failed: %s\n", nt_errstr(status));
12544 status = cli_qpathinfo2(cli,
12554 if (!NT_STATUS_IS_OK(status)) {
12555 printf("cli_qpathinfo2 returned %s\n",
12556 nt_errstr(status));
12560 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
12561 /* SMB2 should always return an inode. */
12563 printf("SMB2 bad inode (0)\n");
12567 /* SMB1 must always return zero here. */
12569 printf("SMB1 bad inode (!0)\n");
12574 /* Sleep 3 seconds, then create a file. */
12577 status = cli_openx(cli, fname, O_RDWR | O_CREAT | O_EXCL,
12579 if (!NT_STATUS_IS_OK(status)) {
12580 printf("cli_openx failed: %s\n", nt_errstr(status));
12584 status = cli_qpathinfo2(cli,
12594 if (!NT_STATUS_IS_OK(status)) {
12595 printf("cli_qpathinfo2 (2) returned %s\n",
12596 nt_errstr(status));
12600 if (timespec_compare(&create_time1, &create_time)) {
12601 printf("run_dir_createtime: create time was updated (error)\n");
12603 printf("run_dir_createtime: create time was not updated (correct)\n");
12609 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
12610 cli_rmdir(cli, dname);
12611 if (!torture_close_connection(cli)) {
12618 static bool run_streamerror(int dummy)
12620 struct cli_state *cli;
12621 const char *dname = "\\testdir_streamerror";
12622 const char *streamname =
12623 "testdir_streamerror:{4c8cc155-6c1e-11d1-8e41-00c04fb9386d}:$DATA";
12625 time_t change_time, access_time, write_time;
12631 if (!torture_open_connection(&cli, 0)) {
12635 torture_deltree(cli, dname);
12637 status = cli_mkdir(cli, dname);
12638 if (!NT_STATUS_IS_OK(status)) {
12639 printf("mkdir failed: %s\n", nt_errstr(status));
12643 status = cli_qpathinfo1(cli, streamname, &change_time, &access_time,
12644 &write_time, &size, &attr);
12645 if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
12646 printf("pathinfo returned %s, expected "
12647 "NT_STATUS_OBJECT_NAME_NOT_FOUND\n",
12648 nt_errstr(status));
12652 status = cli_ntcreate(cli, streamname, 0x16,
12653 FILE_READ_DATA|FILE_READ_EA|
12654 FILE_READ_ATTRIBUTES|READ_CONTROL_ACCESS,
12655 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ,
12656 FILE_OPEN, 0, 0, &fnum, NULL);
12658 if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
12659 printf("ntcreate returned %s, expected "
12660 "NT_STATUS_OBJECT_NAME_NOT_FOUND\n",
12661 nt_errstr(status));
12666 cli_rmdir(cli, dname);
12670 struct pidtest_state {
12676 static void pid_echo_done(struct tevent_req *subreq);
12678 static struct tevent_req *pid_echo_send(TALLOC_CTX *mem_ctx,
12679 struct tevent_context *ev,
12680 struct cli_state *cli)
12682 struct tevent_req *req, *subreq;
12683 struct pidtest_state *state;
12685 req = tevent_req_create(mem_ctx, &state, struct pidtest_state);
12690 SSVAL(state->vwv, 0, 1);
12691 state->data = data_blob_const("hello", 5);
12693 subreq = smb1cli_req_send(state,
12697 0, 0, /* *_flags */
12698 0, 0, /* *_flags2 */
12700 0xDEADBEEF, /* pid */
12702 NULL, /* session */
12703 ARRAY_SIZE(state->vwv), state->vwv,
12704 state->data.length, state->data.data);
12706 if (tevent_req_nomem(subreq, req)) {
12707 return tevent_req_post(req, ev);
12709 tevent_req_set_callback(subreq, pid_echo_done, req);
12713 static void pid_echo_done(struct tevent_req *subreq)
12715 struct tevent_req *req = tevent_req_callback_data(
12716 subreq, struct tevent_req);
12717 struct pidtest_state *state = tevent_req_data(
12718 req, struct pidtest_state);
12720 uint32_t num_bytes;
12721 uint8_t *bytes = NULL;
12722 struct iovec *recv_iov = NULL;
12723 uint8_t *phdr = NULL;
12724 uint16_t pidlow = 0;
12725 uint16_t pidhigh = 0;
12726 struct smb1cli_req_expected_response expected[] = {
12728 .status = NT_STATUS_OK,
12733 status = smb1cli_req_recv(subreq, state,
12738 NULL, /* pvwv_offset */
12741 NULL, /* pbytes_offset */
12743 expected, ARRAY_SIZE(expected));
12745 TALLOC_FREE(subreq);
12747 if (!NT_STATUS_IS_OK(status)) {
12748 tevent_req_nterror(req, status);
12752 if (num_bytes != state->data.length) {
12753 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
12757 if (memcmp(bytes, state->data.data, num_bytes) != 0) {
12758 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
12762 /* Check pid low/high == DEADBEEF */
12763 pidlow = SVAL(phdr, HDR_PID);
12764 if (pidlow != 0xBEEF){
12765 printf("Incorrect pidlow 0x%x, should be 0xBEEF\n",
12766 (unsigned int)pidlow);
12767 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
12770 pidhigh = SVAL(phdr, HDR_PIDHIGH);
12771 if (pidhigh != 0xDEAD){
12772 printf("Incorrect pidhigh 0x%x, should be 0xDEAD\n",
12773 (unsigned int)pidhigh);
12774 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
12778 tevent_req_done(req);
12781 static NTSTATUS pid_echo_recv(struct tevent_req *req)
12783 return tevent_req_simple_recv_ntstatus(req);
12786 static bool run_pidhigh(int dummy)
12788 bool success = false;
12789 struct cli_state *cli = NULL;
12791 struct tevent_context *ev = NULL;
12792 struct tevent_req *req = NULL;
12793 TALLOC_CTX *frame = talloc_stackframe();
12795 printf("starting pid high test\n");
12796 if (!torture_open_connection(&cli, 0)) {
12799 smbXcli_conn_set_sockopt(cli->conn, sockops);
12801 ev = samba_tevent_context_init(frame);
12806 req = pid_echo_send(frame, ev, cli);
12811 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
12815 status = pid_echo_recv(req);
12816 if (NT_STATUS_IS_OK(status)) {
12817 printf("pid high test ok\n");
12823 TALLOC_FREE(frame);
12824 torture_close_connection(cli);
12829 Test Windows open on a bad POSIX symlink.
12831 static bool run_symlink_open_test(int dummy)
12833 static struct cli_state *cli;
12834 const char *fname = "non_existant_file";
12835 const char *sname = "dangling_symlink";
12836 uint16_t fnum = (uint16_t)-1;
12837 bool correct = false;
12839 TALLOC_CTX *frame = NULL;
12841 frame = talloc_stackframe();
12843 printf("Starting Windows bad symlink open test\n");
12845 if (!torture_open_connection(&cli, 0)) {
12846 TALLOC_FREE(frame);
12850 smbXcli_conn_set_sockopt(cli->conn, sockops);
12852 status = torture_setup_unix_extensions(cli);
12853 if (!NT_STATUS_IS_OK(status)) {
12854 TALLOC_FREE(frame);
12858 /* Ensure nothing exists. */
12859 cli_setatr(cli, fname, 0, 0);
12860 cli_posix_unlink(cli, fname);
12861 cli_setatr(cli, sname, 0, 0);
12862 cli_posix_unlink(cli, sname);
12864 /* Create a symlink pointing nowhere. */
12865 status = cli_posix_symlink(cli, fname, sname);
12866 if (!NT_STATUS_IS_OK(status)) {
12867 printf("cli_posix_symlink of %s -> %s failed (%s)\n",
12870 nt_errstr(status));
12874 /* Now ensure that a Windows open doesn't hang. */
12875 status = cli_ntcreate(cli,
12878 FILE_READ_DATA|FILE_WRITE_DATA,
12880 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
12888 * We get either NT_STATUS_OBJECT_NAME_NOT_FOUND or
12889 * NT_STATUS_OBJECT_PATH_NOT_FOUND depending on if
12890 * we use O_NOFOLLOW on the server or not.
12892 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND) ||
12893 NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_PATH_NOT_FOUND))
12897 printf("cli_ntcreate of %s returned %s - should return"
12898 " either (%s) or (%s)\n",
12901 nt_errstr(NT_STATUS_OBJECT_NAME_NOT_FOUND),
12902 nt_errstr(NT_STATUS_OBJECT_PATH_NOT_FOUND));
12910 if (fnum != (uint16_t)-1) {
12911 cli_close(cli, fnum);
12912 fnum = (uint16_t)-1;
12915 cli_setatr(cli, sname, 0, 0);
12916 cli_posix_unlink(cli, sname);
12917 cli_setatr(cli, fname, 0, 0);
12918 cli_posix_unlink(cli, fname);
12920 if (!torture_close_connection(cli)) {
12924 TALLOC_FREE(frame);
12928 static NTSTATUS smb1_wild_mangle_list_fn(struct file_info *finfo,
12932 char **mangled_name_return = (char **)state;
12933 bool is_mangled = strchr(finfo->name, '~');
12936 *mangled_name_return = talloc_strdup(NULL, finfo->name);
12937 if (*mangled_name_return == NULL) {
12938 return NT_STATUS_NO_MEMORY;
12941 return NT_STATUS_OK;
12944 static bool run_smb1_wild_mangle_unlink_test(int dummy)
12946 static struct cli_state *cli_posix = NULL;
12947 static struct cli_state *cli = NULL;
12948 uint16_t fnum = (uint16_t)-1;
12949 bool correct = false;
12950 const char *dname = "smb1_wild_mangle_unlink";
12951 const char *aname = "smb1_wild_mangle_unlink/a";
12952 const char *star_name = "smb1_wild_mangle_unlink/*";
12953 char *windows_unlink_name = NULL;
12954 char *mangled_name = NULL;
12957 printf("Starting SMB1 wild mangle unlink test\n");
12959 /* Open a Windows connection. */
12960 if (!torture_open_connection(&cli, 0)) {
12964 smbXcli_conn_set_sockopt(cli->conn, sockops);
12966 /* Open a POSIX connection. */
12967 if (!torture_open_connection(&cli_posix, 0)) {
12971 smbXcli_conn_set_sockopt(cli_posix->conn, sockops);
12973 status = torture_setup_unix_extensions(cli_posix);
12974 if (!NT_STATUS_IS_OK(status)) {
12975 printf("server doesn't support POSIX\n");
12980 torture_deltree(cli, dname);
12983 * Create two files - 'a' and '*'.
12984 * We need POSIX extensions for this as '*'
12985 * is not a valid Windows name.
12988 status = cli_mkdir(cli, dname);
12989 if (!NT_STATUS_IS_OK(status)) {
12990 printf("cli_mkdir of %s returned %s\n",
12992 nt_errstr(status));
12996 status = cli_posix_open(cli_posix,
12998 O_RDWR|O_CREAT|O_EXCL,
13001 if (!NT_STATUS_IS_OK(status)) {
13002 printf("cli_posix_open (create) of %s returned %s\n",
13004 nt_errstr(status));
13007 status = cli_close(cli_posix, fnum);
13008 if (!NT_STATUS_IS_OK(status)) {
13011 status = cli_posix_open(cli_posix,
13013 O_RDWR|O_CREAT|O_EXCL,
13016 if (!NT_STATUS_IS_OK(status)) {
13017 printf("cli_posix_open (create) of %s returned %s\n",
13019 nt_errstr(status));
13022 status = cli_close(cli_posix, fnum);
13023 if (!NT_STATUS_IS_OK(status)) {
13027 status = cli_list(cli,
13030 smb1_wild_mangle_list_fn,
13032 if (!NT_STATUS_IS_OK(status)) {
13033 printf("cli_list of %s returned %s\n",
13035 nt_errstr(status));
13039 if (mangled_name == NULL) {
13043 printf("mangled_name = %s\n",
13047 * Try a Windows unlink with the mangled name.
13048 * This should *NOT* unlink the 'a' name.
13051 windows_unlink_name = talloc_asprintf(cli_posix,
13056 status = cli_unlink(cli, windows_unlink_name, 0);
13057 if (!NT_STATUS_IS_OK(status)) {
13058 printf("cli_unlink of %s returned %s\n",
13059 windows_unlink_name,
13060 nt_errstr(status));
13064 /* Does 'a' still exist ? */
13065 status = cli_posix_open(cli_posix,
13070 if (!NT_STATUS_IS_OK(status)) {
13071 printf("cli_posix_open O_RNONLY of %s returned %s\n",
13073 nt_errstr(status));
13077 status = cli_close(cli_posix, fnum);
13078 if (!NT_STATUS_IS_OK(status)) {
13086 TALLOC_FREE(windows_unlink_name);
13087 TALLOC_FREE(mangled_name);
13090 torture_deltree(cli, dname);
13091 torture_close_connection(cli);
13094 if (cli_posix != NULL) {
13095 torture_close_connection(cli_posix);
13101 static bool run_smb1_wild_mangle_rename_test(int dummy)
13103 static struct cli_state *cli_posix = NULL;
13104 static struct cli_state *cli = NULL;
13105 uint16_t fnum = (uint16_t)-1;
13106 bool correct = false;
13107 const char *dname = "smb1_wild_mangle_rename";
13108 const char *fooname = "smb1_wild_mangle_rename/foo";
13109 const char *foostar_name = "smb1_wild_mangle_rename/fo*";
13110 const char *wild_name = "smb1_wild_mangle_rename/*";
13111 char *windows_rename_src = NULL;
13112 const char *windows_rename_dst = "smb1_wild_mangle_rename\\bar";
13113 char *mangled_name = NULL;
13116 printf("Starting SMB1 wild mangle rename test\n");
13118 if (!torture_open_connection(&cli_posix, 0)) {
13122 smbXcli_conn_set_sockopt(cli_posix->conn, sockops);
13124 status = torture_setup_unix_extensions(cli_posix);
13125 if (!NT_STATUS_IS_OK(status)) {
13126 printf("server doesn't support POSIX\n");
13130 /* Open a Windows connection. */
13131 if (!torture_open_connection(&cli, 0)) {
13135 smbXcli_conn_set_sockopt(cli->conn, sockops);
13137 /* Ensure we start from fresh. */
13138 torture_deltree(cli, dname);
13141 * Create two files - 'foo' and 'fo*'.
13142 * We need POSIX extensions for this as 'fo*'
13143 * is not a valid Windows name.
13146 status = cli_posix_mkdir(cli_posix, dname, 0770);
13147 if (!NT_STATUS_IS_OK(status)) {
13148 printf("cli_posix_mkdir of %s returned %s\n",
13150 nt_errstr(status));
13154 status = cli_posix_open(cli_posix,
13156 O_RDWR|O_CREAT|O_EXCL,
13159 if (!NT_STATUS_IS_OK(status)) {
13160 printf("cli_posix_open (create) of %s returned %s\n",
13162 nt_errstr(status));
13165 status = cli_close(cli_posix, fnum);
13166 if (!NT_STATUS_IS_OK(status)) {
13169 status = cli_posix_open(cli_posix,
13171 O_RDWR|O_CREAT|O_EXCL,
13174 if (!NT_STATUS_IS_OK(status)) {
13175 printf("cli_posix_open (create) of %s returned %s\n",
13177 nt_errstr(status));
13180 status = cli_close(cli_posix, fnum);
13181 if (!NT_STATUS_IS_OK(status)) {
13186 * Get the mangled name. We can re-use the
13187 * previous smb1_wild_mangle_list_fn for this.
13190 status = cli_list(cli,
13193 smb1_wild_mangle_list_fn,
13195 if (!NT_STATUS_IS_OK(status)) {
13196 printf("cli_list of %s returned %s\n",
13198 nt_errstr(status));
13202 if (mangled_name == NULL) {
13206 printf("mangled_name = %s\n",
13210 * Try a Windows rename with the mangled name.
13211 * This should *NOT* rename the 'foo' name.
13214 windows_rename_src = talloc_asprintf(cli_posix,
13219 status = cli_rename(cli,
13220 windows_rename_src,
13221 windows_rename_dst,
13223 if (!NT_STATUS_IS_OK(status)) {
13224 printf("cli_rename of %s -> %s returned %s\n",
13225 windows_rename_src,
13226 windows_rename_dst,
13227 nt_errstr(status));
13231 /* Does 'foo' still exist ? */
13232 status = cli_posix_open(cli_posix,
13237 if (!NT_STATUS_IS_OK(status)) {
13238 printf("cli_posix_open O_RNONLY of %s returned %s\n",
13240 nt_errstr(status));
13244 status = cli_close(cli_posix, fnum);
13245 if (!NT_STATUS_IS_OK(status)) {
13253 TALLOC_FREE(mangled_name);
13254 TALLOC_FREE(windows_rename_src);
13257 torture_deltree(cli, dname);
13258 torture_close_connection(cli);
13261 torture_close_connection(cli_posix);
13267 * Only testing minimal time strings, as the others
13268 * need (locale-dependent) guessing at what strftime does and
13269 * even may differ in builds.
13271 static bool timesubst_test(void)
13273 TALLOC_CTX *ctx = NULL;
13274 /* Sa 23. Dez 04:33:20 CET 2017 */
13275 const struct timeval tv = { 1514000000, 123 };
13276 const char* expect_minimal = "20171223_033320";
13277 const char* expect_minus = "20171223_033320_000123";
13279 char *env_tz, *orig_tz = NULL;
13280 bool result = true;
13282 ctx = talloc_new(NULL);
13284 env_tz = getenv("TZ");
13286 orig_tz = talloc_strdup(ctx, env_tz);
13288 setenv("TZ", "UTC", 1);
13290 s = minimal_timeval_string(ctx, &tv, false);
13292 if(!s || strcmp(s, expect_minimal)) {
13293 printf("minimal_timeval_string(ctx, tv, false) returned [%s], expected "
13294 "[%s]\n", s ? s : "<nil>", expect_minimal);
13298 s = minimal_timeval_string(ctx, &tv, true);
13299 if(!s || strcmp(s, expect_minus)) {
13300 printf("minimal_timeval_string(ctx, tv, true) returned [%s], expected "
13301 "[%s]\n", s ? s : "<nil>", expect_minus);
13307 setenv("TZ", orig_tz, 1);
13314 static bool run_local_substitute(int dummy)
13318 ok &= subst_test("%U", "bla", "", -1, -1, "bla");
13319 ok &= subst_test("%u%U", "bla", "", -1, -1, "blabla");
13320 ok &= subst_test("%g", "", "", -1, -1, "NO_GROUP");
13321 ok &= subst_test("%G", "", "", -1, -1, "NO_GROUP");
13322 ok &= subst_test("%g", "", "", -1, 0, gidtoname(0));
13323 ok &= subst_test("%G", "", "", -1, 0, gidtoname(0));
13324 ok &= subst_test("%D%u", "u", "dom", -1, 0, "domu");
13325 ok &= subst_test("%i %I", "", "", -1, -1, "0.0.0.0 0.0.0.0");
13326 ok &= subst_test("%j %J", "", "", -1, -1, "0_0_0_0 0_0_0_0");
13327 /* Substitution depends on current time, so better test the underlying
13328 formatting function. At least covers %t. */
13329 ok &= timesubst_test();
13331 /* Different captialization rules in sub_basic... */
13333 ok &= (strcmp(talloc_sub_basic(talloc_tos(), "BLA", "dom", "%U%D"),
13339 static bool run_local_base64(int dummy)
13344 for (i=1; i<2000; i++) {
13345 DATA_BLOB blob1, blob2;
13348 blob1.data = talloc_array(talloc_tos(), uint8_t, i);
13350 generate_random_buffer(blob1.data, blob1.length);
13352 b64 = base64_encode_data_blob(talloc_tos(), blob1);
13354 d_fprintf(stderr, "base64_encode_data_blob failed "
13355 "for %d bytes\n", i);
13358 blob2 = base64_decode_data_blob(b64);
13361 if (data_blob_cmp(&blob1, &blob2)) {
13362 d_fprintf(stderr, "data_blob_cmp failed for %d "
13366 TALLOC_FREE(blob1.data);
13367 data_blob_free(&blob2);
13372 static void parse_fn(const struct gencache_timeout *t,
13374 void *private_data)
13379 static bool run_local_gencache(int dummy)
13385 struct memcache *mem;
13388 mem = memcache_init(NULL, 0);
13390 d_printf("%s: memcache_init failed\n", __location__);
13393 memcache_set_global(mem);
13395 if (!gencache_set("foo", "bar", time(NULL) + 1000)) {
13396 d_printf("%s: gencache_set() failed\n", __location__);
13400 if (!gencache_get("foo", NULL, NULL, NULL)) {
13401 d_printf("%s: gencache_get() failed\n", __location__);
13405 for (i=0; i<1000000; i++) {
13406 gencache_parse("foo", parse_fn, NULL);
13409 if (!gencache_get("foo", talloc_tos(), &val, &tm)) {
13410 d_printf("%s: gencache_get() failed\n", __location__);
13415 if (!gencache_get("foo", talloc_tos(), &val, &tm)) {
13416 d_printf("%s: gencache_get() failed\n", __location__);
13420 if (strcmp(val, "bar") != 0) {
13421 d_printf("%s: gencache_get() returned %s, expected %s\n",
13422 __location__, val, "bar");
13429 if (!gencache_del("foo")) {
13430 d_printf("%s: gencache_del() failed\n", __location__);
13433 if (gencache_del("foo")) {
13434 d_printf("%s: second gencache_del() succeeded\n",
13439 if (gencache_get("foo", talloc_tos(), &val, &tm)) {
13440 d_printf("%s: gencache_get() on deleted entry "
13441 "succeeded\n", __location__);
13445 blob = data_blob_string_const_null("bar");
13446 tm = time(NULL) + 60;
13448 if (!gencache_set_data_blob("foo", blob, tm)) {
13449 d_printf("%s: gencache_set_data_blob() failed\n", __location__);
13453 if (!gencache_get_data_blob("foo", talloc_tos(), &blob, NULL, NULL)) {
13454 d_printf("%s: gencache_get_data_blob() failed\n", __location__);
13458 if (strcmp((const char *)blob.data, "bar") != 0) {
13459 d_printf("%s: gencache_get_data_blob() returned %s, expected %s\n",
13460 __location__, (const char *)blob.data, "bar");
13461 data_blob_free(&blob);
13465 data_blob_free(&blob);
13467 if (!gencache_del("foo")) {
13468 d_printf("%s: gencache_del() failed\n", __location__);
13471 if (gencache_del("foo")) {
13472 d_printf("%s: second gencache_del() succeeded\n",
13477 if (gencache_get_data_blob("foo", talloc_tos(), &blob, NULL, NULL)) {
13478 d_printf("%s: gencache_get_data_blob() on deleted entry "
13479 "succeeded\n", __location__);
13484 blob.data = (uint8_t *)&v;
13485 blob.length = sizeof(v);
13487 if (!gencache_set_data_blob("blob", blob, tm)) {
13488 d_printf("%s: gencache_set_data_blob() failed\n",
13492 if (gencache_get("blob", talloc_tos(), &val, &tm)) {
13493 d_printf("%s: gencache_get succeeded\n", __location__);
13500 static bool rbt_testflags(struct db_context *db, const char *key,
13505 struct db_record *rec;
13507 rec = dbwrap_fetch_locked(db, db, string_tdb_data(key));
13509 d_fprintf(stderr, "fetch_locked failed\n");
13513 status = dbwrap_record_store(rec, string_tdb_data(value), TDB_MODIFY);
13514 if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
13515 d_fprintf(stderr, "store TDB_MODIFY unexpected status: %s\n",
13516 nt_errstr(status));
13520 status = dbwrap_record_store(rec, string_tdb_data("overwriteme"),
13522 if (!NT_STATUS_IS_OK(status)) {
13523 d_fprintf(stderr, "store TDB_INSERT failed: %s\n",
13524 nt_errstr(status));
13528 status = dbwrap_record_store(rec, string_tdb_data(value), TDB_INSERT);
13529 if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_COLLISION)) {
13530 d_fprintf(stderr, "store TDB_INSERT unexpected status: %s\n",
13531 nt_errstr(status));
13535 status = dbwrap_record_store(rec, string_tdb_data(value), TDB_MODIFY);
13536 if (!NT_STATUS_IS_OK(status)) {
13537 d_fprintf(stderr, "store TDB_MODIFY failed: %s\n",
13538 nt_errstr(status));
13548 static bool rbt_testval(struct db_context *db, const char *key,
13551 struct db_record *rec;
13552 TDB_DATA data = string_tdb_data(value);
13557 rec = dbwrap_fetch_locked(db, db, string_tdb_data(key));
13559 d_fprintf(stderr, "fetch_locked failed\n");
13562 status = dbwrap_record_store(rec, data, 0);
13563 if (!NT_STATUS_IS_OK(status)) {
13564 d_fprintf(stderr, "store failed: %s\n", nt_errstr(status));
13569 rec = dbwrap_fetch_locked(db, db, string_tdb_data(key));
13571 d_fprintf(stderr, "second fetch_locked failed\n");
13575 dbvalue = dbwrap_record_get_value(rec);
13576 if ((dbvalue.dsize != data.dsize)
13577 || (memcmp(dbvalue.dptr, data.dptr, data.dsize) != 0)) {
13578 d_fprintf(stderr, "Got wrong data back\n");
13588 static int local_rbtree_traverse_read(struct db_record *rec, void *private_data)
13590 int *count2 = (int *)private_data;
13595 static int local_rbtree_traverse_delete(struct db_record *rec, void *private_data)
13597 int *count2 = (int *)private_data;
13599 dbwrap_record_delete(rec);
13603 static bool run_local_rbtree(int dummy)
13605 struct db_context *db;
13612 db = db_open_rbt(NULL);
13615 d_fprintf(stderr, "db_open_rbt failed\n");
13619 if (!rbt_testflags(db, "firstkey", "firstval")) {
13623 for (i = 0; i < 999; i++) {
13624 char key[sizeof("key-9223372036854775807")];
13625 char value[sizeof("value-9223372036854775807")];
13627 snprintf(key, sizeof(key), "key%ld", random());
13628 snprintf(value, sizeof(value) ,"value%ld", random());
13630 if (!rbt_testval(db, key, value)) {
13634 snprintf(value, sizeof(value) ,"value%ld", random());
13636 if (!rbt_testval(db, key, value)) {
13642 count = 0; count2 = 0;
13643 status = dbwrap_traverse_read(db, local_rbtree_traverse_read,
13645 printf("%s: read1: %d %d, %s\n", __func__, count, count2, nt_errstr(status));
13646 if ((count != count2) || (count != 1000)) {
13649 count = 0; count2 = 0;
13650 status = dbwrap_traverse(db, local_rbtree_traverse_delete,
13652 printf("%s: delete: %d %d, %s\n", __func__, count, count2, nt_errstr(status));
13653 if ((count != count2) || (count != 1000)) {
13656 count = 0; count2 = 0;
13657 status = dbwrap_traverse_read(db, local_rbtree_traverse_read,
13659 printf("%s: read2: %d %d, %s\n", __func__, count, count2, nt_errstr(status));
13660 if ((count != count2) || (count != 0)) {
13671 local test for character set functions
13673 This is a very simple test for the functionality in convert_string_error()
13675 static bool run_local_convert_string(int dummy)
13677 TALLOC_CTX *tmp_ctx = talloc_new(NULL);
13678 const char *test_strings[2] = { "March", "M\303\244rz" };
13682 for (i=0; i<2; i++) {
13683 const char *str = test_strings[i];
13684 int len = strlen(str);
13685 size_t converted_size;
13688 memset(dst, 'X', sizeof(dst));
13690 /* first try with real source length */
13691 ret = convert_string_error(CH_UNIX, CH_UTF8,
13696 d_fprintf(stderr, "Failed to convert '%s' to CH_DISPLAY\n", str);
13700 if (converted_size != len) {
13701 d_fprintf(stderr, "Converted size of '%s' should be %d - got %d\n",
13702 str, len, (int)converted_size);
13706 if (strncmp(str, dst, converted_size) != 0) {
13707 d_fprintf(stderr, "Expected '%s' to match '%s'\n", str, dst);
13711 if (strlen(str) != converted_size) {
13712 d_fprintf(stderr, "Expected '%s' length %d - got %d\n", str,
13713 (int)strlen(str), (int)converted_size);
13717 if (dst[converted_size] != 'X') {
13718 d_fprintf(stderr, "Expected no termination of '%s'\n", dst);
13722 /* now with srclen==-1, this causes the nul to be
13724 ret = convert_string_error(CH_UNIX, CH_UTF8,
13729 d_fprintf(stderr, "Failed to convert '%s' to CH_DISPLAY\n", str);
13733 if (converted_size != len+1) {
13734 d_fprintf(stderr, "Converted size of '%s' should be %d - got %d\n",
13735 str, len, (int)converted_size);
13739 if (strncmp(str, dst, converted_size) != 0) {
13740 d_fprintf(stderr, "Expected '%s' to match '%s'\n", str, dst);
13744 if (len+1 != converted_size) {
13745 d_fprintf(stderr, "Expected '%s' length %d - got %d\n", str,
13746 len+1, (int)converted_size);
13750 if (dst[converted_size] != 'X') {
13751 d_fprintf(stderr, "Expected no termination of '%s'\n", dst);
13758 TALLOC_FREE(tmp_ctx);
13761 TALLOC_FREE(tmp_ctx);
13765 static bool run_local_string_to_sid(int dummy) {
13766 struct dom_sid sid;
13768 if (string_to_sid(&sid, "S--1-5-32-545")) {
13769 printf("allowing S--1-5-32-545\n");
13772 if (string_to_sid(&sid, "S-1-5-32-+545")) {
13773 printf("allowing S-1-5-32-+545\n");
13776 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")) {
13777 printf("allowing S-1-2-3-4-5-6-7-8-9-0-1-2-3-4-5-6-7-8-9-0\n");
13780 if (string_to_sid(&sid, "S-1-5-32-545-abc")) {
13781 printf("allowing S-1-5-32-545-abc\n");
13784 if (string_to_sid(&sid, "S-300-5-32-545")) {
13785 printf("allowing S-300-5-32-545\n");
13788 if (string_to_sid(&sid, "S-1-0xfffffffffffffe-32-545")) {
13789 printf("allowing S-1-0xfffffffffffffe-32-545\n");
13792 if (string_to_sid(&sid, "S-1-0xffffffffffff-5294967297-545")) {
13793 printf("allowing S-1-0xffffffffffff-5294967297-545\n");
13796 if (!string_to_sid(&sid, "S-1-0xfffffffffffe-32-545")) {
13797 printf("could not parse S-1-0xfffffffffffe-32-545\n");
13800 if (!string_to_sid(&sid, "S-1-5-32-545")) {
13801 printf("could not parse S-1-5-32-545\n");
13804 if (!dom_sid_equal(&sid, &global_sid_Builtin_Users)) {
13805 struct dom_sid_buf buf;
13806 printf("mis-parsed S-1-5-32-545 as %s\n",
13807 dom_sid_str_buf(&sid, &buf));
13813 static bool sid_to_string_test(const char *expected) {
13816 struct dom_sid sid;
13818 if (!string_to_sid(&sid, expected)) {
13819 printf("could not parse %s\n", expected);
13823 str = dom_sid_string(NULL, &sid);
13824 if (strcmp(str, expected)) {
13825 printf("Comparison failed (%s != %s)\n", str, expected);
13832 static bool run_local_sid_to_string(int dummy) {
13833 if (!sid_to_string_test("S-1-0xffffffffffff-1-1-1-1-1-1-1-1-1-1-1-1"))
13835 if (!sid_to_string_test("S-1-545"))
13837 if (!sid_to_string_test("S-255-3840-1-1-1-1"))
13842 static bool run_local_binary_to_sid(int dummy) {
13844 struct dom_sid *sid = talloc(NULL, struct dom_sid);
13845 static const uint8_t good_binary_sid[] = {
13846 0x1, /* revision number */
13847 15, /* num auths */
13848 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, /* id_auth */
13849 0x1, 0x1, 0x1, 0x1, /* auth[0] */
13850 0x1, 0x1, 0x1, 0x1, /* auth[1] */
13851 0x1, 0x1, 0x1, 0x1, /* auth[2] */
13852 0x1, 0x1, 0x1, 0x1, /* auth[3] */
13853 0x1, 0x1, 0x1, 0x1, /* auth[4] */
13854 0x1, 0x1, 0x1, 0x1, /* auth[5] */
13855 0x1, 0x1, 0x1, 0x1, /* auth[6] */
13856 0x1, 0x1, 0x1, 0x1, /* auth[7] */
13857 0x1, 0x1, 0x1, 0x1, /* auth[8] */
13858 0x1, 0x1, 0x1, 0x1, /* auth[9] */
13859 0x1, 0x1, 0x1, 0x1, /* auth[10] */
13860 0x1, 0x1, 0x1, 0x1, /* auth[11] */
13861 0x1, 0x1, 0x1, 0x1, /* auth[12] */
13862 0x1, 0x1, 0x1, 0x1, /* auth[13] */
13863 0x1, 0x1, 0x1, 0x1, /* auth[14] */
13866 static const uint8_t long_binary_sid[] = {
13867 0x1, /* revision number */
13868 15, /* num auths */
13869 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, /* id_auth */
13870 0x1, 0x1, 0x1, 0x1, /* auth[0] */
13871 0x1, 0x1, 0x1, 0x1, /* auth[1] */
13872 0x1, 0x1, 0x1, 0x1, /* auth[2] */
13873 0x1, 0x1, 0x1, 0x1, /* auth[3] */
13874 0x1, 0x1, 0x1, 0x1, /* auth[4] */
13875 0x1, 0x1, 0x1, 0x1, /* auth[5] */
13876 0x1, 0x1, 0x1, 0x1, /* auth[6] */
13877 0x1, 0x1, 0x1, 0x1, /* auth[7] */
13878 0x1, 0x1, 0x1, 0x1, /* auth[8] */
13879 0x1, 0x1, 0x1, 0x1, /* auth[9] */
13880 0x1, 0x1, 0x1, 0x1, /* auth[10] */
13881 0x1, 0x1, 0x1, 0x1, /* auth[11] */
13882 0x1, 0x1, 0x1, 0x1, /* auth[12] */
13883 0x1, 0x1, 0x1, 0x1, /* auth[13] */
13884 0x1, 0x1, 0x1, 0x1, /* auth[14] */
13885 0x1, 0x1, 0x1, 0x1, /* auth[15] */
13886 0x1, 0x1, 0x1, 0x1, /* auth[16] */
13887 0x1, 0x1, 0x1, 0x1, /* auth[17] */
13890 static const uint8_t long_binary_sid2[] = {
13891 0x1, /* revision number */
13892 32, /* num auths */
13893 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, /* id_auth */
13894 0x1, 0x1, 0x1, 0x1, /* auth[0] */
13895 0x1, 0x1, 0x1, 0x1, /* auth[1] */
13896 0x1, 0x1, 0x1, 0x1, /* auth[2] */
13897 0x1, 0x1, 0x1, 0x1, /* auth[3] */
13898 0x1, 0x1, 0x1, 0x1, /* auth[4] */
13899 0x1, 0x1, 0x1, 0x1, /* auth[5] */
13900 0x1, 0x1, 0x1, 0x1, /* auth[6] */
13901 0x1, 0x1, 0x1, 0x1, /* auth[7] */
13902 0x1, 0x1, 0x1, 0x1, /* auth[8] */
13903 0x1, 0x1, 0x1, 0x1, /* auth[9] */
13904 0x1, 0x1, 0x1, 0x1, /* auth[10] */
13905 0x1, 0x1, 0x1, 0x1, /* auth[11] */
13906 0x1, 0x1, 0x1, 0x1, /* auth[12] */
13907 0x1, 0x1, 0x1, 0x1, /* auth[13] */
13908 0x1, 0x1, 0x1, 0x1, /* auth[14] */
13909 0x1, 0x1, 0x1, 0x1, /* auth[15] */
13910 0x1, 0x1, 0x1, 0x1, /* auth[16] */
13911 0x1, 0x1, 0x1, 0x1, /* auth[17] */
13912 0x1, 0x1, 0x1, 0x1, /* auth[18] */
13913 0x1, 0x1, 0x1, 0x1, /* auth[19] */
13914 0x1, 0x1, 0x1, 0x1, /* auth[20] */
13915 0x1, 0x1, 0x1, 0x1, /* auth[21] */
13916 0x1, 0x1, 0x1, 0x1, /* auth[22] */
13917 0x1, 0x1, 0x1, 0x1, /* auth[23] */
13918 0x1, 0x1, 0x1, 0x1, /* auth[24] */
13919 0x1, 0x1, 0x1, 0x1, /* auth[25] */
13920 0x1, 0x1, 0x1, 0x1, /* auth[26] */
13921 0x1, 0x1, 0x1, 0x1, /* auth[27] */
13922 0x1, 0x1, 0x1, 0x1, /* auth[28] */
13923 0x1, 0x1, 0x1, 0x1, /* auth[29] */
13924 0x1, 0x1, 0x1, 0x1, /* auth[30] */
13925 0x1, 0x1, 0x1, 0x1, /* auth[31] */
13928 ret = sid_parse(good_binary_sid, sizeof(good_binary_sid), sid);
13932 ret = sid_parse(long_binary_sid2, sizeof(long_binary_sid2), sid);
13936 ret = sid_parse(long_binary_sid, sizeof(long_binary_sid), sid);
13943 /* Split a path name into filename and stream name components. Canonicalise
13944 * such that an implicit $DATA token is always explicit.
13946 * The "specification" of this function can be found in the
13947 * run_local_stream_name() function in torture.c, I've tried those
13948 * combinations against a W2k3 server.
13951 static NTSTATUS split_ntfs_stream_name(TALLOC_CTX *mem_ctx, const char *fname,
13952 char **pbase, char **pstream)
13955 char *stream = NULL;
13956 char *sname; /* stream name */
13957 const char *stype; /* stream type */
13959 DEBUG(10, ("split_ntfs_stream_name called for [%s]\n", fname));
13961 sname = strchr_m(fname, ':');
13963 if (sname == NULL) {
13964 if (pbase != NULL) {
13965 base = talloc_strdup(mem_ctx, fname);
13966 NT_STATUS_HAVE_NO_MEMORY(base);
13971 if (pbase != NULL) {
13972 base = talloc_strndup(mem_ctx, fname, PTR_DIFF(sname, fname));
13973 NT_STATUS_HAVE_NO_MEMORY(base);
13978 stype = strchr_m(sname, ':');
13980 if (stype == NULL) {
13981 sname = talloc_strdup(mem_ctx, sname);
13985 if (strcasecmp_m(stype, ":$DATA") != 0) {
13987 * If there is an explicit stream type, so far we only
13988 * allow $DATA. Is there anything else allowed? -- vl
13990 DEBUG(10, ("[%s] is an invalid stream type\n", stype));
13992 return NT_STATUS_OBJECT_NAME_INVALID;
13994 sname = talloc_strndup(mem_ctx, sname, PTR_DIFF(stype, sname));
13998 if (sname == NULL) {
14000 return NT_STATUS_NO_MEMORY;
14003 if (sname[0] == '\0') {
14005 * no stream name, so no stream
14010 if (pstream != NULL) {
14011 stream = talloc_asprintf(mem_ctx, "%s:%s", sname, stype);
14012 if (stream == NULL) {
14013 TALLOC_FREE(sname);
14015 return NT_STATUS_NO_MEMORY;
14018 * upper-case the type field
14020 (void)strupper_m(strchr_m(stream, ':')+1);
14024 if (pbase != NULL) {
14027 if (pstream != NULL) {
14030 return NT_STATUS_OK;
14033 static bool test_stream_name(const char *fname, const char *expected_base,
14034 const char *expected_stream,
14035 NTSTATUS expected_status)
14039 char *stream = NULL;
14041 status = split_ntfs_stream_name(talloc_tos(), fname, &base, &stream);
14042 if (!NT_STATUS_EQUAL(status, expected_status)) {
14046 if (!NT_STATUS_IS_OK(status)) {
14050 if (base == NULL) goto error;
14052 if (strcmp(expected_base, base) != 0) goto error;
14054 if ((expected_stream != NULL) && (stream == NULL)) goto error;
14055 if ((expected_stream == NULL) && (stream != NULL)) goto error;
14057 if ((stream != NULL) && (strcmp(expected_stream, stream) != 0))
14061 TALLOC_FREE(stream);
14065 d_fprintf(stderr, "Do test_stream(%s, %s, %s, %s)\n",
14066 fname, expected_base ? expected_base : "<NULL>",
14067 expected_stream ? expected_stream : "<NULL>",
14068 nt_errstr(expected_status));
14069 d_fprintf(stderr, "-> base=%s, stream=%s, status=%s\n",
14070 base ? base : "<NULL>", stream ? stream : "<NULL>",
14071 nt_errstr(status));
14073 TALLOC_FREE(stream);
14077 static bool run_local_stream_name(int dummy)
14081 ret &= test_stream_name(
14082 "bla", "bla", NULL, NT_STATUS_OK);
14083 ret &= test_stream_name(
14084 "bla::$DATA", "bla", NULL, NT_STATUS_OK);
14085 ret &= test_stream_name(
14086 "bla:blub:", "bla", NULL, NT_STATUS_OBJECT_NAME_INVALID);
14087 ret &= test_stream_name(
14088 "bla::", NULL, NULL, NT_STATUS_OBJECT_NAME_INVALID);
14089 ret &= test_stream_name(
14090 "bla::123", "bla", NULL, NT_STATUS_OBJECT_NAME_INVALID);
14091 ret &= test_stream_name(
14092 "bla:$DATA", "bla", "$DATA:$DATA", NT_STATUS_OK);
14093 ret &= test_stream_name(
14094 "bla:x:$DATA", "bla", "x:$DATA", NT_STATUS_OK);
14095 ret &= test_stream_name(
14096 "bla:x", "bla", "x:$DATA", NT_STATUS_OK);
14101 static bool data_blob_equal(DATA_BLOB a, DATA_BLOB b)
14103 if (a.length != b.length) {
14104 printf("a.length=%d != b.length=%d\n",
14105 (int)a.length, (int)b.length);
14108 if (memcmp(a.data, b.data, a.length) != 0) {
14109 printf("a.data and b.data differ\n");
14115 static bool run_local_memcache(int dummy)
14117 struct memcache *cache;
14118 DATA_BLOB k1, k2, k3, k4, k5;
14122 TALLOC_CTX *mem_ctx;
14128 size_t size1, size2;
14131 mem_ctx = talloc_init("foo");
14132 if (mem_ctx == NULL) {
14136 /* STAT_CACHE TESTS */
14138 cache = memcache_init(NULL, sizeof(void *) == 8 ? 200 : 100);
14140 if (cache == NULL) {
14141 printf("memcache_init failed\n");
14145 d1 = data_blob_const("d1", 2);
14146 d3 = data_blob_const("d3", 2);
14148 k1 = data_blob_const("d1", 2);
14149 k2 = data_blob_const("d2", 2);
14150 k3 = data_blob_const("d3", 2);
14151 k4 = data_blob_const("d4", 2);
14152 k5 = data_blob_const("d5", 2);
14154 memcache_add(cache, STAT_CACHE, k1, d1);
14156 if (!memcache_lookup(cache, STAT_CACHE, k1, &v1)) {
14157 printf("could not find k1\n");
14160 if (!data_blob_equal(d1, v1)) {
14164 memcache_add(cache, STAT_CACHE, k1, d3);
14166 if (!memcache_lookup(cache, STAT_CACHE, k1, &v3)) {
14167 printf("could not find replaced k1\n");
14170 if (!data_blob_equal(d3, v3)) {
14174 TALLOC_FREE(cache);
14176 /* GETWD_CACHE TESTS */
14177 str1 = talloc_strdup(mem_ctx, "string1");
14178 if (str1 == NULL) {
14181 ptr2 = str1; /* Keep an alias for comparison. */
14183 str2 = talloc_strdup(mem_ctx, "string2");
14184 if (str2 == NULL) {
14188 cache = memcache_init(NULL, sizeof(void *) == 8 ? 200 : 100);
14189 if (cache == NULL) {
14190 printf("memcache_init failed\n");
14194 memcache_add_talloc(cache, GETWD_CACHE, k2, &str1);
14195 /* str1 == NULL now. */
14196 ptr1 = memcache_lookup_talloc(cache, GETWD_CACHE, k2);
14197 if (ptr1 == NULL) {
14198 printf("could not find k2\n");
14201 if (ptr1 != ptr2) {
14202 printf("fetch of k2 got wrong string\n");
14206 /* Add a blob to ensure k2 gets purged. */
14207 d3 = data_blob_talloc_zero(mem_ctx, 180);
14208 memcache_add(cache, STAT_CACHE, k3, d3);
14210 ptr2 = memcache_lookup_talloc(cache, GETWD_CACHE, k2);
14211 if (ptr2 != NULL) {
14212 printf("Did find k2, should have been purged\n");
14217 * Test that talloc size also is accounted in memcache and
14218 * causes purge of other object.
14221 str1 = talloc_zero_size(mem_ctx, 100);
14222 str2 = talloc_zero_size(mem_ctx, 100);
14224 memcache_add_talloc(cache, GETWD_CACHE, k4, &str1);
14225 memcache_add_talloc(cache, GETWD_CACHE, k5, &str1);
14227 ptr3 = memcache_lookup_talloc(cache, GETWD_CACHE, k4);
14228 if (ptr3 != NULL) {
14229 printf("Did find k4, should have been purged\n");
14234 * Test that adding a duplicate non-talloced
14235 * key/value on top of a talloced key/value takes account
14236 * of the talloc_freed value size.
14238 TALLOC_FREE(cache);
14239 TALLOC_FREE(mem_ctx);
14241 mem_ctx = talloc_init("key_replace");
14242 if (mem_ctx == NULL) {
14246 cache = memcache_init(NULL, sizeof(void *) == 8 ? 200 : 100);
14247 if (cache == NULL) {
14252 * Add a 100 byte talloced string. This will
14253 * store a (4 or 8 byte) pointer and record the
14254 * total talloced size.
14256 str1 = talloc_zero_size(mem_ctx, 100);
14257 memcache_add_talloc(cache, GETWD_CACHE, k4, &str1);
14259 * Now overwrite with a small talloced
14260 * value. This should fit in the existing size
14261 * and the total talloced size should be removed
14262 * from the cache size.
14264 str1 = talloc_zero_size(mem_ctx, 2);
14265 memcache_add_talloc(cache, GETWD_CACHE, k4, &str1);
14267 * Now store a 20 byte string. If the
14268 * total talloced size wasn't accounted for
14269 * and removed in the overwrite, then this
14272 str2 = talloc_zero_size(mem_ctx, 20);
14273 memcache_add_talloc(cache, GETWD_CACHE, k5, &str2);
14275 ptr3 = memcache_lookup_talloc(cache, GETWD_CACHE, k4);
14276 if (ptr3 == NULL) {
14277 printf("Did not find k4, should not have been purged\n");
14281 TALLOC_FREE(cache);
14282 TALLOC_FREE(mem_ctx);
14284 mem_ctx = talloc_init("foo");
14285 if (mem_ctx == NULL) {
14289 cache = memcache_init(NULL, 0);
14290 if (cache == NULL) {
14294 str1 = talloc_strdup(mem_ctx, "string1");
14295 if (str1 == NULL) {
14298 str2 = talloc_strdup(mem_ctx, "string2");
14299 if (str2 == NULL) {
14302 memcache_add_talloc(cache, SINGLETON_CACHE_TALLOC,
14303 data_blob_string_const("torture"), &str1);
14304 size1 = talloc_total_size(cache);
14306 memcache_add_talloc(cache, SINGLETON_CACHE_TALLOC,
14307 data_blob_string_const("torture"), &str2);
14308 size2 = talloc_total_size(cache);
14310 printf("size1=%d, size2=%d\n", (int)size1, (int)size2);
14312 if (size2 > size1) {
14313 printf("memcache leaks memory!\n");
14319 TALLOC_FREE(cache);
14323 static void wbclient_done(struct tevent_req *req)
14326 struct winbindd_response *wb_resp;
14327 int *i = (int *)tevent_req_callback_data_void(req);
14329 wbc_err = wb_trans_recv(req, req, &wb_resp);
14332 d_printf("wb_trans_recv %d returned %s\n", *i, wbcErrorString(wbc_err));
14335 static bool run_wbclient_multi_ping(int dummy)
14337 struct tevent_context *ev;
14338 struct wb_context **wb_ctx;
14339 struct winbindd_request wb_req;
14340 bool result = false;
14343 BlockSignals(True, SIGPIPE);
14345 ev = tevent_context_init(talloc_tos());
14350 wb_ctx = talloc_array(ev, struct wb_context *, torture_nprocs);
14351 if (wb_ctx == NULL) {
14355 ZERO_STRUCT(wb_req);
14356 wb_req.cmd = WINBINDD_PING;
14358 d_printf("torture_nprocs=%d, numops=%d\n", (int)torture_nprocs, (int)torture_numops);
14360 for (i=0; i<torture_nprocs; i++) {
14361 wb_ctx[i] = wb_context_init(ev, NULL);
14362 if (wb_ctx[i] == NULL) {
14365 for (j=0; j<torture_numops; j++) {
14366 struct tevent_req *req;
14367 req = wb_trans_send(ev, ev, wb_ctx[i],
14368 (j % 2) == 0, &wb_req);
14372 tevent_req_set_callback(req, wbclient_done, &i);
14378 while (i < torture_nprocs * torture_numops) {
14379 tevent_loop_once(ev);
14388 static bool dbtrans_inc(struct db_context *db)
14390 struct db_record *rec;
14396 rec = dbwrap_fetch_locked(db, db, string_term_tdb_data("transtest"));
14398 printf(__location__ "fetch_lock failed\n");
14402 value = dbwrap_record_get_value(rec);
14404 if (value.dsize != sizeof(uint32_t)) {
14405 printf(__location__ "value.dsize = %d\n",
14410 memcpy(&val, value.dptr, sizeof(val));
14413 status = dbwrap_record_store(
14414 rec, make_tdb_data((uint8_t *)&val, sizeof(val)), 0);
14415 if (!NT_STATUS_IS_OK(status)) {
14416 printf(__location__ "store failed: %s\n",
14417 nt_errstr(status));
14427 static bool run_local_dbtrans(int dummy)
14429 struct db_context *db;
14430 struct db_record *rec;
14436 db = db_open(talloc_tos(), "transtest.tdb", 0, TDB_DEFAULT,
14437 O_RDWR|O_CREAT, 0600, DBWRAP_LOCK_ORDER_1,
14440 printf("Could not open transtest.db\n");
14444 res = dbwrap_transaction_start(db);
14446 printf(__location__ "transaction_start failed\n");
14450 rec = dbwrap_fetch_locked(db, db, string_term_tdb_data("transtest"));
14452 printf(__location__ "fetch_lock failed\n");
14456 value = dbwrap_record_get_value(rec);
14458 if (value.dptr == NULL) {
14460 status = dbwrap_record_store(
14461 rec, make_tdb_data((uint8_t *)&initial,
14464 if (!NT_STATUS_IS_OK(status)) {
14465 printf(__location__ "store returned %s\n",
14466 nt_errstr(status));
14473 res = dbwrap_transaction_commit(db);
14475 printf(__location__ "transaction_commit failed\n");
14480 uint32_t val, val2;
14483 res = dbwrap_transaction_start(db);
14485 printf(__location__ "transaction_start failed\n");
14489 status = dbwrap_fetch_uint32_bystring(db, "transtest", &val);
14490 if (!NT_STATUS_IS_OK(status)) {
14491 printf(__location__ "dbwrap_fetch_uint32 failed: %s\n",
14492 nt_errstr(status));
14496 for (i=0; i<10; i++) {
14497 if (!dbtrans_inc(db)) {
14502 status = dbwrap_fetch_uint32_bystring(db, "transtest", &val2);
14503 if (!NT_STATUS_IS_OK(status)) {
14504 printf(__location__ "dbwrap_fetch_uint32 failed: %s\n",
14505 nt_errstr(status));
14509 if (val2 != val + 10) {
14510 printf(__location__ "val=%d, val2=%d\n",
14511 (int)val, (int)val2);
14515 printf("val2=%d\r", val2);
14517 res = dbwrap_transaction_commit(db);
14519 printf(__location__ "transaction_commit failed\n");
14529 * Just a dummy test to be run under a debugger. There's no real way
14530 * to inspect the tevent_poll specific function from outside of
14534 static bool run_local_tevent_poll(int dummy)
14536 struct tevent_context *ev;
14537 struct tevent_fd *fd1, *fd2;
14538 bool result = false;
14540 ev = tevent_context_init_byname(NULL, "poll");
14542 d_fprintf(stderr, "tevent_context_init_byname failed\n");
14546 fd1 = tevent_add_fd(ev, ev, 2, 0, NULL, NULL);
14548 d_fprintf(stderr, "tevent_add_fd failed\n");
14551 fd2 = tevent_add_fd(ev, ev, 3, 0, NULL, NULL);
14553 d_fprintf(stderr, "tevent_add_fd failed\n");
14558 fd2 = tevent_add_fd(ev, ev, 1, 0, NULL, NULL);
14560 d_fprintf(stderr, "tevent_add_fd failed\n");
14570 static bool run_local_hex_encode_buf(int dummy)
14576 for (i=0; i<sizeof(src); i++) {
14579 hex_encode_buf(buf, src, sizeof(src));
14580 if (strcmp(buf, "0001020304050607") != 0) {
14583 hex_encode_buf(buf, NULL, 0);
14584 if (buf[0] != '\0') {
14590 static const char *remove_duplicate_addrs2_test_strings_vector[] = {
14612 "1001:1111:1111:1000:0:1111:1111:1111",
14621 static const char *remove_duplicate_addrs2_test_strings_result[] = {
14635 "1001:1111:1111:1000:0:1111:1111:1111"
14638 static bool run_local_remove_duplicate_addrs2(int dummy)
14640 struct samba_sockaddr test_vector[28];
14643 /* Construct the sockaddr_storage test vector. */
14644 for (i = 0; i < 28; i++) {
14645 struct addrinfo hints;
14646 struct addrinfo *res = NULL;
14649 memset(&hints, '\0', sizeof(hints));
14650 hints.ai_flags = AI_NUMERICHOST;
14651 ret = getaddrinfo(remove_duplicate_addrs2_test_strings_vector[i],
14656 fprintf(stderr, "getaddrinfo failed on [%s]\n",
14657 remove_duplicate_addrs2_test_strings_vector[i]);
14660 memset(&test_vector[i], '\0', sizeof(test_vector[i]));
14661 memcpy(&test_vector[i].u.ss,
14667 count = remove_duplicate_addrs2(test_vector, i);
14670 fprintf(stderr, "count wrong (%zu) should be 14\n",
14675 for (i = 0; i < count; i++) {
14676 char addr[INET6_ADDRSTRLEN];
14678 print_sockaddr(addr, sizeof(addr), &test_vector[i].u.ss);
14680 if (strcmp(addr, remove_duplicate_addrs2_test_strings_result[i]) != 0) {
14681 fprintf(stderr, "mismatch on [%zu] [%s] [%s]\n",
14684 remove_duplicate_addrs2_test_strings_result[i]);
14689 printf("run_local_remove_duplicate_addrs2: success\n");
14693 static bool run_local_tdb_opener(int dummy)
14699 t = tdb_open("test.tdb", 1000, TDB_CLEAR_IF_FIRST,
14700 O_RDWR|O_CREAT, 0755);
14702 perror("tdb_open failed");
14713 static bool run_local_tdb_writer(int dummy)
14719 t = tdb_open("test.tdb", 1000, 0, O_RDWR|O_CREAT, 0755);
14721 perror("tdb_open failed");
14725 val.dptr = (uint8_t *)&v;
14726 val.dsize = sizeof(v);
14732 ret = tdb_store(t, val, val, 0);
14734 printf("%s\n", tdb_errorstr(t));
14739 data = tdb_fetch(t, val);
14740 if (data.dptr != NULL) {
14741 SAFE_FREE(data.dptr);
14747 static bool run_local_canonicalize_path(int dummy)
14749 const char *src[] = {
14756 ".././././../../../boo",
14768 "/foo/bar/../baz/",
14769 "////////////////",
14770 "/////////./././././.",
14771 "/./.././../.boo/../baz",
14772 "/a/component/path",
14773 "/a/component/path/",
14774 "/a/component/path/..",
14775 "/a/component/../path/",
14776 "///a/./././///component/../////path/",
14779 const char *dst[] = {
14802 "/a/component/path",
14803 "/a/component/path",
14811 for (i = 0; src[i] != NULL; i++) {
14812 char *d = canonicalize_absolute_path(talloc_tos(), src[i]);
14814 perror("talloc fail\n");
14817 if (strcmp(d, dst[i]) != 0) {
14819 "canonicalize mismatch %s -> %s != %s",
14820 src[i], d, dst[i]);
14827 struct session_setup_nt1_truncated_state {
14832 static void smb1_session_setup_nt1_truncated_done(struct tevent_req *subreq);
14834 static struct tevent_req *smb1_session_setup_nt1_truncated_send(
14835 TALLOC_CTX *mem_ctx,
14836 struct tevent_context *ev,
14837 struct smbXcli_conn *conn)
14839 uint16_t *vwv = NULL;
14840 uint8_t *bytes = NULL;
14841 const char *pass = "12345678";
14842 const char *uname = "z";
14843 struct session_setup_nt1_truncated_state *state = NULL;
14844 struct tevent_req *req = NULL;
14845 struct tevent_req *subreq = NULL;
14847 req = tevent_req_create(mem_ctx,
14849 struct session_setup_nt1_truncated_state);
14853 vwv = &state->vwv[0];
14854 bytes = &state->bytes[0];
14856 SCVAL(vwv+0, 0, 0xff);
14857 SCVAL(vwv+0, 1, 0);
14858 SSVAL(vwv+1, 0, 0);
14859 SSVAL(vwv+2, 0, 8192);
14860 SSVAL(vwv+3, 0, 2);
14861 SSVAL(vwv+4, 0, 1);
14862 SIVAL(vwv+5, 0, 0);
14863 SSVAL(vwv+7, 0, strlen(pass)); /* OEMPasswordLen */
14864 SSVAL(vwv+8, 0, 0); /* UnicodePasswordLen */
14865 SSVAL(vwv+9, 0, 0); /* reserved */
14866 SSVAL(vwv+10, 0, 0); /* reserved */
14867 SIVAL(vwv+11, 0, CAP_STATUS32);
14869 memcpy(bytes, pass, strlen(pass));
14870 bytes += strlen(pass);
14871 memcpy(bytes, uname, strlen(uname)+1);
14873 subreq = smb1cli_req_send(state, ev, conn,
14875 0, /* additional_flags */
14876 0, /* clear_flags */
14877 0, /* additional_flags2 */
14878 0, /* clear_flags2 */
14879 10000, /* timeout_msec */
14882 NULL, /* session */
14885 strlen(pass), /* Truncate length at password. */
14887 if (tevent_req_nomem(subreq, req)) {
14888 return tevent_req_post(req, ev);
14890 tevent_req_set_callback(subreq,
14891 smb1_session_setup_nt1_truncated_done,
14896 static void smb1_session_setup_nt1_truncated_done(struct tevent_req *subreq)
14898 struct tevent_req *req =
14899 tevent_req_callback_data(subreq,
14900 struct tevent_req);
14901 struct session_setup_nt1_truncated_state *state =
14902 tevent_req_data(req,
14903 struct session_setup_nt1_truncated_state);
14905 struct smb1cli_req_expected_response expected[] = {
14907 .status = NT_STATUS_OK,
14912 status = smb1cli_req_recv(subreq, state,
14917 NULL, /* pvwv_offset */
14920 NULL, /* pbytes_offset */
14922 expected, ARRAY_SIZE(expected));
14923 TALLOC_FREE(subreq);
14924 if (tevent_req_nterror(req, status)) {
14927 tevent_req_done(req);
14930 static NTSTATUS smb1_session_setup_nt1_truncated_recv(struct tevent_req *req)
14932 return tevent_req_simple_recv_ntstatus(req);
14935 static bool run_smb1_truncated_sesssetup(int dummy)
14937 struct tevent_context *ev;
14938 struct tevent_req *req;
14939 struct smbXcli_conn *conn;
14940 struct sockaddr_storage ss;
14945 printf("Starting send truncated SMB1 sesssetup.\n");
14947 ok = resolve_name(host, &ss, 0x20, true);
14949 d_fprintf(stderr, "Could not resolve name %s\n", host);
14953 status = open_socket_out(&ss, 445, 10000, &fd);
14954 if (!NT_STATUS_IS_OK(status)) {
14955 d_fprintf(stderr, "open_socket_out failed: %s\n",
14956 nt_errstr(status));
14960 conn = smbXcli_conn_create(talloc_tos(), fd, host, SMB_SIGNING_OFF, 0,
14962 if (conn == NULL) {
14963 d_fprintf(stderr, "smbXcli_conn_create failed\n");
14967 status = smbXcli_negprot(conn,
14974 if (!NT_STATUS_IS_OK(status)) {
14975 d_fprintf(stderr, "smbXcli_negprot failed!\n");
14979 ev = samba_tevent_context_init(talloc_tos());
14981 d_fprintf(stderr, "samba_tevent_context_init failed\n");
14985 req = smb1_session_setup_nt1_truncated_send(ev, ev, conn);
14987 d_fprintf(stderr, "smb1_session_setup_nt1_truncated_send failed\n");
14991 ok = tevent_req_poll_ntstatus(req, ev, &status);
14993 d_fprintf(stderr, "tevent_req_poll failed with status %s\n",
14994 nt_errstr(status));
14998 status = smb1_session_setup_nt1_truncated_recv(req);
14999 if (!NT_STATUS_IS_OK(status)) {
15000 d_fprintf(stderr, "smb1_session_setup_nt1_truncated_recv returned "
15001 "%s, expected NT_STATUS_OK\n",
15002 nt_errstr(status));
15010 struct smb1_negotiate_exit_state {
15014 static void smb1_negotiate_exit_done(struct tevent_req *subreq);
15016 static struct tevent_req *smb1_negotiate_exit_send(
15017 TALLOC_CTX *mem_ctx,
15018 struct tevent_context *ev,
15019 struct smbXcli_conn *conn)
15021 struct smb1_negotiate_exit_state *state = NULL;
15022 struct tevent_req *req = NULL;
15023 struct tevent_req *subreq = NULL;
15025 req = tevent_req_create(mem_ctx,
15027 struct smb1_negotiate_exit_state);
15031 subreq = smb1cli_req_send(state, ev, conn,
15033 0, /* additional_flags */
15034 0, /* clear_flags */
15035 0, /* additional_flags2 */
15036 0, /* clear_flags2 */
15037 10000, /* timeout_msec */
15040 NULL, /* session */
15045 if (tevent_req_nomem(subreq, req)) {
15046 return tevent_req_post(req, ev);
15048 tevent_req_set_callback(subreq,
15049 smb1_negotiate_exit_done,
15054 static void smb1_negotiate_exit_done(struct tevent_req *subreq)
15056 struct tevent_req *req =
15057 tevent_req_callback_data(subreq,
15058 struct tevent_req);
15059 struct smb1_negotiate_exit_state *state =
15060 tevent_req_data(req,
15061 struct smb1_negotiate_exit_state);
15063 struct smb1cli_req_expected_response expected[] = {
15065 .status = NT_STATUS_OK,
15070 status = smb1cli_req_recv(subreq, state,
15075 NULL, /* pvwv_offset */
15078 NULL, /* pbytes_offset */
15080 expected, ARRAY_SIZE(expected));
15081 TALLOC_FREE(subreq);
15082 if (tevent_req_nterror(req, status)) {
15085 tevent_req_done(req);
15088 static NTSTATUS smb1_negotiate_exit_recv(struct tevent_req *req)
15090 return tevent_req_simple_recv_ntstatus(req);
15093 static bool do_smb1_exit(TALLOC_CTX *mem_ctx,
15094 struct tevent_context *ev,
15095 struct smbXcli_conn *conn)
15097 struct tevent_req *req;
15100 NTSTATUS expected_status = NT_STATUS_DOS(ERRSRV, ERRinvnid);;
15102 req = smb1_negotiate_exit_send(ev, ev, conn);
15104 d_fprintf(stderr, "smb1_negotiate_exit_send failed\n");
15108 ok = tevent_req_poll_ntstatus(req, ev, &status);
15110 d_fprintf(stderr, "tevent_req_poll failed with status %s\n",
15111 nt_errstr(status));
15115 status = smb1_negotiate_exit_recv(req);
15116 if (!NT_STATUS_EQUAL(status, expected_status)) {
15117 d_fprintf(stderr, "smb1_negotiate_exit_recv returned "
15118 "%s, expected ERRSRV, ERRinvnid\n",
15119 nt_errstr(status));
15125 static bool run_smb1_negotiate_exit(int dummy)
15127 struct tevent_context *ev;
15128 struct smbXcli_conn *conn;
15129 struct sockaddr_storage ss;
15134 printf("Starting send SMB1 negotiate+exit.\n");
15136 ok = resolve_name(host, &ss, 0x20, true);
15138 d_fprintf(stderr, "Could not resolve name %s\n", host);
15142 status = open_socket_out(&ss, 445, 10000, &fd);
15143 if (!NT_STATUS_IS_OK(status)) {
15144 d_fprintf(stderr, "open_socket_out failed: %s\n",
15145 nt_errstr(status));
15149 conn = smbXcli_conn_create(talloc_tos(), fd, host, SMB_SIGNING_OFF, 0,
15151 if (conn == NULL) {
15152 d_fprintf(stderr, "smbXcli_conn_create failed\n");
15156 status = smbXcli_negprot(conn,
15163 if (!NT_STATUS_IS_OK(status)) {
15164 d_fprintf(stderr, "smbXcli_negprot failed!\n");
15168 ev = samba_tevent_context_init(talloc_tos());
15170 d_fprintf(stderr, "samba_tevent_context_init failed\n");
15175 * Call do_smb1_exit twice to catch a server crash, the
15176 * server sends the first return code then crashes.
15178 ok = do_smb1_exit(ev, ev, conn);
15180 d_fprintf(stderr, "do_smb1_exit (1) failed\n");
15183 ok = do_smb1_exit(ev, ev, conn);
15185 d_fprintf(stderr, "do_smb1_exit (2) failed\n");
15193 static bool run_smb1_negotiate_tcon(int dummy)
15195 struct cli_state *cli = NULL;
15197 uint16_t max_xmit = 0;
15200 printf("Starting send SMB1 negotiate+tcon.\n");
15201 cli = open_nbt_connection();
15203 d_fprintf(stderr, "open_nbt_connection failed!\n");
15206 smbXcli_conn_set_sockopt(cli->conn, sockops);
15208 status = smbXcli_negprot(cli->conn,
15215 if (!NT_STATUS_IS_OK(status)) {
15216 d_fprintf(stderr, "smbXcli_negprot failed %s!\n",
15217 nt_errstr(status));
15220 status = cli_raw_tcon(cli,
15226 if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
15227 d_fprintf(stderr, "cli_raw_tcon failed - got %s "
15228 "(should get NT_STATUS_ACCESS_DENIED)!\n",
15229 nt_errstr(status));
15235 static bool run_ign_bad_negprot(int dummy)
15237 struct tevent_context *ev;
15238 struct tevent_req *req;
15239 struct smbXcli_conn *conn;
15240 struct sockaddr_storage ss;
15245 printf("starting ignore bad negprot\n");
15247 ok = resolve_name(host, &ss, 0x20, true);
15249 d_fprintf(stderr, "Could not resolve name %s\n", host);
15253 status = open_socket_out(&ss, 445, 10000, &fd);
15254 if (!NT_STATUS_IS_OK(status)) {
15255 d_fprintf(stderr, "open_socket_out failed: %s\n",
15256 nt_errstr(status));
15260 conn = smbXcli_conn_create(talloc_tos(), fd, host, SMB_SIGNING_OFF, 0,
15262 if (conn == NULL) {
15263 d_fprintf(stderr, "smbXcli_conn_create failed\n");
15267 status = smbXcli_negprot(conn,
15274 if (NT_STATUS_IS_OK(status)) {
15275 d_fprintf(stderr, "smbXcli_negprot succeeded!\n");
15279 ev = samba_tevent_context_init(talloc_tos());
15281 d_fprintf(stderr, "samba_tevent_context_init failed\n");
15285 req = smb1cli_session_setup_nt1_send(
15286 ev, ev, conn, 0, getpid(), NULL, 65503, 2, 1, 0, "", "",
15287 data_blob_null, data_blob_null, 0x40,
15288 "Windows 2000 2195", "Windows 2000 5.0");
15290 d_fprintf(stderr, "smb1cli_session_setup_nt1_send failed\n");
15294 ok = tevent_req_poll_ntstatus(req, ev, &status);
15296 d_fprintf(stderr, "tevent_req_poll failed\n");
15300 status = smb1cli_session_setup_nt1_recv(req, NULL, NULL, NULL, NULL,
15302 if (!NT_STATUS_EQUAL(status, NT_STATUS_CONNECTION_RESET)) {
15303 d_fprintf(stderr, "smb1cli_session_setup_nt1_recv returned "
15304 "%s, expected NT_STATUS_CONNECTION_RESET\n",
15305 nt_errstr(status));
15311 printf("starting ignore bad negprot\n");
15317 static double create_procs(bool (*fn)(int), bool *result)
15320 volatile pid_t *child_status;
15321 volatile bool *child_status_out;
15324 struct timeval start;
15328 child_status = (volatile pid_t *)anonymous_shared_allocate(sizeof(pid_t)*torture_nprocs);
15329 if (!child_status) {
15330 printf("Failed to setup shared memory\n");
15334 child_status_out = (volatile bool *)anonymous_shared_allocate(sizeof(bool)*torture_nprocs);
15335 if (!child_status_out) {
15336 printf("Failed to setup result status shared memory\n");
15340 for (i = 0; i < torture_nprocs; i++) {
15341 child_status[i] = 0;
15342 child_status_out[i] = True;
15345 start = timeval_current();
15347 for (i=0;i<torture_nprocs;i++) {
15350 pid_t mypid = getpid();
15351 sys_srandom(((int)mypid) ^ ((int)time(NULL)));
15353 slprintf(myname,sizeof(myname),"CLIENT%d", i);
15356 if (torture_open_connection(¤t_cli, i)) break;
15357 if (tries-- == 0) {
15358 printf("pid %d failed to start\n", (int)getpid());
15364 child_status[i] = getpid();
15366 while (child_status[i] && timeval_elapsed(&start) < 5) smb_msleep(2);
15368 child_status_out[i] = fn(i);
15375 for (i=0;i<torture_nprocs;i++) {
15376 if (child_status[i]) synccount++;
15378 if (synccount == torture_nprocs) break;
15380 } while (timeval_elapsed(&start) < 30);
15382 if (synccount != torture_nprocs) {
15383 printf("FAILED TO START %d CLIENTS (started %d)\n", torture_nprocs, synccount);
15385 return timeval_elapsed(&start);
15388 /* start the client load */
15389 start = timeval_current();
15391 for (i=0;i<torture_nprocs;i++) {
15392 child_status[i] = 0;
15395 printf("%d clients started\n", torture_nprocs);
15397 for (i=0;i<torture_nprocs;i++) {
15398 while (waitpid(0, &status, 0) == -1 && errno == EINTR) /* noop */ ;
15403 for (i=0;i<torture_nprocs;i++) {
15404 if (!child_status_out[i]) {
15408 return timeval_elapsed(&start);
15411 #define FLAG_MULTIPROC 1
15417 } torture_ops[] = {
15420 .fn = run_fdpasstest,
15424 .fn = run_locktest1,
15428 .fn = run_locktest2,
15432 .fn = run_locktest3,
15436 .fn = run_locktest4,
15440 .fn = run_locktest5,
15444 .fn = run_locktest6,
15448 .fn = run_locktest7,
15452 .fn = run_locktest8,
15456 .fn = run_locktest9a,
15460 .fn = run_locktest9b,
15464 .fn = run_locktest10,
15468 .fn = run_locktest11,
15472 .fn = run_locktest12,
15476 .fn = run_locktest13,
15480 .fn = run_unlinktest,
15484 .fn = run_browsetest,
15488 .fn = run_attrtest,
15492 .fn = run_trans2test,
15496 .fn = run_maxfidtest,
15497 .flags = FLAG_MULTIPROC,
15502 .flags = FLAG_MULTIPROC,
15505 .name = "RANDOMIPC",
15506 .fn = run_randomipc,
15509 .name = "NEGNOWAIT",
15510 .fn = run_negprot_nowait,
15532 #ifdef HAVE_KERNEL_OPLOCKS_LINUX
15544 .fn = run_dirtest1,
15547 .name = "DIR-CREATETIME",
15548 .fn = run_dir_createtime,
15552 .fn = torture_denytest1,
15556 .fn = torture_denytest2,
15560 .fn = run_tcon_test,
15564 .fn = run_tcon_devtype_test,
15568 .fn = run_readwritetest,
15572 .fn = run_readwritemulti,
15573 .flags = FLAG_MULTIPROC
15577 .fn = run_readwritelarge,
15580 .name = "RW-SIGNING",
15581 .fn = run_readwritelarge_signtest,
15585 .fn = run_opentest,
15589 .fn = run_simple_posix_open_test,
15592 .name = "POSIX-APPEND",
15593 .fn = run_posix_append,
15596 .name = "POSIX-SYMLINK-ACL",
15597 .fn = run_acl_symlink_test,
15600 .name = "POSIX-SYMLINK-EA",
15601 .fn = run_ea_symlink_test,
15604 .name = "POSIX-STREAM-DELETE",
15605 .fn = run_posix_stream_delete,
15608 .name = "POSIX-OFD-LOCK",
15609 .fn = run_posix_ofd_lock_test,
15612 .name = "POSIX-BLOCKING-LOCK",
15613 .fn = run_posix_blocking_lock,
15616 .name = "POSIX-MKDIR",
15617 .fn = run_posix_mkdir_test,
15620 .name = "POSIX-ACL-OPLOCK",
15621 .fn = run_posix_acl_oplock_test,
15624 .name = "POSIX-ACL-SHAREROOT",
15625 .fn = run_posix_acl_shareroot_test,
15628 .name = "POSIX-LS-WILDCARD",
15629 .fn = run_posix_ls_wildcard_test,
15632 .name = "POSIX-LS-SINGLE",
15633 .fn = run_posix_ls_single_test,
15636 .name = "POSIX-READLINK",
15637 .fn = run_posix_readlink_test,
15640 .name = "POSIX-STAT",
15641 .fn = run_posix_stat_test,
15644 .name = "POSIX-SYMLINK-PARENT",
15645 .fn = run_posix_symlink_parent_test,
15648 .name = "POSIX-SYMLINK-CHMOD",
15649 .fn = run_posix_symlink_chmod_test,
15652 .name = "POSIX-SYMLINK-RENAME",
15653 .fn = run_posix_symlink_rename_test,
15656 .name = "POSIX-DIR-DEFAULT-ACL",
15657 .fn = run_posix_dir_default_acl_test,
15660 .name = "POSIX-SYMLINK-GETPATHINFO",
15661 .fn = run_posix_symlink_getpathinfo_test,
15664 .name = "POSIX-SYMLINK-SETPATHINFO",
15665 .fn = run_posix_symlink_setpathinfo_test,
15668 .name = "WINDOWS-BAD-SYMLINK",
15669 .fn = run_symlink_open_test,
15672 .name = "SMB1-WILD-MANGLE-UNLINK",
15673 .fn = run_smb1_wild_mangle_unlink_test,
15676 .name = "SMB1-WILD-MANGLE-RENAME",
15677 .fn = run_smb1_wild_mangle_rename_test,
15680 .name = "CASE-INSENSITIVE-CREATE",
15681 .fn = run_case_insensitive_create,
15684 .name = "ASYNC-ECHO",
15685 .fn = run_async_echo,
15688 .name = "UID-REGRESSION-TEST",
15689 .fn = run_uid_regression_test,
15692 .name = "SHORTNAME-TEST",
15693 .fn = run_shortname_test,
15696 .name = "ADDRCHANGE",
15697 .fn = run_addrchange,
15701 .name = "OPENATTR",
15702 .fn = run_openattrtest,
15714 .name = "RENAME-ACCESS",
15715 .fn = run_rename_access,
15718 .name = "OWNER-RIGHTS",
15719 .fn = run_owner_rights,
15723 .fn = run_deletetest,
15726 .name = "DELETE-STREAM",
15727 .fn = run_delete_stream,
15730 .name = "DELETE-PRINT",
15731 .fn = run_delete_print_test,
15734 .name = "DELETE-LN",
15735 .fn = run_deletetest_ln,
15738 .name = "PROPERTIES",
15739 .fn = run_properties,
15743 .fn = torture_mangle,
15750 .name = "MANGLE-ILLEGAL",
15751 .fn = run_mangle_illegal,
15758 .name = "TRANS2SCAN",
15759 .fn = torture_trans2_scan,
15762 .name = "NTTRANSSCAN",
15763 .fn = torture_nttrans_scan,
15767 .fn = torture_utable,
15770 .name = "CASETABLE",
15771 .fn = torture_casetable,
15774 .name = "ERRMAPEXTRACT",
15775 .fn = run_error_map_extract,
15778 .name = "PIPE_NUMBER",
15779 .fn = run_pipe_number,
15783 .fn = run_tcon2_test,
15787 .fn = torture_ioctl_test,
15791 .fn = torture_chkpath_test,
15795 .fn = run_fdsesstest,
15802 .name = "SESSSETUP_BENCH",
15803 .fn = run_sesssetup_bench,
15818 .name = "WINDOWS-WRITE",
15819 .fn = run_windows_write,
15822 .name = "LARGE_READX",
15823 .fn = run_large_readx,
15826 .name = "MSDFS-ATTRIBUTE",
15827 .fn = run_msdfs_attribute,
15830 .name = "NTTRANS-CREATE",
15831 .fn = run_nttrans_create,
15834 .name = "NTTRANS-FSCTL",
15835 .fn = run_nttrans_fsctl,
15838 .name = "CLI_ECHO",
15839 .fn = run_cli_echo,
15842 .name = "CLI_SPLICE",
15843 .fn = run_cli_splice,
15850 .name = "STREAMERROR",
15851 .fn = run_streamerror,
15854 .name = "NOTIFY-BENCH",
15855 .fn = run_notify_bench,
15858 .name = "NOTIFY-BENCH2",
15859 .fn = run_notify_bench2,
15862 .name = "NOTIFY-BENCH3",
15863 .fn = run_notify_bench3,
15866 .name = "BAD-NBT-SESSION",
15867 .fn = run_bad_nbt_session,
15870 .name = "IGN-BAD-NEGPROT",
15871 .fn = run_ign_bad_negprot,
15874 .name = "SMB-ANY-CONNECT",
15875 .fn = run_smb_any_connect,
15878 .name = "NOTIFY-ONLINE",
15879 .fn = run_notify_online,
15882 .name = "SMB2-BASIC",
15883 .fn = run_smb2_basic,
15886 .name = "SMB2-NEGPROT",
15887 .fn = run_smb2_negprot,
15890 .name = "SMB2-ANONYMOUS",
15891 .fn = run_smb2_anonymous,
15894 .name = "SMB2-SESSION-RECONNECT",
15895 .fn = run_smb2_session_reconnect,
15898 .name = "SMB2-TCON-DEPENDENCE",
15899 .fn = run_smb2_tcon_dependence,
15902 .name = "SMB2-MULTI-CHANNEL",
15903 .fn = run_smb2_multi_channel,
15906 .name = "SMB2-SESSION-REAUTH",
15907 .fn = run_smb2_session_reauth,
15910 .name = "SMB2-FTRUNCATE",
15911 .fn = run_smb2_ftruncate,
15914 .name = "SMB2-DIR-FSYNC",
15915 .fn = run_smb2_dir_fsync,
15918 .name = "SMB2-PATH-SLASH",
15919 .fn = run_smb2_path_slash,
15922 .name = "SMB1-SYSTEM-SECURITY",
15923 .fn = run_smb1_system_security,
15926 .name = "SMB2-SACL",
15927 .fn = run_smb2_sacl,
15930 .name = "SMB2-QUOTA1",
15931 .fn = run_smb2_quota1,
15934 .name = "SMB2-INVALID-PIPENAME",
15935 .fn = run_smb2_invalid_pipename,
15938 .name = "SMB2-STREAM-ACL",
15939 .fn = run_smb2_stream_acl,
15942 .name = "SMB2-LIST-DIR-ASYNC",
15943 .fn = run_list_dir_async_test,
15946 .name = "SMB2-DEL-ON-CLOSE-NONEMPTY",
15947 .fn = run_delete_on_close_non_empty,
15950 .name = "SMB2-DEL-ON-CLOSE-NONWRITE-DELETE-YES",
15951 .fn = run_delete_on_close_nonwrite_delete_yes_test,
15954 .name = "SMB2-DEL-ON-CLOSE-NONWRITE-DELETE-NO",
15955 .fn = run_delete_on_close_nonwrite_delete_no_test,
15958 .name = "SMB2-DFS-PATHS",
15959 .fn = run_smb2_dfs_paths,
15962 .name = "SMB2-NON-DFS-SHARE",
15963 .fn = run_smb2_non_dfs_share,
15966 .name = "SMB2-DFS-SHARE-NON-DFS-PATH",
15967 .fn = run_smb2_dfs_share_non_dfs_path,
15970 .name = "SMB2-DFS-FILENAME-LEADING-BACKSLASH",
15971 .fn = run_smb2_dfs_filename_leading_backslash,
15974 .name = "SMB2-PIPE-READ-ASYNC-DISCONNECT",
15975 .fn = run_smb2_pipe_read_async_disconnect,
15978 .name = "SMB1-TRUNCATED-SESSSETUP",
15979 .fn = run_smb1_truncated_sesssetup,
15982 .name = "SMB1-NEGOTIATE-EXIT",
15983 .fn = run_smb1_negotiate_exit,
15986 .name = "SMB1-NEGOTIATE-TCON",
15987 .fn = run_smb1_negotiate_tcon,
15990 .name = "SMB1-DFS-PATHS",
15991 .fn = run_smb1_dfs_paths,
15994 .name = "SMB1-DFS-SEARCH-PATHS",
15995 .fn = run_smb1_dfs_search_paths,
15998 .name = "SMB1-DFS-OPERATIONS",
15999 .fn = run_smb1_dfs_operations,
16002 .name = "SMB1-DFS-BADPATH",
16003 .fn = run_smb1_dfs_check_badpath,
16006 .name = "CLEANUP1",
16007 .fn = run_cleanup1,
16010 .name = "CLEANUP2",
16011 .fn = run_cleanup2,
16014 .name = "CLEANUP4",
16015 .fn = run_cleanup4,
16018 .name = "OPLOCK-CANCEL",
16019 .fn = run_oplock_cancel,
16026 .name = "LOCAL-SUBSTITUTE",
16027 .fn = run_local_substitute,
16030 .name = "LOCAL-GENCACHE",
16031 .fn = run_local_gencache,
16034 .name = "LOCAL-DBWRAP-WATCH1",
16035 .fn = run_dbwrap_watch1,
16038 .name = "LOCAL-DBWRAP-WATCH2",
16039 .fn = run_dbwrap_watch2,
16042 .name = "LOCAL-DBWRAP-WATCH3",
16043 .fn = run_dbwrap_watch3,
16046 .name = "LOCAL-DBWRAP-WATCH4",
16047 .fn = run_dbwrap_watch4,
16050 .name = "LOCAL-DBWRAP-DO-LOCKED1",
16051 .fn = run_dbwrap_do_locked1,
16054 .name = "LOCAL-MESSAGING-READ1",
16055 .fn = run_messaging_read1,
16058 .name = "LOCAL-MESSAGING-READ2",
16059 .fn = run_messaging_read2,
16062 .name = "LOCAL-MESSAGING-READ3",
16063 .fn = run_messaging_read3,
16066 .name = "LOCAL-MESSAGING-READ4",
16067 .fn = run_messaging_read4,
16070 .name = "LOCAL-MESSAGING-FDPASS1",
16071 .fn = run_messaging_fdpass1,
16074 .name = "LOCAL-MESSAGING-FDPASS2",
16075 .fn = run_messaging_fdpass2,
16078 .name = "LOCAL-MESSAGING-FDPASS2a",
16079 .fn = run_messaging_fdpass2a,
16082 .name = "LOCAL-MESSAGING-FDPASS2b",
16083 .fn = run_messaging_fdpass2b,
16086 .name = "LOCAL-MESSAGING-SEND-ALL",
16087 .fn = run_messaging_send_all,
16090 .name = "LOCAL-BASE64",
16091 .fn = run_local_base64,
16094 .name = "LOCAL-RBTREE",
16095 .fn = run_local_rbtree,
16098 .name = "LOCAL-MEMCACHE",
16099 .fn = run_local_memcache,
16102 .name = "LOCAL-STREAM-NAME",
16103 .fn = run_local_stream_name,
16106 .name = "LOCAL-STR-MATCH-MSWILD",
16107 .fn = run_str_match_mswild,
16110 .name = "LOCAL-STR-MATCH-REGEX-SUB1",
16111 .fn = run_str_match_regex_sub1,
16114 .name = "WBCLIENT-MULTI-PING",
16115 .fn = run_wbclient_multi_ping,
16118 .name = "LOCAL-string_to_sid",
16119 .fn = run_local_string_to_sid,
16122 .name = "LOCAL-sid_to_string",
16123 .fn = run_local_sid_to_string,
16126 .name = "LOCAL-binary_to_sid",
16127 .fn = run_local_binary_to_sid,
16130 .name = "LOCAL-DBTRANS",
16131 .fn = run_local_dbtrans,
16134 .name = "LOCAL-TEVENT-POLL",
16135 .fn = run_local_tevent_poll,
16138 .name = "LOCAL-CONVERT-STRING",
16139 .fn = run_local_convert_string,
16142 .name = "LOCAL-CONV-AUTH-INFO",
16143 .fn = run_local_conv_auth_info,
16146 .name = "LOCAL-hex_encode_buf",
16147 .fn = run_local_hex_encode_buf,
16150 .name = "LOCAL-IDMAP-TDB-COMMON",
16151 .fn = run_idmap_tdb_common_test,
16154 .name = "LOCAL-remove_duplicate_addrs2",
16155 .fn = run_local_remove_duplicate_addrs2,
16158 .name = "local-tdb-opener",
16159 .fn = run_local_tdb_opener,
16162 .name = "local-tdb-writer",
16163 .fn = run_local_tdb_writer,
16166 .name = "LOCAL-DBWRAP-CTDB1",
16167 .fn = run_local_dbwrap_ctdb1,
16170 .name = "LOCAL-BENCH-PTHREADPOOL",
16171 .fn = run_bench_pthreadpool,
16174 .name = "LOCAL-PTHREADPOOL-TEVENT",
16175 .fn = run_pthreadpool_tevent,
16178 .name = "LOCAL-G-LOCK1",
16182 .name = "LOCAL-G-LOCK2",
16186 .name = "LOCAL-G-LOCK3",
16190 .name = "LOCAL-G-LOCK4",
16194 .name = "LOCAL-G-LOCK4A",
16195 .fn = run_g_lock4a,
16198 .name = "LOCAL-G-LOCK5",
16202 .name = "LOCAL-G-LOCK6",
16206 .name = "LOCAL-G-LOCK7",
16210 .name = "LOCAL-G-LOCK8",
16214 .name = "LOCAL-G-LOCK-PING-PONG",
16215 .fn = run_g_lock_ping_pong,
16218 .name = "LOCAL-CANONICALIZE-PATH",
16219 .fn = run_local_canonicalize_path,
16222 .name = "LOCAL-NAMEMAP-CACHE1",
16223 .fn = run_local_namemap_cache1,
16226 .name = "LOCAL-IDMAP-CACHE1",
16227 .fn = run_local_idmap_cache1,
16230 .name = "qpathinfo-bufsize",
16231 .fn = run_qpathinfo_bufsize,
16234 .name = "hide-new-files-timeout",
16235 .fn = run_hidenewfiles,
16238 .name = "hide-new-files-timeout-showdirs",
16239 .fn = run_hidenewfiles_showdirs,
16241 #ifdef CLUSTER_SUPPORT
16243 .name = "ctdbd-conn1",
16244 .fn = run_ctdbd_conn1,
16248 .name = "readdir-timestamp",
16249 .fn = run_readdir_timestamp,
16252 .name = "rpc-scale",
16253 .fn = run_rpc_scale,
16256 .name = "LOCAL-TDB-VALIDATE",
16257 .fn = run_tdb_validate,
16264 /****************************************************************************
16265 run a specified test or "ALL"
16266 ****************************************************************************/
16267 static bool run_test(const char *name)
16270 bool result = True;
16271 bool found = False;
16274 if (strequal(name,"ALL")) {
16275 for (i=0;torture_ops[i].name;i++) {
16276 run_test(torture_ops[i].name);
16281 for (i=0;torture_ops[i].name;i++) {
16282 fstr_sprintf(randomfname, "\\XX%x",
16283 (unsigned)random());
16285 if (strequal(name, torture_ops[i].name)) {
16287 printf("Running %s\n", name);
16288 if (torture_ops[i].flags & FLAG_MULTIPROC) {
16289 t = create_procs(torture_ops[i].fn, &result);
16292 printf("TEST %s FAILED!\n", name);
16295 struct timeval start;
16296 start = timeval_current();
16297 if (!torture_ops[i].fn(0)) {
16299 printf("TEST %s FAILED!\n", name);
16301 t = timeval_elapsed(&start);
16303 printf("%s took %g secs\n\n", name, t);
16308 printf("Did not find a test named %s\n", name);
16316 static void usage(void)
16320 printf("WARNING samba4 test suite is much more complete nowadays.\n");
16321 printf("Please use samba4 torture.\n\n");
16323 printf("Usage: smbtorture //server/share <options> TEST1 TEST2 ...\n");
16325 printf("\t-d debuglevel\n");
16326 printf("\t-U user%%pass\n");
16327 printf("\t-k use kerberos\n");
16328 printf("\t-N numprocs\n");
16329 printf("\t-n my_netbios_name\n");
16330 printf("\t-W workgroup\n");
16331 printf("\t-o num_operations\n");
16332 printf("\t-O socket_options\n");
16333 printf("\t-m maximum protocol\n");
16334 printf("\t-L use oplocks\n");
16335 printf("\t-c CLIENT.TXT specify client load file for NBENCH\n");
16336 printf("\t-A showall\n");
16337 printf("\t-p port\n");
16338 printf("\t-s seed\n");
16339 printf("\t-b unclist_filename specify multiple shares for multiple connections\n");
16340 printf("\t-f filename filename to test\n");
16341 printf("\t-e encrypt\n");
16342 printf("\t-T 'OPTION=VALUE' smb.conf option line\n");
16345 printf("tests are:");
16346 for (i=0;torture_ops[i].name;i++) {
16347 printf(" %s", torture_ops[i].name);
16351 printf("default test is ALL\n");
16356 /****************************************************************************
16358 ****************************************************************************/
16359 int main(int argc,char *argv[])
16365 bool correct = True;
16366 TALLOC_CTX *frame = talloc_stackframe();
16367 int seed = time(NULL);
16368 struct loadparm_context *lp_ctx = NULL;
16370 #ifdef HAVE_SETBUFFER
16371 setbuffer(stdout, NULL, 0);
16374 setup_logging("smbtorture", DEBUG_STDOUT);
16379 lp_ctx = loadparm_init_s3(frame, loadparm_s3_helpers());
16380 if (lp_ctx == NULL) {
16382 "Failed to initialise the global parameter structure.\n");
16386 if (is_default_dyn_CONFIGFILE()) {
16387 if(getenv("SMB_CONF_PATH")) {
16388 set_dyn_CONFIGFILE(getenv("SMB_CONF_PATH"));
16391 lp_load_global(get_dyn_CONFIGFILE());
16398 for(p = argv[1]; *p; p++)
16402 if (strncmp(argv[1], "//", 2)) {
16406 fstrcpy(host, &argv[1][2]);
16407 p = strchr_m(&host[2],'/');
16412 fstrcpy(share, p+1);
16414 fstrcpy(myname, get_myname(talloc_tos()));
16416 fprintf(stderr, "Failed to get my hostname.\n");
16420 if (*username == 0 && getenv("LOGNAME")) {
16421 fstrcpy(username,getenv("LOGNAME"));
16427 fstrcpy(workgroup, lp_workgroup());
16429 while ((opt = getopt(argc, argv, "p:hW:U:n:N:O:o:m:Ll:d:Aec:ks:b:B:f:T:"))
16433 port_to_use = atoi(optarg);
16436 seed = atoi(optarg);
16439 fstrcpy(workgroup,optarg);
16442 lpcfg_set_cmdline(lp_ctx, "client max protocol", optarg);
16445 torture_nprocs = atoi(optarg);
16448 torture_numops = atoi(optarg);
16451 lpcfg_set_cmdline(lp_ctx, "log level", optarg);
16457 use_oplocks = True;
16460 local_path = optarg;
16463 torture_showall = True;
16466 fstrcpy(myname, optarg);
16469 client_txt = optarg;
16476 use_kerberos = True;
16478 d_printf("No kerberos support compiled in\n");
16484 fstrcpy(username,optarg);
16485 p = strchr_m(username,'%');
16488 fstrcpy(password, p+1);
16493 fstrcpy(multishare_conn_fname, optarg);
16494 use_multishare_conn = True;
16497 torture_blocksize = atoi(optarg);
16500 test_filename = SMB_STRDUP(optarg);
16503 lpcfg_set_option(lp_ctx, optarg);
16506 printf("Unknown option %c (%d)\n", (char)opt, opt);
16511 d_printf("using seed %d\n", seed);
16515 if(use_kerberos && !gotuser) gotpass = True;
16518 char pwd[256] = {0};
16521 rc = samba_getpass("Password:", pwd, sizeof(pwd), false, false);
16523 fstrcpy(password, pwd);
16528 printf("host=%s share=%s user=%s myname=%s\n",
16529 host, share, username, myname);
16531 torture_creds = cli_session_creds_init(frame,
16537 false, /* fallback_after_kerberos */
16538 false, /* use_ccache */
16539 false); /* password_is_nt_hash */
16540 if (torture_creds == NULL) {
16541 d_printf("cli_session_creds_init() failed.\n");
16545 if (argc == optind) {
16546 correct = run_test("ALL");
16548 for (i=optind;i<argc;i++) {
16549 if (!run_test(argv[i])) {
16555 TALLOC_FREE(frame);