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(NULL,
362 if (!NT_STATUS_IS_OK(status)) {
363 printf("failed to open share connection: //%s/%s port:%d - %s\n",
364 hostname, sharename, port_to_use, nt_errstr(status));
368 cli_set_timeout(*c, 120000); /* set a really long timeout (2 minutes) */
371 return force_cli_encryption(*c,
377 bool torture_open_connection_flags(struct cli_state **c, int conn_index, int flags)
379 char **unc_list = NULL;
380 int num_unc_names = 0;
383 if (use_multishare_conn==True) {
385 unc_list = file_lines_load(multishare_conn_fname, &num_unc_names, 0, NULL);
386 if (!unc_list || num_unc_names <= 0) {
387 printf("Failed to load unc names list from '%s'\n", multishare_conn_fname);
391 if (!smbcli_parse_unc(unc_list[conn_index % num_unc_names],
393 printf("Failed to parse UNC name %s\n",
394 unc_list[conn_index % num_unc_names]);
395 TALLOC_FREE(unc_list);
399 result = torture_open_connection_share(c, h, s, flags);
401 /* h, s were copied earlier */
402 TALLOC_FREE(unc_list);
406 return torture_open_connection_share(c, host, share, flags);
409 bool torture_open_connection(struct cli_state **c, int conn_index)
411 int flags = CLI_FULL_CONNECTION_FORCE_SMB1;
414 flags |= CLI_FULL_CONNECTION_OPLOCKS;
416 if (use_level_II_oplocks) {
417 flags |= CLI_FULL_CONNECTION_LEVEL_II_OPLOCKS;
420 return torture_open_connection_flags(c, conn_index, flags);
423 bool torture_init_connection(struct cli_state **pcli)
425 struct cli_state *cli;
427 cli = open_nbt_connection();
436 bool torture_cli_session_setup2(struct cli_state *cli, uint16_t *new_vuid)
438 uint16_t old_vuid = cli_state_get_uid(cli);
442 cli_state_set_uid(cli, 0);
443 status = cli_session_setup_creds(cli, torture_creds);
444 ret = NT_STATUS_IS_OK(status);
445 *new_vuid = cli_state_get_uid(cli);
446 cli_state_set_uid(cli, old_vuid);
451 bool torture_close_connection(struct cli_state *c)
456 status = cli_tdis(c);
457 if (!NT_STATUS_IS_OK(status)) {
458 printf("tdis failed (%s)\n", nt_errstr(status));
467 void torture_conn_set_sockopt(struct cli_state *cli)
469 smbXcli_conn_set_sockopt(cli->conn, sockops);
472 static NTSTATUS torture_delete_fn(struct file_info *finfo,
477 char *filename = NULL;
478 char *dirname = NULL;
480 TALLOC_CTX *frame = talloc_stackframe();
481 struct cli_state *cli = (struct cli_state *)state;
483 if (ISDOT(finfo->name) || ISDOTDOT(finfo->name)) {
488 dirname = talloc_strdup(frame, pattern);
489 if (dirname == NULL) {
491 return NT_STATUS_NO_MEMORY;
493 p = strrchr_m(dirname, '\\');
495 /* Remove the terminating '\' */
498 if (dirname[0] != '\0') {
499 filename = talloc_asprintf(frame,
504 filename = talloc_asprintf(frame,
508 if (filename == NULL) {
510 return NT_STATUS_NO_MEMORY;
512 if (finfo->attr & FILE_ATTRIBUTE_DIRECTORY) {
513 char *subdirname = talloc_asprintf(frame,
516 if (subdirname == NULL) {
518 return NT_STATUS_NO_MEMORY;
520 status = cli_list(cli,
522 FILE_ATTRIBUTE_DIRECTORY |
523 FILE_ATTRIBUTE_HIDDEN |
524 FILE_ATTRIBUTE_SYSTEM,
527 if (!NT_STATUS_IS_OK(status)) {
528 printf("torture_delete_fn: cli_list "
529 "of %s failed (%s)\n",
535 status = cli_rmdir(cli, filename);
537 status = cli_unlink(cli,
539 FILE_ATTRIBUTE_SYSTEM |
540 FILE_ATTRIBUTE_HIDDEN);
542 if (!NT_STATUS_IS_OK(status)) {
543 if (finfo->attr & FILE_ATTRIBUTE_DIRECTORY) {
544 printf("torture_delete_fn: cli_rmdir"
545 " of %s failed (%s)\n",
549 printf("torture_delete_fn: cli_unlink"
550 " of %s failed (%s)\n",
559 void torture_deltree(struct cli_state *cli, const char *dname)
564 /* It might be a file */
565 (void)cli_unlink(cli,
567 FILE_ATTRIBUTE_SYSTEM |
568 FILE_ATTRIBUTE_HIDDEN);
570 mask = talloc_asprintf(cli,
574 printf("torture_deltree: talloc_asprintf failed\n");
578 status = cli_list(cli,
580 FILE_ATTRIBUTE_DIRECTORY |
581 FILE_ATTRIBUTE_HIDDEN|
582 FILE_ATTRIBUTE_SYSTEM,
585 if (!NT_STATUS_IS_OK(status)) {
586 printf("torture_deltree: cli_list of %s failed (%s)\n",
591 status = cli_rmdir(cli, dname);
592 if (!NT_STATUS_IS_OK(status)) {
593 printf("torture_deltree: cli_rmdir of %s failed (%s)\n",
599 /* check if the server produced the expected dos or nt error code */
600 static bool check_both_error(int line, NTSTATUS status,
601 uint8_t eclass, uint32_t ecode, NTSTATUS nterr)
603 if (NT_STATUS_IS_DOS(status)) {
607 /* Check DOS error */
608 cclass = NT_STATUS_DOS_CLASS(status);
609 num = NT_STATUS_DOS_CODE(status);
611 if (eclass != cclass || ecode != num) {
612 printf("unexpected error code class=%d code=%d\n",
613 (int)cclass, (int)num);
614 printf(" expected %d/%d %s (line=%d)\n",
615 (int)eclass, (int)ecode, nt_errstr(nterr), line);
620 if (!NT_STATUS_EQUAL(nterr, status)) {
621 printf("unexpected error code %s\n",
623 printf(" expected %s (line=%d)\n",
624 nt_errstr(nterr), line);
633 /* check if the server produced the expected error code */
634 static bool check_error(int line, NTSTATUS status,
635 uint8_t eclass, uint32_t ecode, NTSTATUS nterr)
637 if (NT_STATUS_IS_DOS(status)) {
641 /* Check DOS error */
643 cclass = NT_STATUS_DOS_CLASS(status);
644 num = NT_STATUS_DOS_CODE(status);
646 if (eclass != cclass || ecode != num) {
647 printf("unexpected error code class=%d code=%d\n",
648 (int)cclass, (int)num);
649 printf(" expected %d/%d %s (line=%d)\n",
650 (int)eclass, (int)ecode, nt_errstr(nterr),
658 if (NT_STATUS_V(nterr) != NT_STATUS_V(status)) {
659 printf("unexpected error code %s\n",
661 printf(" expected %s (line=%d)\n", nt_errstr(nterr),
670 NTSTATUS cli_qpathinfo1(struct cli_state *cli,
678 int timezone = smb1cli_conn_server_time_zone(cli->conn);
679 time_t (*date_fn)(const void *buf, int serverzone) = NULL;
680 uint8_t *rdata = NULL;
684 status = cli_qpathinfo(talloc_tos(),
692 if (!NT_STATUS_IS_OK(status)) {
696 date_fn = make_unix_date;
698 date_fn = make_unix_date2;
702 *change_time = date_fn(rdata + 0, timezone);
705 *access_time = date_fn(rdata + 4, timezone);
708 *write_time = date_fn(rdata + 8, timezone);
711 *size = PULL_LE_U32(rdata, 12);
714 *pattr = PULL_LE_U16(rdata, l1_attrFile);
719 static bool wait_lock(struct cli_state *c, int fnum, uint32_t offset, uint32_t len)
723 status = cli_lock32(c, fnum, offset, len, -1, WRITE_LOCK);
725 while (!NT_STATUS_IS_OK(status)) {
726 if (!check_both_error(__LINE__, status, ERRDOS,
727 ERRlock, NT_STATUS_LOCK_NOT_GRANTED)) {
731 status = cli_lock32(c, fnum, offset, len, -1, WRITE_LOCK);
738 static bool rw_torture(struct cli_state *c)
740 const char *lockfname = "\\torture.lck";
744 pid_t pid2, pid = getpid();
751 memset(buf, '\0', sizeof(buf));
753 status = cli_openx(c, lockfname, O_RDWR | O_CREAT | O_EXCL,
755 if (!NT_STATUS_IS_OK(status)) {
756 status = cli_openx(c, lockfname, O_RDWR, DENY_NONE, &fnum2);
758 if (!NT_STATUS_IS_OK(status)) {
759 printf("open of %s failed (%s)\n",
760 lockfname, nt_errstr(status));
764 for (i=0;i<torture_numops;i++) {
765 unsigned n = (unsigned)sys_random()%10;
768 printf("%d\r", i); fflush(stdout);
770 slprintf(fname, sizeof(fstring) - 1, "\\torture.%u", n);
772 if (!wait_lock(c, fnum2, n*sizeof(int), sizeof(int))) {
776 status = cli_openx(c, fname, O_RDWR | O_CREAT | O_TRUNC,
778 if (!NT_STATUS_IS_OK(status)) {
779 printf("open failed (%s)\n", nt_errstr(status));
784 status = cli_writeall(c, fnum, 0, (uint8_t *)&pid, 0,
786 if (!NT_STATUS_IS_OK(status)) {
787 printf("write failed (%s)\n", nt_errstr(status));
792 status = cli_writeall(c, fnum, 0, (uint8_t *)buf,
793 sizeof(pid)+(j*sizeof(buf)),
795 if (!NT_STATUS_IS_OK(status)) {
796 printf("write failed (%s)\n",
804 status = cli_read(c, fnum, (char *)&pid2, 0, sizeof(pid),
806 if (!NT_STATUS_IS_OK(status)) {
807 printf("read failed (%s)\n", nt_errstr(status));
809 } else if (nread != sizeof(pid)) {
810 printf("read/write compare failed: "
811 "recv %ld req %ld\n", (unsigned long)nread,
812 (unsigned long)sizeof(pid));
817 printf("data corruption!\n");
821 status = cli_close(c, fnum);
822 if (!NT_STATUS_IS_OK(status)) {
823 printf("close failed (%s)\n", nt_errstr(status));
827 status = cli_unlink(c, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
828 if (!NT_STATUS_IS_OK(status)) {
829 printf("unlink failed (%s)\n", nt_errstr(status));
833 status = cli_unlock(c, fnum2, n*sizeof(int), sizeof(int));
834 if (!NT_STATUS_IS_OK(status)) {
835 printf("unlock failed (%s)\n", nt_errstr(status));
841 cli_unlink(c, lockfname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
848 static bool run_torture(int dummy)
850 struct cli_state *cli;
855 smbXcli_conn_set_sockopt(cli->conn, sockops);
857 ret = rw_torture(cli);
859 if (!torture_close_connection(cli)) {
866 static bool rw_torture3(struct cli_state *c, char *lockfname)
868 uint16_t fnum = (uint16_t)-1;
873 unsigned countprev = 0;
876 NTSTATUS status = NT_STATUS_OK;
879 for (i = 0; i < sizeof(buf); i += sizeof(uint32_t))
881 SIVAL(buf, i, sys_random());
888 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
889 if (!NT_STATUS_IS_OK(status)) {
890 printf("unlink failed (%s) (normal, this file should "
891 "not exist)\n", nt_errstr(status));
894 status = cli_openx(c, lockfname, O_RDWR | O_CREAT | O_EXCL,
896 if (!NT_STATUS_IS_OK(status)) {
897 printf("first open read/write of %s failed (%s)\n",
898 lockfname, nt_errstr(status));
904 for (i = 0; i < 500 && fnum == (uint16_t)-1; i++)
906 status = cli_openx(c, lockfname, O_RDONLY,
908 if (NT_STATUS_IS_OK(status)) {
913 if (!NT_STATUS_IS_OK(status)) {
914 printf("second open read-only of %s failed (%s)\n",
915 lockfname, nt_errstr(status));
921 for (count = 0; count < sizeof(buf); count += sent)
923 if (count >= countprev) {
924 printf("%d %8d\r", i, count);
927 countprev += (sizeof(buf) / 20);
932 sent = ((unsigned)sys_random()%(20))+ 1;
933 if (sent > sizeof(buf) - count)
935 sent = sizeof(buf) - count;
938 status = cli_writeall(c, fnum, 0, (uint8_t *)buf+count,
940 if (!NT_STATUS_IS_OK(status)) {
941 printf("write failed (%s)\n",
948 status = cli_read(c, fnum, buf_rd+count, count,
949 sizeof(buf)-count, &sent);
950 if(!NT_STATUS_IS_OK(status)) {
951 printf("read failed offset:%d size:%ld (%s)\n",
952 count, (unsigned long)sizeof(buf)-count,
956 } else if (sent > 0) {
957 if (memcmp(buf_rd+count, buf+count, sent) != 0)
959 printf("read/write compare failed\n");
960 printf("offset: %d req %ld recvd %ld\n", count, (unsigned long)sizeof(buf)-count, (unsigned long)sent);
969 status = cli_close(c, fnum);
970 if (!NT_STATUS_IS_OK(status)) {
971 printf("close failed (%s)\n", nt_errstr(status));
978 static bool rw_torture2(struct cli_state *c1, struct cli_state *c2)
980 const char *lockfname = "\\torture2.lck";
990 status = cli_unlink(c1, lockfname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
991 if (!NT_STATUS_IS_OK(status)) {
992 printf("unlink failed (%s) (normal, this file should not exist)\n", nt_errstr(status));
995 status = cli_openx(c1, lockfname, O_RDWR | O_CREAT | O_EXCL,
997 if (!NT_STATUS_IS_OK(status)) {
998 printf("first open read/write of %s failed (%s)\n",
999 lockfname, nt_errstr(status));
1003 status = cli_openx(c2, lockfname, O_RDONLY, DENY_NONE, &fnum2);
1004 if (!NT_STATUS_IS_OK(status)) {
1005 printf("second open read-only of %s failed (%s)\n",
1006 lockfname, nt_errstr(status));
1007 cli_close(c1, fnum1);
1011 for (i = 0; i < torture_numops; i++)
1013 size_t buf_size = ((unsigned)sys_random()%(sizeof(buf)-1))+ 1;
1015 printf("%d\r", i); fflush(stdout);
1018 generate_random_buffer((unsigned char *)buf, buf_size);
1020 status = cli_writeall(c1, fnum1, 0, (uint8_t *)buf, 0,
1022 if (!NT_STATUS_IS_OK(status)) {
1023 printf("write failed (%s)\n", nt_errstr(status));
1028 status = cli_read(c2, fnum2, buf_rd, 0, buf_size, &bytes_read);
1029 if(!NT_STATUS_IS_OK(status)) {
1030 printf("read failed (%s)\n", nt_errstr(status));
1033 } else if (bytes_read != buf_size) {
1034 printf("read failed\n");
1035 printf("read %ld, expected %ld\n",
1036 (unsigned long)bytes_read,
1037 (unsigned long)buf_size);
1042 if (memcmp(buf_rd, buf, buf_size) != 0)
1044 printf("read/write compare failed\n");
1050 status = cli_close(c2, fnum2);
1051 if (!NT_STATUS_IS_OK(status)) {
1052 printf("close failed (%s)\n", nt_errstr(status));
1056 status = cli_close(c1, fnum1);
1057 if (!NT_STATUS_IS_OK(status)) {
1058 printf("close failed (%s)\n", nt_errstr(status));
1062 status = cli_unlink(c1, lockfname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1063 if (!NT_STATUS_IS_OK(status)) {
1064 printf("unlink failed (%s)\n", nt_errstr(status));
1071 static bool run_readwritetest(int dummy)
1073 struct cli_state *cli1, *cli2;
1074 bool test1, test2 = False;
1076 if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
1079 smbXcli_conn_set_sockopt(cli1->conn, sockops);
1080 smbXcli_conn_set_sockopt(cli2->conn, sockops);
1082 printf("starting readwritetest\n");
1084 test1 = rw_torture2(cli1, cli2);
1085 printf("Passed readwritetest v1: %s\n", BOOLSTR(test1));
1088 test2 = rw_torture2(cli1, cli1);
1089 printf("Passed readwritetest v2: %s\n", BOOLSTR(test2));
1092 if (!torture_close_connection(cli1)) {
1096 if (!torture_close_connection(cli2)) {
1100 return (test1 && test2);
1103 static bool run_readwritemulti(int dummy)
1105 struct cli_state *cli;
1110 smbXcli_conn_set_sockopt(cli->conn, sockops);
1112 printf("run_readwritemulti: fname %s\n", randomfname);
1113 test = rw_torture3(cli, randomfname);
1115 if (!torture_close_connection(cli)) {
1122 static bool run_readwritelarge_internal(void)
1124 static struct cli_state *cli1;
1126 const char *lockfname = "\\large.dat";
1129 bool correct = True;
1132 if (!torture_open_connection(&cli1, 0)) {
1135 smbXcli_conn_set_sockopt(cli1->conn, sockops);
1136 memset(buf,'\0',sizeof(buf));
1138 printf("starting readwritelarge_internal\n");
1140 cli_unlink(cli1, lockfname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1142 status = cli_openx(cli1, lockfname, O_RDWR | O_CREAT | O_EXCL,
1144 if (!NT_STATUS_IS_OK(status)) {
1145 printf("open read/write of %s failed (%s)\n", lockfname, nt_errstr(status));
1149 cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 0, sizeof(buf), NULL);
1151 status = cli_qfileinfo_basic(cli1, fnum1, NULL, &fsize, NULL, NULL,
1153 if (!NT_STATUS_IS_OK(status)) {
1154 printf("qfileinfo failed (%s)\n", nt_errstr(status));
1158 if (fsize == sizeof(buf))
1159 printf("readwritelarge_internal test 1 succeeded (size = %lx)\n",
1160 (unsigned long)fsize);
1162 printf("readwritelarge_internal test 1 failed (size = %lx)\n",
1163 (unsigned long)fsize);
1167 status = cli_close(cli1, fnum1);
1168 if (!NT_STATUS_IS_OK(status)) {
1169 printf("close failed (%s)\n", nt_errstr(status));
1173 status = cli_unlink(cli1, lockfname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1174 if (!NT_STATUS_IS_OK(status)) {
1175 printf("unlink failed (%s)\n", nt_errstr(status));
1179 status = cli_openx(cli1, lockfname, O_RDWR | O_CREAT | O_EXCL,
1181 if (!NT_STATUS_IS_OK(status)) {
1182 printf("open read/write of %s failed (%s)\n", lockfname, nt_errstr(status));
1186 cli_smbwrite(cli1, fnum1, buf, 0, sizeof(buf), NULL);
1188 status = cli_qfileinfo_basic(cli1, fnum1, NULL, &fsize, NULL, NULL,
1190 if (!NT_STATUS_IS_OK(status)) {
1191 printf("qfileinfo failed (%s)\n", nt_errstr(status));
1195 if (fsize == sizeof(buf))
1196 printf("readwritelarge_internal test 2 succeeded (size = %lx)\n",
1197 (unsigned long)fsize);
1199 printf("readwritelarge_internal test 2 failed (size = %lx)\n",
1200 (unsigned long)fsize);
1204 status = cli_close(cli1, fnum1);
1205 if (!NT_STATUS_IS_OK(status)) {
1206 printf("close failed (%s)\n", nt_errstr(status));
1210 if (!torture_close_connection(cli1)) {
1216 static bool run_readwritelarge(int dummy)
1218 return run_readwritelarge_internal();
1221 static bool run_readwritelarge_signtest(int dummy)
1224 signing_state = SMB_SIGNING_REQUIRED;
1225 ret = run_readwritelarge_internal();
1226 signing_state = SMB_SIGNING_DEFAULT;
1233 #define ival(s) strtol(s, NULL, 0)
1235 /* run a test that simulates an approximate netbench client load */
1236 static bool run_netbench(int client)
1238 struct cli_state *cli;
1243 const char *params[20];
1244 bool correct = True;
1250 smbXcli_conn_set_sockopt(cli->conn, sockops);
1254 slprintf(cname,sizeof(cname)-1, "client%d", client);
1256 f = fopen(client_txt, "r");
1263 while (fgets(line, sizeof(line)-1, f)) {
1267 line[strlen(line)-1] = 0;
1269 /* printf("[%d] %s\n", line_count, line); */
1271 all_string_sub(line,"client1", cname, sizeof(line));
1273 /* parse the command parameters */
1274 params[0] = strtok_r(line, " ", &saveptr);
1276 while (params[i]) params[++i] = strtok_r(NULL, " ", &saveptr);
1280 if (i < 2) continue;
1282 if (!strncmp(params[0],"SMB", 3)) {
1283 printf("ERROR: You are using a dbench 1 load file\n");
1287 if (!strcmp(params[0],"NTCreateX")) {
1288 nb_createx(params[1], ival(params[2]), ival(params[3]),
1290 } else if (!strcmp(params[0],"Close")) {
1291 nb_close(ival(params[1]));
1292 } else if (!strcmp(params[0],"Rename")) {
1293 nb_rename(params[1], params[2]);
1294 } else if (!strcmp(params[0],"Unlink")) {
1295 nb_unlink(params[1]);
1296 } else if (!strcmp(params[0],"Deltree")) {
1297 nb_deltree(params[1]);
1298 } else if (!strcmp(params[0],"Rmdir")) {
1299 nb_rmdir(params[1]);
1300 } else if (!strcmp(params[0],"QUERY_PATH_INFORMATION")) {
1301 nb_qpathinfo(params[1]);
1302 } else if (!strcmp(params[0],"QUERY_FILE_INFORMATION")) {
1303 nb_qfileinfo(ival(params[1]));
1304 } else if (!strcmp(params[0],"QUERY_FS_INFORMATION")) {
1305 nb_qfsinfo(ival(params[1]));
1306 } else if (!strcmp(params[0],"FIND_FIRST")) {
1307 nb_findfirst(params[1]);
1308 } else if (!strcmp(params[0],"WriteX")) {
1309 nb_writex(ival(params[1]),
1310 ival(params[2]), ival(params[3]), ival(params[4]));
1311 } else if (!strcmp(params[0],"ReadX")) {
1312 nb_readx(ival(params[1]),
1313 ival(params[2]), ival(params[3]), ival(params[4]));
1314 } else if (!strcmp(params[0],"Flush")) {
1315 nb_flush(ival(params[1]));
1317 printf("Unknown operation %s\n", params[0]);
1325 if (!torture_close_connection(cli)) {
1333 /* run a test that simulates an approximate netbench client load */
1334 static bool run_nbench(int dummy)
1337 bool correct = True;
1339 nbio_shmem(torture_nprocs);
1343 signal(SIGALRM, nb_alarm);
1345 t = create_procs(run_netbench, &correct);
1348 printf("\nThroughput %g MB/sec\n",
1349 1.0e-6 * nbio_total() / t);
1355 This test checks for two things:
1357 1) correct support for retaining locks over a close (ie. the server
1358 must not use posix semantics)
1359 2) support for lock timeouts
1361 static bool run_locktest1(int dummy)
1363 struct cli_state *cli1, *cli2;
1364 const char *fname = "\\lockt1.lck";
1365 uint16_t fnum1, fnum2, fnum3;
1367 unsigned lock_timeout;
1370 if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
1373 smbXcli_conn_set_sockopt(cli1->conn, sockops);
1374 smbXcli_conn_set_sockopt(cli2->conn, sockops);
1376 printf("starting locktest1\n");
1378 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1380 status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
1382 if (!NT_STATUS_IS_OK(status)) {
1383 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
1387 status = cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum2);
1388 if (!NT_STATUS_IS_OK(status)) {
1389 printf("open2 of %s failed (%s)\n", fname, nt_errstr(status));
1393 status = cli_openx(cli2, fname, O_RDWR, DENY_NONE, &fnum3);
1394 if (!NT_STATUS_IS_OK(status)) {
1395 printf("open3 of %s failed (%s)\n", fname, nt_errstr(status));
1399 status = cli_lock32(cli1, fnum1, 0, 4, 0, WRITE_LOCK);
1400 if (!NT_STATUS_IS_OK(status)) {
1401 printf("lock1 failed (%s)\n", nt_errstr(status));
1405 status = cli_lock32(cli2, fnum3, 0, 4, 0, WRITE_LOCK);
1406 if (NT_STATUS_IS_OK(status)) {
1407 printf("lock2 succeeded! This is a locking bug\n");
1410 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1411 NT_STATUS_LOCK_NOT_GRANTED)) {
1416 lock_timeout = (1 + (random() % 20));
1417 printf("Testing lock timeout with timeout=%u\n", lock_timeout);
1419 status = cli_lock32(cli2, fnum3, 0, 4, lock_timeout * 1000, WRITE_LOCK);
1420 if (NT_STATUS_IS_OK(status)) {
1421 printf("lock3 succeeded! This is a locking bug\n");
1424 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1425 NT_STATUS_FILE_LOCK_CONFLICT)) {
1431 if (ABS(t2 - t1) < lock_timeout-1) {
1432 printf("error: This server appears not to support timed lock requests\n");
1435 printf("server slept for %u seconds for a %u second timeout\n",
1436 (unsigned int)(t2-t1), lock_timeout);
1438 status = cli_close(cli1, fnum2);
1439 if (!NT_STATUS_IS_OK(status)) {
1440 printf("close1 failed (%s)\n", nt_errstr(status));
1444 status = cli_lock32(cli2, fnum3, 0, 4, 0, WRITE_LOCK);
1445 if (NT_STATUS_IS_OK(status)) {
1446 printf("lock4 succeeded! This is a locking bug\n");
1449 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1450 NT_STATUS_FILE_LOCK_CONFLICT)) {
1455 status = cli_close(cli1, fnum1);
1456 if (!NT_STATUS_IS_OK(status)) {
1457 printf("close2 failed (%s)\n", nt_errstr(status));
1461 status = cli_close(cli2, fnum3);
1462 if (!NT_STATUS_IS_OK(status)) {
1463 printf("close3 failed (%s)\n", nt_errstr(status));
1467 status = cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1468 if (!NT_STATUS_IS_OK(status)) {
1469 printf("unlink failed (%s)\n", nt_errstr(status));
1474 if (!torture_close_connection(cli1)) {
1478 if (!torture_close_connection(cli2)) {
1482 printf("Passed locktest1\n");
1487 this checks to see if a secondary tconx can use open files from an
1490 static bool run_tcon_test(int dummy)
1492 static struct cli_state *cli;
1493 const char *fname = "\\tcontest.tmp";
1495 uint32_t cnum1, cnum2, cnum3;
1496 struct smbXcli_tcon *orig_tcon = NULL;
1497 char *orig_share = NULL;
1498 uint16_t vuid1, vuid2;
1503 memset(buf, '\0', sizeof(buf));
1505 if (!torture_open_connection(&cli, 0)) {
1508 smbXcli_conn_set_sockopt(cli->conn, sockops);
1510 printf("starting tcontest\n");
1512 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1514 status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
1515 if (!NT_STATUS_IS_OK(status)) {
1516 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
1520 cnum1 = cli_state_get_tid(cli);
1521 vuid1 = cli_state_get_uid(cli);
1523 status = cli_writeall(cli, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
1524 if (!NT_STATUS_IS_OK(status)) {
1525 printf("initial write failed (%s)", nt_errstr(status));
1529 cli_state_save_tcon_share(cli, &orig_tcon, &orig_share);
1531 status = cli_tree_connect_creds(cli, share, "?????", torture_creds);
1532 if (!NT_STATUS_IS_OK(status)) {
1533 printf("%s refused 2nd tree connect (%s)\n", host,
1535 cli_state_restore_tcon_share(cli, orig_tcon, orig_share);
1540 cnum2 = cli_state_get_tid(cli);
1541 cnum3 = MAX(cnum1, cnum2) + 1; /* any invalid number */
1542 vuid2 = cli_state_get_uid(cli) + 1;
1544 /* try a write with the wrong tid */
1545 cli_state_set_tid(cli, cnum2);
1547 status = cli_writeall(cli, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
1548 if (NT_STATUS_IS_OK(status)) {
1549 printf("* server allows write with wrong TID\n");
1552 printf("server fails write with wrong TID : %s\n",
1557 /* try a write with an invalid tid */
1558 cli_state_set_tid(cli, cnum3);
1560 status = cli_writeall(cli, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
1561 if (NT_STATUS_IS_OK(status)) {
1562 printf("* server allows write with invalid TID\n");
1565 printf("server fails write with invalid TID : %s\n",
1569 /* try a write with an invalid vuid */
1570 cli_state_set_uid(cli, vuid2);
1571 cli_state_set_tid(cli, cnum1);
1573 status = cli_writeall(cli, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
1574 if (NT_STATUS_IS_OK(status)) {
1575 printf("* server allows write with invalid VUID\n");
1578 printf("server fails write with invalid VUID : %s\n",
1582 cli_state_set_tid(cli, cnum1);
1583 cli_state_set_uid(cli, vuid1);
1585 status = cli_close(cli, fnum1);
1586 if (!NT_STATUS_IS_OK(status)) {
1587 printf("close failed (%s)\n", nt_errstr(status));
1588 cli_state_restore_tcon_share(cli, orig_tcon, orig_share);
1593 cli_state_set_tid(cli, cnum2);
1595 status = cli_tdis(cli);
1596 if (!NT_STATUS_IS_OK(status)) {
1597 printf("secondary tdis failed (%s)\n", nt_errstr(status));
1598 cli_state_restore_tcon_share(cli, orig_tcon, orig_share);
1603 cli_state_restore_tcon_share(cli, orig_tcon, orig_share);
1605 cli_state_set_tid(cli, cnum1);
1607 if (!torture_close_connection(cli)) {
1616 checks for old style tcon support
1618 static bool run_tcon2_test(int dummy)
1620 static struct cli_state *cli;
1621 uint16_t cnum, max_xmit;
1625 if (!torture_open_connection(&cli, 0)) {
1628 smbXcli_conn_set_sockopt(cli->conn, sockops);
1630 printf("starting tcon2 test\n");
1632 if (asprintf(&service, "\\\\%s\\%s", host, share) == -1) {
1636 status = cli_raw_tcon(cli, service, password, "?????", &max_xmit, &cnum);
1640 if (!NT_STATUS_IS_OK(status)) {
1641 printf("tcon2 failed : %s\n", nt_errstr(status));
1643 printf("tcon OK : max_xmit=%d cnum=%d\n",
1644 (int)max_xmit, (int)cnum);
1647 if (!torture_close_connection(cli)) {
1651 printf("Passed tcon2 test\n");
1655 static bool tcon_devtest(struct cli_state *cli,
1656 const char *myshare, const char *devtype,
1657 const char *return_devtype,
1658 NTSTATUS expected_error)
1663 status = cli_tree_connect_creds(cli, myshare, devtype, torture_creds);
1665 if (NT_STATUS_IS_OK(expected_error)) {
1666 if (NT_STATUS_IS_OK(status)) {
1667 if (return_devtype != NULL &&
1668 strequal(cli->dev, return_devtype)) {
1671 printf("tconX to share %s with type %s "
1672 "succeeded but returned the wrong "
1673 "device type (got [%s] but should have got [%s])\n",
1674 myshare, devtype, cli->dev, return_devtype);
1678 printf("tconX to share %s with type %s "
1679 "should have succeeded but failed\n",
1685 if (NT_STATUS_IS_OK(status)) {
1686 printf("tconx to share %s with type %s "
1687 "should have failed but succeeded\n",
1691 if (NT_STATUS_EQUAL(status, expected_error)) {
1694 printf("Returned unexpected error\n");
1703 checks for correct tconX support
1705 static bool run_tcon_devtype_test(int dummy)
1707 static struct cli_state *cli1 = NULL;
1708 int flags = CLI_FULL_CONNECTION_FORCE_SMB1;
1712 status = cli_full_connection_creds(NULL,
1719 NULL, /* service_type */
1723 if (!NT_STATUS_IS_OK(status)) {
1724 printf("could not open connection\n");
1728 if (!tcon_devtest(cli1, "IPC$", "A:", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1731 if (!tcon_devtest(cli1, "IPC$", "?????", "IPC", NT_STATUS_OK))
1734 if (!tcon_devtest(cli1, "IPC$", "LPT:", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1737 if (!tcon_devtest(cli1, "IPC$", "IPC", "IPC", NT_STATUS_OK))
1740 if (!tcon_devtest(cli1, "IPC$", "FOOBA", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1743 if (!tcon_devtest(cli1, share, "A:", "A:", NT_STATUS_OK))
1746 if (!tcon_devtest(cli1, share, "?????", "A:", NT_STATUS_OK))
1749 if (!tcon_devtest(cli1, share, "LPT:", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1752 if (!tcon_devtest(cli1, share, "IPC", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1755 if (!tcon_devtest(cli1, share, "FOOBA", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1761 printf("Passed tcondevtest\n");
1768 This test checks that
1770 1) the server supports multiple locking contexts on the one SMB
1771 connection, distinguished by PID.
1773 2) the server correctly fails overlapping locks made by the same PID (this
1774 goes against POSIX behaviour, which is why it is tricky to implement)
1776 3) the server denies unlock requests by an incorrect client PID
1778 static bool run_locktest2(int dummy)
1780 static struct cli_state *cli;
1781 const char *fname = "\\lockt2.lck";
1782 uint16_t fnum1, fnum2, fnum3;
1783 bool correct = True;
1786 if (!torture_open_connection(&cli, 0)) {
1790 smbXcli_conn_set_sockopt(cli->conn, sockops);
1792 printf("starting locktest2\n");
1794 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1798 status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
1799 if (!NT_STATUS_IS_OK(status)) {
1800 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
1804 status = cli_openx(cli, fname, O_RDWR, DENY_NONE, &fnum2);
1805 if (!NT_STATUS_IS_OK(status)) {
1806 printf("open2 of %s failed (%s)\n", fname, nt_errstr(status));
1812 status = cli_openx(cli, fname, O_RDWR, DENY_NONE, &fnum3);
1813 if (!NT_STATUS_IS_OK(status)) {
1814 printf("open3 of %s failed (%s)\n", fname, nt_errstr(status));
1820 status = cli_lock32(cli, fnum1, 0, 4, 0, WRITE_LOCK);
1821 if (!NT_STATUS_IS_OK(status)) {
1822 printf("lock1 failed (%s)\n", nt_errstr(status));
1826 status = cli_lock32(cli, fnum1, 0, 4, 0, WRITE_LOCK);
1827 if (NT_STATUS_IS_OK(status)) {
1828 printf("WRITE lock1 succeeded! This is a locking bug\n");
1831 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1832 NT_STATUS_LOCK_NOT_GRANTED)) {
1837 status = cli_lock32(cli, fnum2, 0, 4, 0, WRITE_LOCK);
1838 if (NT_STATUS_IS_OK(status)) {
1839 printf("WRITE lock2 succeeded! This is a locking bug\n");
1842 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1843 NT_STATUS_LOCK_NOT_GRANTED)) {
1848 status = cli_lock32(cli, fnum2, 0, 4, 0, READ_LOCK);
1849 if (NT_STATUS_IS_OK(status)) {
1850 printf("READ lock2 succeeded! This is a locking bug\n");
1853 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1854 NT_STATUS_FILE_LOCK_CONFLICT)) {
1859 status = cli_lock32(cli, fnum1, 100, 4, 0, WRITE_LOCK);
1860 if (!NT_STATUS_IS_OK(status)) {
1861 printf("lock at 100 failed (%s)\n", nt_errstr(status));
1864 if (NT_STATUS_IS_OK(cli_unlock(cli, fnum1, 100, 4))) {
1865 printf("unlock at 100 succeeded! This is a locking bug\n");
1869 status = cli_unlock(cli, fnum1, 0, 4);
1870 if (NT_STATUS_IS_OK(status)) {
1871 printf("unlock1 succeeded! This is a locking bug\n");
1874 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1875 NT_STATUS_RANGE_NOT_LOCKED)) {
1880 status = cli_unlock(cli, fnum1, 0, 8);
1881 if (NT_STATUS_IS_OK(status)) {
1882 printf("unlock2 succeeded! This is a locking bug\n");
1885 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1886 NT_STATUS_RANGE_NOT_LOCKED)) {
1891 status = cli_lock32(cli, fnum3, 0, 4, 0, WRITE_LOCK);
1892 if (NT_STATUS_IS_OK(status)) {
1893 printf("lock3 succeeded! This is a locking bug\n");
1896 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1897 NT_STATUS_LOCK_NOT_GRANTED)) {
1904 status = cli_close(cli, fnum1);
1905 if (!NT_STATUS_IS_OK(status)) {
1906 printf("close1 failed (%s)\n", nt_errstr(status));
1910 status = cli_close(cli, fnum2);
1911 if (!NT_STATUS_IS_OK(status)) {
1912 printf("close2 failed (%s)\n", nt_errstr(status));
1916 status = cli_close(cli, fnum3);
1917 if (!NT_STATUS_IS_OK(status)) {
1918 printf("close3 failed (%s)\n", nt_errstr(status));
1922 if (!torture_close_connection(cli)) {
1926 printf("locktest2 finished\n");
1933 This test checks that
1935 1) the server supports the full offset range in lock requests
1937 static bool run_locktest3(int dummy)
1939 static struct cli_state *cli1, *cli2;
1940 const char *fname = "\\lockt3.lck";
1941 uint16_t fnum1, fnum2;
1944 bool correct = True;
1947 #define NEXT_OFFSET offset += (~(uint32_t)0) / torture_numops
1949 if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
1952 smbXcli_conn_set_sockopt(cli1->conn, sockops);
1953 smbXcli_conn_set_sockopt(cli2->conn, sockops);
1955 printf("starting locktest3\n");
1957 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1959 status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
1961 if (!NT_STATUS_IS_OK(status)) {
1962 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
1966 status = cli_openx(cli2, fname, O_RDWR, DENY_NONE, &fnum2);
1967 if (!NT_STATUS_IS_OK(status)) {
1968 printf("open2 of %s failed (%s)\n", fname, nt_errstr(status));
1972 for (offset=i=0;i<torture_numops;i++) {
1975 status = cli_lock32(cli1, fnum1, offset-1, 1, 0, WRITE_LOCK);
1976 if (!NT_STATUS_IS_OK(status)) {
1977 printf("lock1 %d failed (%s)\n",
1983 status = cli_lock32(cli2, fnum2, offset-2, 1, 0, WRITE_LOCK);
1984 if (!NT_STATUS_IS_OK(status)) {
1985 printf("lock2 %d failed (%s)\n",
1992 for (offset=i=0;i<torture_numops;i++) {
1995 status = cli_lock32(cli1, fnum1, offset-2, 1, 0, WRITE_LOCK);
1996 if (NT_STATUS_IS_OK(status)) {
1997 printf("error: lock1 %d succeeded!\n", i);
2001 status = cli_lock32(cli2, fnum2, offset-1, 1, 0, WRITE_LOCK);
2002 if (NT_STATUS_IS_OK(status)) {
2003 printf("error: lock2 %d succeeded!\n", i);
2007 status = cli_lock32(cli1, fnum1, offset-1, 1, 0, WRITE_LOCK);
2008 if (NT_STATUS_IS_OK(status)) {
2009 printf("error: lock3 %d succeeded!\n", i);
2013 status = cli_lock32(cli2, fnum2, offset-2, 1, 0, WRITE_LOCK);
2014 if (NT_STATUS_IS_OK(status)) {
2015 printf("error: lock4 %d succeeded!\n", i);
2020 for (offset=i=0;i<torture_numops;i++) {
2023 status = cli_unlock(cli1, fnum1, offset-1, 1);
2024 if (!NT_STATUS_IS_OK(status)) {
2025 printf("unlock1 %d failed (%s)\n",
2031 status = cli_unlock(cli2, fnum2, offset-2, 1);
2032 if (!NT_STATUS_IS_OK(status)) {
2033 printf("unlock2 %d failed (%s)\n",
2040 status = cli_close(cli1, fnum1);
2041 if (!NT_STATUS_IS_OK(status)) {
2042 printf("close1 failed (%s)\n", nt_errstr(status));
2046 status = cli_close(cli2, fnum2);
2047 if (!NT_STATUS_IS_OK(status)) {
2048 printf("close2 failed (%s)\n", nt_errstr(status));
2052 status = cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2053 if (!NT_STATUS_IS_OK(status)) {
2054 printf("unlink failed (%s)\n", nt_errstr(status));
2058 if (!torture_close_connection(cli1)) {
2062 if (!torture_close_connection(cli2)) {
2066 printf("finished locktest3\n");
2071 static bool test_cli_read(struct cli_state *cli, uint16_t fnum,
2072 char *buf, off_t offset, size_t size,
2073 size_t *nread, size_t expect)
2078 status = cli_read(cli, fnum, buf, offset, size, &l_nread);
2080 if(!NT_STATUS_IS_OK(status)) {
2082 } else if (l_nread != expect) {
2093 #define EXPECTED(ret, v) if ((ret) != (v)) { \
2094 printf("** "); correct = False; \
2098 looks at overlapping locks
2100 static bool run_locktest4(int dummy)
2102 static struct cli_state *cli1, *cli2;
2103 const char *fname = "\\lockt4.lck";
2104 uint16_t fnum1, fnum2, f;
2107 bool correct = True;
2110 if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
2114 smbXcli_conn_set_sockopt(cli1->conn, sockops);
2115 smbXcli_conn_set_sockopt(cli2->conn, sockops);
2117 printf("starting locktest4\n");
2119 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2121 cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
2122 cli_openx(cli2, fname, O_RDWR, DENY_NONE, &fnum2);
2124 memset(buf, 0, sizeof(buf));
2126 status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 0, sizeof(buf),
2128 if (!NT_STATUS_IS_OK(status)) {
2129 printf("Failed to create file: %s\n", nt_errstr(status));
2134 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 4, 0, WRITE_LOCK)) &&
2135 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 2, 4, 0, WRITE_LOCK));
2136 EXPECTED(ret, False);
2137 printf("the same process %s set overlapping write locks\n", ret?"can":"cannot");
2139 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 10, 4, 0, READ_LOCK)) &&
2140 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 12, 4, 0, READ_LOCK));
2141 EXPECTED(ret, True);
2142 printf("the same process %s set overlapping read locks\n", ret?"can":"cannot");
2144 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 20, 4, 0, WRITE_LOCK)) &&
2145 NT_STATUS_IS_OK(cli_lock32(cli2, fnum2, 22, 4, 0, WRITE_LOCK));
2146 EXPECTED(ret, False);
2147 printf("a different connection %s set overlapping write locks\n", ret?"can":"cannot");
2149 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 30, 4, 0, READ_LOCK)) &&
2150 NT_STATUS_IS_OK(cli_lock32(cli2, fnum2, 32, 4, 0, READ_LOCK));
2151 EXPECTED(ret, True);
2152 printf("a different connection %s set overlapping read locks\n", ret?"can":"cannot");
2154 ret = (cli_setpid(cli1, 1),
2155 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 40, 4, 0, WRITE_LOCK))) &&
2156 (cli_setpid(cli1, 2),
2157 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 42, 4, 0, WRITE_LOCK)));
2158 EXPECTED(ret, False);
2159 printf("a different pid %s set overlapping write locks\n", ret?"can":"cannot");
2161 ret = (cli_setpid(cli1, 1),
2162 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 50, 4, 0, READ_LOCK))) &&
2163 (cli_setpid(cli1, 2),
2164 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 52, 4, 0, READ_LOCK)));
2165 EXPECTED(ret, True);
2166 printf("a different pid %s set overlapping read locks\n", ret?"can":"cannot");
2168 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 60, 4, 0, READ_LOCK)) &&
2169 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 60, 4, 0, READ_LOCK));
2170 EXPECTED(ret, True);
2171 printf("the same process %s set the same read lock twice\n", ret?"can":"cannot");
2173 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 70, 4, 0, WRITE_LOCK)) &&
2174 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 70, 4, 0, WRITE_LOCK));
2175 EXPECTED(ret, False);
2176 printf("the same process %s set the same write lock twice\n", ret?"can":"cannot");
2178 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 80, 4, 0, READ_LOCK)) &&
2179 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 80, 4, 0, WRITE_LOCK));
2180 EXPECTED(ret, False);
2181 printf("the same process %s overlay a read lock with a write lock\n", ret?"can":"cannot");
2183 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 90, 4, 0, WRITE_LOCK)) &&
2184 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 90, 4, 0, READ_LOCK));
2185 EXPECTED(ret, True);
2186 printf("the same process %s overlay a write lock with a read lock\n", ret?"can":"cannot");
2188 ret = (cli_setpid(cli1, 1),
2189 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 100, 4, 0, WRITE_LOCK))) &&
2190 (cli_setpid(cli1, 2),
2191 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 100, 4, 0, READ_LOCK)));
2192 EXPECTED(ret, False);
2193 printf("a different pid %s overlay a write lock with a read lock\n", ret?"can":"cannot");
2195 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 110, 4, 0, READ_LOCK)) &&
2196 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 112, 4, 0, READ_LOCK)) &&
2197 NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 110, 6));
2198 EXPECTED(ret, False);
2199 printf("the same process %s coalesce read locks\n", ret?"can":"cannot");
2202 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 120, 4, 0, WRITE_LOCK)) &&
2203 test_cli_read(cli2, fnum2, buf, 120, 4, NULL, 4);
2204 EXPECTED(ret, False);
2205 printf("this server %s strict write locking\n", ret?"doesn't do":"does");
2207 status = cli_lock32(cli1, fnum1, 130, 4, 0, READ_LOCK);
2208 ret = NT_STATUS_IS_OK(status);
2210 status = cli_writeall(cli2, fnum2, 0, (uint8_t *)buf, 130, 4,
2212 ret = NT_STATUS_IS_OK(status);
2214 EXPECTED(ret, False);
2215 printf("this server %s strict read locking\n", ret?"doesn't do":"does");
2218 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 140, 4, 0, READ_LOCK)) &&
2219 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 140, 4, 0, READ_LOCK)) &&
2220 NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 140, 4)) &&
2221 NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 140, 4));
2222 EXPECTED(ret, True);
2223 printf("this server %s do recursive read locking\n", ret?"does":"doesn't");
2226 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 150, 4, 0, WRITE_LOCK)) &&
2227 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 150, 4, 0, READ_LOCK)) &&
2228 NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 150, 4)) &&
2229 test_cli_read(cli2, fnum2, buf, 150, 4, NULL, 4) &&
2230 !(NT_STATUS_IS_OK(cli_writeall(cli2, fnum2, 0, (uint8_t *)buf,
2232 NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 150, 4));
2233 EXPECTED(ret, True);
2234 printf("this server %s do recursive lock overlays\n", ret?"does":"doesn't");
2236 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 160, 4, 0, READ_LOCK)) &&
2237 NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 160, 4)) &&
2238 NT_STATUS_IS_OK(cli_writeall(cli2, fnum2, 0, (uint8_t *)buf,
2240 test_cli_read(cli2, fnum2, buf, 160, 4, NULL, 4);
2241 EXPECTED(ret, True);
2242 printf("the same process %s remove a read lock using write locking\n", ret?"can":"cannot");
2244 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 170, 4, 0, WRITE_LOCK)) &&
2245 NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 170, 4)) &&
2246 NT_STATUS_IS_OK(cli_writeall(cli2, fnum2, 0, (uint8_t *)buf,
2248 test_cli_read(cli2, fnum2, buf, 170, 4, NULL, 4);
2249 EXPECTED(ret, True);
2250 printf("the same process %s remove a write lock using read locking\n", ret?"can":"cannot");
2252 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 190, 4, 0, WRITE_LOCK)) &&
2253 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 190, 4, 0, READ_LOCK)) &&
2254 NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 190, 4)) &&
2255 !NT_STATUS_IS_OK(cli_writeall(cli2, fnum2, 0, (uint8_t *)buf,
2257 test_cli_read(cli2, fnum2, buf, 190, 4, NULL, 4);
2258 EXPECTED(ret, True);
2259 printf("the same process %s remove the first lock first\n", ret?"does":"doesn't");
2261 cli_close(cli1, fnum1);
2262 cli_close(cli2, fnum2);
2263 cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
2264 cli_openx(cli1, fname, O_RDWR, DENY_NONE, &f);
2265 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 8, 0, READ_LOCK)) &&
2266 NT_STATUS_IS_OK(cli_lock32(cli1, f, 0, 1, 0, READ_LOCK)) &&
2267 NT_STATUS_IS_OK(cli_close(cli1, fnum1)) &&
2268 NT_STATUS_IS_OK(cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1)) &&
2269 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 7, 1, 0, WRITE_LOCK));
2271 cli_close(cli1, fnum1);
2272 EXPECTED(ret, True);
2273 printf("the server %s have the NT byte range lock bug\n", !ret?"does":"doesn't");
2276 cli_close(cli1, fnum1);
2277 cli_close(cli2, fnum2);
2278 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2279 torture_close_connection(cli1);
2280 torture_close_connection(cli2);
2282 printf("finished locktest4\n");
2287 looks at lock upgrade/downgrade.
2289 static bool run_locktest5(int dummy)
2291 static struct cli_state *cli1, *cli2;
2292 const char *fname = "\\lockt5.lck";
2293 uint16_t fnum1, fnum2, fnum3;
2296 bool correct = True;
2299 if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
2303 smbXcli_conn_set_sockopt(cli1->conn, sockops);
2304 smbXcli_conn_set_sockopt(cli2->conn, sockops);
2306 printf("starting locktest5\n");
2308 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2310 cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
2311 cli_openx(cli2, fname, O_RDWR, DENY_NONE, &fnum2);
2312 cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum3);
2314 memset(buf, 0, sizeof(buf));
2316 status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 0, sizeof(buf),
2318 if (!NT_STATUS_IS_OK(status)) {
2319 printf("Failed to create file: %s\n", nt_errstr(status));
2324 /* Check for NT bug... */
2325 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 8, 0, READ_LOCK)) &&
2326 NT_STATUS_IS_OK(cli_lock32(cli1, fnum3, 0, 1, 0, READ_LOCK));
2327 cli_close(cli1, fnum1);
2328 cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
2329 status = cli_lock32(cli1, fnum1, 7, 1, 0, WRITE_LOCK);
2330 ret = NT_STATUS_IS_OK(status);
2331 EXPECTED(ret, True);
2332 printf("this server %s the NT locking bug\n", ret ? "doesn't have" : "has");
2333 cli_close(cli1, fnum1);
2334 cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
2335 cli_unlock(cli1, fnum3, 0, 1);
2337 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 4, 0, WRITE_LOCK)) &&
2338 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 1, 1, 0, READ_LOCK));
2339 EXPECTED(ret, True);
2340 printf("the same process %s overlay a write with a read lock\n", ret?"can":"cannot");
2342 status = cli_lock32(cli2, fnum2, 0, 4, 0, READ_LOCK);
2343 ret = NT_STATUS_IS_OK(status);
2344 EXPECTED(ret, False);
2346 printf("a different process %s get a read lock on the first process lock stack\n", ret?"can":"cannot");
2348 /* Unlock the process 2 lock. */
2349 cli_unlock(cli2, fnum2, 0, 4);
2351 status = cli_lock32(cli1, fnum3, 0, 4, 0, READ_LOCK);
2352 ret = NT_STATUS_IS_OK(status);
2353 EXPECTED(ret, False);
2355 printf("the same process on a different fnum %s get a read lock\n", ret?"can":"cannot");
2357 /* Unlock the process 1 fnum3 lock. */
2358 cli_unlock(cli1, fnum3, 0, 4);
2360 /* Stack 2 more locks here. */
2361 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 4, 0, READ_LOCK)) &&
2362 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 4, 0, READ_LOCK));
2364 EXPECTED(ret, True);
2365 printf("the same process %s stack read locks\n", ret?"can":"cannot");
2367 /* Unlock the first process lock, then check this was the WRITE lock that was
2370 ret = NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 0, 4)) &&
2371 NT_STATUS_IS_OK(cli_lock32(cli2, fnum2, 0, 4, 0, READ_LOCK));
2373 EXPECTED(ret, True);
2374 printf("the first unlock removes the %s lock\n", ret?"WRITE":"READ");
2376 /* Unlock the process 2 lock. */
2377 cli_unlock(cli2, fnum2, 0, 4);
2379 /* We should have 3 stacked locks here. Ensure we need to do 3 unlocks. */
2381 ret = NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 1, 1)) &&
2382 NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 0, 4)) &&
2383 NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 0, 4));
2385 EXPECTED(ret, True);
2386 printf("the same process %s unlock the stack of 4 locks\n", ret?"can":"cannot");
2388 /* Ensure the next unlock fails. */
2389 ret = NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 0, 4));
2390 EXPECTED(ret, False);
2391 printf("the same process %s count the lock stack\n", !ret?"can":"cannot");
2393 /* Ensure connection 2 can get a write lock. */
2394 status = cli_lock32(cli2, fnum2, 0, 4, 0, WRITE_LOCK);
2395 ret = NT_STATUS_IS_OK(status);
2396 EXPECTED(ret, True);
2398 printf("a different process %s get a write lock on the unlocked stack\n", ret?"can":"cannot");
2402 cli_close(cli1, fnum1);
2403 cli_close(cli2, fnum2);
2404 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2405 if (!torture_close_connection(cli1)) {
2408 if (!torture_close_connection(cli2)) {
2412 printf("finished locktest5\n");
2418 tries the unusual lockingX locktype bits
2420 static bool run_locktest6(int dummy)
2422 static struct cli_state *cli;
2423 const char *fname[1] = { "\\lock6.txt" };
2428 if (!torture_open_connection(&cli, 0)) {
2432 smbXcli_conn_set_sockopt(cli->conn, sockops);
2434 printf("starting locktest6\n");
2437 printf("Testing %s\n", fname[i]);
2439 cli_unlink(cli, fname[i], FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2441 cli_openx(cli, fname[i], O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
2442 status = cli_locktype(cli, fnum, 0, 8, 0, LOCKING_ANDX_CHANGE_LOCKTYPE);
2443 cli_close(cli, fnum);
2444 printf("CHANGE_LOCKTYPE gave %s\n", nt_errstr(status));
2446 cli_openx(cli, fname[i], O_RDWR, DENY_NONE, &fnum);
2447 status = cli_locktype(cli, fnum, 0, 8, 0, LOCKING_ANDX_CANCEL_LOCK);
2448 cli_close(cli, fnum);
2449 printf("CANCEL_LOCK gave %s\n", nt_errstr(status));
2451 cli_unlink(cli, fname[i], FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2454 torture_close_connection(cli);
2456 printf("finished locktest6\n");
2460 static bool run_locktest7(int dummy)
2462 struct cli_state *cli1;
2463 const char *fname = "\\lockt7.lck";
2466 bool correct = False;
2470 if (!torture_open_connection(&cli1, 0)) {
2474 smbXcli_conn_set_sockopt(cli1->conn, sockops);
2476 printf("starting locktest7\n");
2478 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2480 cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
2482 memset(buf, 0, sizeof(buf));
2484 status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 0, sizeof(buf),
2486 if (!NT_STATUS_IS_OK(status)) {
2487 printf("Failed to create file: %s\n", nt_errstr(status));
2491 cli_setpid(cli1, 1);
2493 status = cli_lock32(cli1, fnum1, 130, 4, 0, READ_LOCK);
2494 if (!NT_STATUS_IS_OK(status)) {
2495 printf("Unable to apply read lock on range 130:4, "
2496 "error was %s\n", nt_errstr(status));
2499 printf("pid1 successfully locked range 130:4 for READ\n");
2502 status = cli_read(cli1, fnum1, buf, 130, 4, &nread);
2503 if (!NT_STATUS_IS_OK(status)) {
2504 printf("pid1 unable to read the range 130:4, error was %s\n",
2507 } else if (nread != 4) {
2508 printf("pid1 unable to read the range 130:4, "
2509 "recv %ld req %d\n", (unsigned long)nread, 4);
2512 printf("pid1 successfully read the range 130:4\n");
2515 status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
2516 if (!NT_STATUS_IS_OK(status)) {
2517 printf("pid1 unable to write to the range 130:4, error was "
2518 "%s\n", nt_errstr(status));
2519 if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
2520 printf("Incorrect error (should be NT_STATUS_FILE_LOCK_CONFLICT)\n");
2524 printf("pid1 successfully wrote to the range 130:4 (should be denied)\n");
2528 cli_setpid(cli1, 2);
2530 status = cli_read(cli1, fnum1, buf, 130, 4, &nread);
2531 if (!NT_STATUS_IS_OK(status)) {
2532 printf("pid2 unable to read the range 130:4, error was %s\n",
2535 } else if (nread != 4) {
2536 printf("pid2 unable to read the range 130:4, "
2537 "recv %ld req %d\n", (unsigned long)nread, 4);
2540 printf("pid2 successfully read the range 130:4\n");
2543 status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
2544 if (!NT_STATUS_IS_OK(status)) {
2545 printf("pid2 unable to write to the range 130:4, error was "
2546 "%s\n", nt_errstr(status));
2547 if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
2548 printf("Incorrect error (should be NT_STATUS_FILE_LOCK_CONFLICT)\n");
2552 printf("pid2 successfully wrote to the range 130:4 (should be denied)\n");
2556 cli_setpid(cli1, 1);
2557 cli_unlock(cli1, fnum1, 130, 4);
2559 status = cli_lock32(cli1, fnum1, 130, 4, 0, WRITE_LOCK);
2560 if (!NT_STATUS_IS_OK(status)) {
2561 printf("Unable to apply write lock on range 130:4, error was %s\n", nt_errstr(status));
2564 printf("pid1 successfully locked range 130:4 for WRITE\n");
2567 status = cli_read(cli1, fnum1, buf, 130, 4, &nread);
2568 if (!NT_STATUS_IS_OK(status)) {
2569 printf("pid1 unable to read the range 130:4, error was %s\n",
2572 } else if (nread != 4) {
2573 printf("pid1 unable to read the range 130:4, "
2574 "recv %ld req %d\n", (unsigned long)nread, 4);
2577 printf("pid1 successfully read the range 130:4\n");
2580 status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
2581 if (!NT_STATUS_IS_OK(status)) {
2582 printf("pid1 unable to write to the range 130:4, error was "
2583 "%s\n", nt_errstr(status));
2586 printf("pid1 successfully wrote to the range 130:4\n");
2589 cli_setpid(cli1, 2);
2591 status = cli_read(cli1, fnum1, buf, 130, 4, &nread);
2592 if (!NT_STATUS_IS_OK(status)) {
2593 printf("pid2 unable to read the range 130:4, error was "
2594 "%s\n", nt_errstr(status));
2595 if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
2596 printf("Incorrect error (should be NT_STATUS_FILE_LOCK_CONFLICT)\n");
2600 printf("pid2 successfully read the range 130:4 (should be denied) recv %ld\n",
2601 (unsigned long)nread);
2605 status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
2606 if (!NT_STATUS_IS_OK(status)) {
2607 printf("pid2 unable to write to the range 130:4, error was "
2608 "%s\n", nt_errstr(status));
2609 if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
2610 printf("Incorrect error (should be NT_STATUS_FILE_LOCK_CONFLICT)\n");
2614 printf("pid2 successfully wrote to the range 130:4 (should be denied)\n");
2618 cli_unlock(cli1, fnum1, 130, 0);
2622 cli_close(cli1, fnum1);
2623 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2624 torture_close_connection(cli1);
2626 printf("finished locktest7\n");
2631 * This demonstrates a problem with our use of GPFS share modes: A file
2632 * descriptor sitting in the pending close queue holding a GPFS share mode
2633 * blocks opening a file another time. Happens with Word 2007 temp files.
2634 * With "posix locking = yes" and "gpfs:sharemodes = yes" enabled, the third
2635 * open is denied with NT_STATUS_SHARING_VIOLATION.
2638 static bool run_locktest8(int dummy)
2640 struct cli_state *cli1;
2641 const char *fname = "\\lockt8.lck";
2642 uint16_t fnum1, fnum2;
2644 bool correct = False;
2647 if (!torture_open_connection(&cli1, 0)) {
2651 smbXcli_conn_set_sockopt(cli1->conn, sockops);
2653 printf("starting locktest8\n");
2655 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2657 status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_WRITE,
2659 if (!NT_STATUS_IS_OK(status)) {
2660 d_fprintf(stderr, "cli_openx returned %s\n", nt_errstr(status));
2664 memset(buf, 0, sizeof(buf));
2666 status = cli_openx(cli1, fname, O_RDONLY, DENY_NONE, &fnum2);
2667 if (!NT_STATUS_IS_OK(status)) {
2668 d_fprintf(stderr, "cli_openx second time returned %s\n",
2673 status = cli_lock32(cli1, fnum2, 1, 1, 0, READ_LOCK);
2674 if (!NT_STATUS_IS_OK(status)) {
2675 printf("Unable to apply read lock on range 1:1, error was "
2676 "%s\n", nt_errstr(status));
2680 status = cli_close(cli1, fnum1);
2681 if (!NT_STATUS_IS_OK(status)) {
2682 d_fprintf(stderr, "cli_close(fnum1) %s\n", nt_errstr(status));
2686 status = cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
2687 if (!NT_STATUS_IS_OK(status)) {
2688 d_fprintf(stderr, "cli_openx third time returned %s\n",
2696 cli_close(cli1, fnum1);
2697 cli_close(cli1, fnum2);
2698 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2699 torture_close_connection(cli1);
2701 printf("finished locktest8\n");
2706 * This test is designed to be run in conjunction with
2707 * external NFS or POSIX locks taken in the filesystem.
2708 * It checks that the smbd server will block until the
2709 * lock is released and then acquire it. JRA.
2712 static bool got_alarm;
2713 static struct cli_state *alarm_cli;
2715 static void alarm_handler(int dummy)
2720 static void alarm_handler_parent(int dummy)
2722 smbXcli_conn_disconnect(alarm_cli->conn, NT_STATUS_LOCAL_DISCONNECT);
2725 static void do_local_lock(const char *fname, int read_fd, int write_fd)
2730 const char *local_pathname = NULL;
2733 local_pathname = talloc_asprintf(talloc_tos(),
2734 "%s/%s", local_path, fname);
2735 if (!local_pathname) {
2736 printf("child: alloc fail\n");
2740 unlink(local_pathname);
2741 fd = open(local_pathname, O_RDWR|O_CREAT, 0666);
2743 printf("child: open of %s failed %s.\n",
2744 local_pathname, strerror(errno));
2748 /* Now take a fcntl lock. */
2749 lock.l_type = F_WRLCK;
2750 lock.l_whence = SEEK_SET;
2753 lock.l_pid = getpid();
2755 ret = fcntl(fd,F_SETLK,&lock);
2757 printf("child: failed to get lock 0:4 on file %s. Error %s\n",
2758 local_pathname, strerror(errno));
2761 printf("child: got lock 0:4 on file %s.\n",
2766 CatchSignal(SIGALRM, alarm_handler);
2768 /* Signal the parent. */
2769 if (write(write_fd, &c, 1) != 1) {
2770 printf("child: start signal fail %s.\n",
2777 /* Wait for the parent to be ready. */
2778 if (read(read_fd, &c, 1) != 1) {
2779 printf("child: reply signal fail %s.\n",
2787 printf("child: released lock 0:4 on file %s.\n",
2793 static bool _run_locktest9X(const char *fname, int timeout)
2795 struct cli_state *cli1;
2796 char *fpath = talloc_asprintf(talloc_tos(), "\\%s", fname);
2798 bool correct = False;
2799 int pipe_in[2], pipe_out[2];
2803 struct timeval start;
2807 printf("starting locktest9X: %s\n", fname);
2809 if (local_path == NULL) {
2810 d_fprintf(stderr, "locktest9X must be given a local path via -l <localpath>\n");
2814 if (pipe(pipe_in) == -1 || pipe(pipe_out) == -1) {
2819 if (child_pid == -1) {
2823 if (child_pid == 0) {
2825 do_local_lock(fname, pipe_out[0], pipe_in[1]);
2835 ret = read(pipe_in[0], &c, 1);
2837 d_fprintf(stderr, "failed to read start signal from child. %s\n",
2842 if (!torture_open_connection(&cli1, 0)) {
2846 smbXcli_conn_set_sockopt(cli1->conn, sockops);
2848 status = cli_openx(cli1, fpath, O_RDWR, DENY_NONE,
2850 if (!NT_STATUS_IS_OK(status)) {
2851 d_fprintf(stderr, "cli_openx returned %s\n", nt_errstr(status));
2855 /* Ensure the child has the lock. */
2856 status = cli_lock32(cli1, fnum, 0, 4, 0, WRITE_LOCK);
2857 if (NT_STATUS_IS_OK(status)) {
2858 d_fprintf(stderr, "Got the lock on range 0:4 - this should not happen !\n");
2861 d_printf("Child has the lock.\n");
2864 /* Tell the child to wait 5 seconds then exit. */
2865 ret = write(pipe_out[1], &c, 1);
2867 d_fprintf(stderr, "failed to send exit signal to child. %s\n",
2872 /* Wait 20 seconds for the lock. */
2874 CatchSignal(SIGALRM, alarm_handler_parent);
2877 start = timeval_current();
2879 status = cli_lock32(cli1, fnum, 0, 4, timeout, WRITE_LOCK);
2880 if (!NT_STATUS_IS_OK(status)) {
2881 d_fprintf(stderr, "Unable to apply write lock on range 0:4, error was "
2882 "%s\n", nt_errstr(status));
2887 seconds = timeval_elapsed(&start);
2889 printf("Parent got the lock after %.2f seconds.\n",
2892 status = cli_close(cli1, fnum);
2893 if (!NT_STATUS_IS_OK(status)) {
2894 d_fprintf(stderr, "cli_close(fnum1) %s\n", nt_errstr(status));
2901 cli_close(cli1, fnum);
2902 torture_close_connection(cli1);
2906 printf("finished locktest9X: %s\n", fname);
2910 static bool run_locktest9a(int dummy)
2912 return _run_locktest9X("lock9a.dat", -1);
2915 static bool run_locktest9b(int dummy)
2917 return _run_locktest9X("lock9b.dat", 10000);
2920 struct locktest10_state {
2925 static void locktest10_lockingx_done(struct tevent_req *subreq);
2926 static void locktest10_read_andx_done(struct tevent_req *subreq);
2928 static bool run_locktest10(int dummy)
2930 struct tevent_context *ev = NULL;
2931 struct cli_state *cli1 = NULL;
2932 struct cli_state *cli2 = NULL;
2933 struct smb1_lock_element lck = { 0 };
2934 struct tevent_req *reqs[2] = { NULL };
2935 struct tevent_req *smbreqs[2] = { NULL };
2936 const char fname[] = "\\lockt10.lck";
2937 uint16_t fnum1, fnum2;
2941 struct locktest10_state state = { .ok = true };
2944 printf("starting locktest10\n");
2946 ev = samba_tevent_context_init(NULL);
2948 d_fprintf(stderr, "samba_tevent_context_init failed\n");
2952 ok = torture_open_connection(&cli1, 0);
2956 smbXcli_conn_set_sockopt(cli1->conn, sockops);
2958 ok = torture_open_connection(&cli2, 1);
2962 smbXcli_conn_set_sockopt(cli2->conn, sockops);
2964 status = cli_openx(cli1, fname, O_CREAT|O_RDWR, DENY_NONE, &fnum1);
2965 if (!NT_STATUS_IS_OK(status)) {
2967 "cli_openx failed: %s\n",
2972 status = cli_writeall(cli1, fnum1, 0, &data, 0, sizeof(data), NULL);
2973 if (!NT_STATUS_IS_OK(status)) {
2975 "cli_writeall failed: %s\n",
2980 status = cli_openx(cli2, fname, O_CREAT|O_RDWR, DENY_NONE, &fnum2);
2981 if (!NT_STATUS_IS_OK(status)) {
2983 "cli_openx failed: %s\n",
2988 status = cli_locktype(
2989 cli2, fnum2, 0, 1, 0, LOCKING_ANDX_EXCLUSIVE_LOCK);
2990 if (!NT_STATUS_IS_OK(status)) {
2992 "cli_locktype failed: %s\n",
2997 lck = (struct smb1_lock_element) {
2998 .pid = cli_getpid(cli1), .offset = 0, .length = 1,
3001 reqs[0] = cli_lockingx_create(
3003 ev, /* tevent_context */
3006 LOCKING_ANDX_EXCLUSIVE_LOCK, /* typeoflock */
3007 0, /* newoplocklevel */
3009 0, /* num_unlocks */
3013 &smbreqs[0]); /* psmbreq */
3014 if (reqs[0] == NULL) {
3015 d_fprintf(stderr, "cli_lockingx_create failed\n");
3018 tevent_req_set_callback(reqs[0], locktest10_lockingx_done, &state);
3020 reqs[1] = cli_read_andx_create(
3027 &smbreqs[1]); /* psmbreq */
3028 if (reqs[1] == NULL) {
3029 d_fprintf(stderr, "cli_read_andx_create failed\n");
3032 tevent_req_set_callback(reqs[1], locktest10_read_andx_done, &state);
3034 status = smb1cli_req_chain_submit(smbreqs, ARRAY_SIZE(smbreqs));
3035 if (!NT_STATUS_IS_OK(status)) {
3037 "smb1cli_req_chain_submit failed: %s\n",
3042 while (!state.done) {
3043 tevent_loop_once(ev);
3046 torture_close_connection(cli1);
3055 static void locktest10_lockingx_done(struct tevent_req *subreq)
3057 struct locktest10_state *state = tevent_req_callback_data_void(subreq);
3060 status = cli_lockingx_recv(subreq);
3061 TALLOC_FREE(subreq);
3063 if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
3064 d_printf("cli_lockingx returned %s\n", nt_errstr(status));
3069 static void locktest10_read_andx_done(struct tevent_req *subreq)
3071 struct locktest10_state *state = tevent_req_callback_data_void(subreq);
3072 ssize_t received = -1;
3073 uint8_t *rcvbuf = NULL;
3076 status = cli_read_andx_recv(subreq, &received, &rcvbuf);
3078 if (!NT_STATUS_EQUAL(status, NT_STATUS_REQUEST_ABORTED)) {
3079 d_printf("cli_read_andx returned %s\n", nt_errstr(status));
3084 TALLOC_FREE(subreq);
3087 static bool run_locktest11(int dummy)
3089 struct cli_state *cli1;
3090 const char *fname = "\\lockt11.lck";
3095 if (!torture_open_connection(&cli1, 0)) {
3099 smbXcli_conn_set_sockopt(cli1->conn, sockops);
3101 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3103 status = cli_openx(cli1, fname, O_CREAT|O_RDWR, DENY_NONE, &fnum);
3104 if (!NT_STATUS_IS_OK(status)) {
3106 "cli_openx returned %s\n",
3112 * Test that LOCKING_ANDX_CANCEL_LOCK without any locks
3113 * returns NT_STATUS_OK
3116 status = cli_lockingx(
3119 LOCKING_ANDX_CANCEL_LOCK, /* typeoflock */
3120 0, /* newoplocklevel */
3122 0, /* num_unlocks */
3127 if (!NT_STATUS_IS_OK(status)) {
3128 d_printf("cli_lockingX returned %s\n", nt_errstr(status));
3134 cli_close(cli1, fnum);
3135 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3140 struct deferred_close_state {
3141 struct tevent_context *ev;
3142 struct cli_state *cli;
3146 static void deferred_close_waited(struct tevent_req *subreq);
3147 static void deferred_close_done(struct tevent_req *subreq);
3149 static struct tevent_req *deferred_close_send(
3150 TALLOC_CTX *mem_ctx,
3151 struct tevent_context *ev,
3153 struct cli_state *cli,
3156 struct tevent_req *req = NULL, *subreq = NULL;
3157 struct deferred_close_state *state = NULL;
3158 struct timeval wakeup_time = timeval_current_ofs(wait_secs, 0);
3160 req = tevent_req_create(
3161 mem_ctx, &state, struct deferred_close_state);
3169 subreq = tevent_wakeup_send(state, state->ev, wakeup_time);
3170 if (tevent_req_nomem(subreq, req)) {
3171 return tevent_req_post(req, ev);
3173 tevent_req_set_callback(subreq, deferred_close_waited, req);
3177 static void deferred_close_waited(struct tevent_req *subreq)
3179 struct tevent_req *req = tevent_req_callback_data(
3180 subreq, struct tevent_req);
3181 struct deferred_close_state *state = tevent_req_data(
3182 req, struct deferred_close_state);
3185 ok = tevent_wakeup_recv(subreq);
3186 TALLOC_FREE(subreq);
3188 tevent_req_oom(req);
3192 subreq = cli_close_send(state, state->ev, state->cli, state->fnum, 0);
3193 if (tevent_req_nomem(subreq, req)) {
3196 tevent_req_set_callback(subreq, deferred_close_done, req);
3199 static void deferred_close_done(struct tevent_req *subreq)
3201 NTSTATUS status = cli_close_recv(subreq);
3202 tevent_req_simple_finish_ntstatus(subreq, status);
3205 static NTSTATUS deferred_close_recv(struct tevent_req *req)
3207 return tevent_req_simple_recv_ntstatus(req);
3210 struct lockread_state {
3211 struct smb1_lock_element lck;
3212 struct tevent_req *reqs[2];
3213 struct tevent_req *smbreqs[2];
3214 NTSTATUS lock_status;
3215 NTSTATUS read_status;
3219 static void lockread_lockingx_done(struct tevent_req *subreq);
3220 static void lockread_read_andx_done(struct tevent_req *subreq);
3222 static struct tevent_req *lockread_send(
3223 TALLOC_CTX *mem_ctx,
3224 struct tevent_context *ev,
3225 struct cli_state *cli,
3228 struct tevent_req *req = NULL;
3229 struct lockread_state *state = NULL;
3232 req = tevent_req_create(mem_ctx, &state, struct lockread_state);
3237 state->lck = (struct smb1_lock_element) {
3238 .pid = cli_getpid(cli), .offset = 0, .length = 1,
3241 state->reqs[0] = cli_lockingx_create(
3243 ev, /* tevent_context */
3246 LOCKING_ANDX_EXCLUSIVE_LOCK, /* typeoflock */
3247 0, /* newoplocklevel */
3248 10000, /* timeout */
3249 0, /* num_unlocks */
3252 &state->lck, /* locks */
3253 &state->smbreqs[0]); /* psmbreq */
3254 if (tevent_req_nomem(state->reqs[0], req)) {
3255 return tevent_req_post(req, ev);
3257 tevent_req_set_callback(
3258 state->reqs[0], lockread_lockingx_done, req);
3260 state->reqs[1] = cli_read_andx_create(
3267 &state->smbreqs[1]); /* psmbreq */
3268 if (tevent_req_nomem(state->reqs[1], req)) {
3269 return tevent_req_post(req, ev);
3271 tevent_req_set_callback(
3272 state->reqs[1], lockread_read_andx_done, req);
3274 status = smb1cli_req_chain_submit(state->smbreqs, 2);
3275 if (tevent_req_nterror(req, status)) {
3276 return tevent_req_post(req, ev);
3281 static void lockread_lockingx_done(struct tevent_req *subreq)
3283 struct tevent_req *req = tevent_req_callback_data(
3284 subreq, struct tevent_req);
3285 struct lockread_state *state = tevent_req_data(
3286 req, struct lockread_state);
3287 state->lock_status = cli_lockingx_recv(subreq);
3288 TALLOC_FREE(subreq);
3290 "lockingx returned %s\n",
3291 nt_errstr(state->lock_status));
3294 static void lockread_read_andx_done(struct tevent_req *subreq)
3296 struct tevent_req *req = tevent_req_callback_data(
3297 subreq, struct tevent_req);
3298 struct lockread_state *state = tevent_req_data(
3299 req, struct lockread_state);
3300 ssize_t received = -1;
3301 uint8_t *rcvbuf = NULL;
3303 state->read_status = cli_read_andx_recv(subreq, &received, &rcvbuf);
3306 "read returned %s\n",
3307 nt_errstr(state->read_status));
3309 if (!NT_STATUS_IS_OK(state->read_status)) {
3310 TALLOC_FREE(subreq);
3311 tevent_req_done(req);
3316 state->readbuf = talloc_memdup(state, rcvbuf, received);
3317 TALLOC_FREE(subreq);
3318 if (tevent_req_nomem(state->readbuf, req)) {
3322 TALLOC_FREE(subreq);
3323 tevent_req_done(req);
3326 static NTSTATUS lockread_recv(
3327 struct tevent_req *req,
3328 NTSTATUS *lock_status,
3329 NTSTATUS *read_status,
3330 TALLOC_CTX *mem_ctx,
3333 struct lockread_state *state = tevent_req_data(
3334 req, struct lockread_state);
3337 if (tevent_req_is_nterror(req, &status)) {
3341 *lock_status = state->lock_status;
3342 *read_status = state->read_status;
3343 if (state->readbuf != NULL) {
3344 *read_buf = talloc_move(mem_ctx, &state->readbuf);
3349 return NT_STATUS_OK;
3352 struct lock12_state {
3356 static void lock12_closed(struct tevent_req *subreq);
3357 static void lock12_read(struct tevent_req *subreq);
3359 static struct tevent_req *lock12_send(
3360 TALLOC_CTX *mem_ctx,
3361 struct tevent_context *ev,
3362 struct cli_state *cli,
3366 struct tevent_req *req = NULL, *subreq = NULL;
3367 struct lock12_state *state = NULL;
3369 req = tevent_req_create(mem_ctx, &state, struct lock12_state);
3374 subreq = deferred_close_send(state, ev, 1, cli, fnum1);
3375 if (tevent_req_nomem(subreq, req)) {
3376 return tevent_req_post(req, ev);
3378 tevent_req_set_callback(subreq, lock12_closed, req);
3380 subreq = lockread_send(state, ev, cli, fnum2);
3381 if (tevent_req_nomem(subreq, req)) {
3382 return tevent_req_post(req, ev);
3384 tevent_req_set_callback(subreq, lock12_read, req);
3389 static void lock12_closed(struct tevent_req *subreq)
3391 struct tevent_req *req = tevent_req_callback_data(
3392 subreq, struct tevent_req);
3395 status = deferred_close_recv(subreq);
3396 TALLOC_FREE(subreq);
3397 DBG_DEBUG("close returned %s\n", nt_errstr(status));
3398 if (tevent_req_nterror(req, status)) {
3403 static void lock12_read(struct tevent_req *subreq)
3405 struct tevent_req *req = tevent_req_callback_data(
3406 subreq, struct tevent_req);
3407 struct lock12_state *state = tevent_req_data(
3408 req, struct lock12_state);
3409 NTSTATUS status, lock_status, read_status;
3410 uint8_t *buf = NULL;
3412 status = lockread_recv(
3413 subreq, &lock_status, &read_status, state, &buf);
3414 TALLOC_FREE(subreq);
3415 if (tevent_req_nterror(req, status) ||
3416 tevent_req_nterror(req, lock_status) ||
3417 tevent_req_nterror(req, read_status)) {
3420 tevent_req_done(req);
3423 static NTSTATUS lock12_recv(struct tevent_req *req)
3428 if (tevent_req_is_nterror(req, &status)) {
3431 return NT_STATUS_OK;
3434 static bool run_locktest12(int dummy)
3436 struct tevent_context *ev = NULL;
3437 struct tevent_req *req = NULL;
3438 struct cli_state *cli = NULL;
3439 const char fname[] = "\\lockt12.lck";
3440 uint16_t fnum1, fnum2;
3446 printf("starting locktest12\n");
3448 ev = samba_tevent_context_init(NULL);
3450 d_fprintf(stderr, "samba_tevent_context_init failed\n");
3454 ok = torture_open_connection(&cli, 0);
3458 smbXcli_conn_set_sockopt(cli->conn, sockops);
3460 status = cli_openx(cli, fname, O_CREAT|O_RDWR, DENY_NONE, &fnum1);
3461 if (!NT_STATUS_IS_OK(status)) {
3463 "cli_openx failed: %s\n",
3468 status = cli_openx(cli, fname, O_CREAT|O_RDWR, DENY_NONE, &fnum2);
3469 if (!NT_STATUS_IS_OK(status)) {
3471 "cli_openx failed: %s\n",
3476 status = cli_writeall(cli, fnum1, 0, &data, 0, sizeof(data), NULL);
3477 if (!NT_STATUS_IS_OK(status)) {
3479 "cli_writeall failed: %s\n",
3484 status = cli_locktype(
3485 cli, fnum1, 0, 1, 0, LOCKING_ANDX_EXCLUSIVE_LOCK);
3486 if (!NT_STATUS_IS_OK(status)) {
3488 "cli_locktype failed: %s\n",
3493 req = lock12_send(ev, ev, cli, fnum1, fnum2);
3495 d_fprintf(stderr, "lock12_send failed\n");
3499 ok = tevent_req_poll_ntstatus(req, ev, &status);
3501 d_fprintf(stderr, "tevent_req_poll_ntstatus failed\n");
3505 if (!NT_STATUS_IS_OK(status)) {
3507 "tevent_req_poll_ntstatus returned %s\n",
3512 status = lock12_recv(req);
3513 if (!NT_STATUS_IS_OK(status)) {
3514 d_fprintf(stderr, "lock12 returned %s\n", nt_errstr(status));
3521 torture_close_connection(cli);
3526 struct lock_ntcancel_state {
3527 struct timeval start;
3528 struct smb1_lock_element lck;
3529 struct tevent_req *subreq;
3532 static void lock_ntcancel_waited(struct tevent_req *subreq);
3533 static void lock_ntcancel_done(struct tevent_req *subreq);
3535 static struct tevent_req *lock_ntcancel_send(
3536 TALLOC_CTX *mem_ctx,
3537 struct tevent_context *ev,
3538 struct cli_state *cli,
3541 struct tevent_req *req = NULL, *subreq = NULL;
3542 struct lock_ntcancel_state *state = NULL;
3544 req = tevent_req_create(mem_ctx, &state, struct lock_ntcancel_state);
3548 state->lck = (struct smb1_lock_element) {
3549 .pid = cli_getpid(cli), .offset = 0, .length = 1,
3551 state->start = timeval_current();
3553 state->subreq = cli_lockingx_send(
3554 state, /* mem_ctx */
3555 ev, /* tevent_context */
3558 LOCKING_ANDX_EXCLUSIVE_LOCK, /* typeoflock */
3559 0, /* newoplocklevel */
3560 10000, /* timeout */
3561 0, /* num_unlocks */
3564 &state->lck); /* locks */
3565 if (tevent_req_nomem(state->subreq, req)) {
3566 return tevent_req_post(req, ev);
3568 tevent_req_set_callback(state->subreq, lock_ntcancel_done, req);
3570 subreq = tevent_wakeup_send(state, ev, timeval_current_ofs(1, 0));
3571 if (tevent_req_nomem(subreq, req)) {
3572 return tevent_req_post(req, ev);
3574 tevent_req_set_callback(subreq, lock_ntcancel_waited, req);
3578 static void lock_ntcancel_waited(struct tevent_req *subreq)
3580 struct tevent_req *req = tevent_req_callback_data(
3581 subreq, struct tevent_req);
3582 struct lock_ntcancel_state *state = tevent_req_data(
3583 req, struct lock_ntcancel_state);
3586 ok = tevent_wakeup_recv(subreq);
3587 TALLOC_FREE(subreq);
3589 tevent_req_oom(req);
3593 ok = tevent_req_cancel(state->subreq);
3595 d_fprintf(stderr, "Could not cancel subreq\n");
3596 tevent_req_oom(req);
3601 static void lock_ntcancel_done(struct tevent_req *subreq)
3603 struct tevent_req *req = tevent_req_callback_data(
3604 subreq, struct tevent_req);
3605 struct lock_ntcancel_state *state = tevent_req_data(
3606 req, struct lock_ntcancel_state);
3610 status = cli_lockingx_recv(subreq);
3611 TALLOC_FREE(subreq);
3613 if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
3614 d_printf("cli_lockingx returned %s\n", nt_errstr(status));
3615 tevent_req_nterror(req, NT_STATUS_UNSUCCESSFUL);
3619 elapsed = timeval_elapsed(&state->start);
3622 d_printf("cli_lockingx was too slow, cancel did not work\n");
3623 tevent_req_nterror(req, NT_STATUS_UNSUCCESSFUL);
3627 tevent_req_done(req);
3630 static NTSTATUS lock_ntcancel_recv(struct tevent_req *req)
3632 return tevent_req_simple_recv_ntstatus(req);
3635 static bool run_locktest13(int dummy)
3637 struct tevent_context *ev = NULL;
3638 struct tevent_req *req = NULL;
3639 struct cli_state *cli = NULL;
3640 const char fname[] = "\\lockt13.lck";
3641 uint16_t fnum1, fnum2;
3647 printf("starting locktest13\n");
3649 ev = samba_tevent_context_init(NULL);
3651 d_fprintf(stderr, "samba_tevent_context_init failed\n");
3655 ok = torture_open_connection(&cli, 0);
3659 smbXcli_conn_set_sockopt(cli->conn, sockops);
3661 status = cli_openx(cli, fname, O_CREAT|O_RDWR, DENY_NONE, &fnum1);
3662 if (!NT_STATUS_IS_OK(status)) {
3664 "cli_openx failed: %s\n",
3669 status = cli_openx(cli, fname, O_CREAT|O_RDWR, DENY_NONE, &fnum2);
3670 if (!NT_STATUS_IS_OK(status)) {
3672 "cli_openx failed: %s\n",
3677 status = cli_writeall(cli, fnum1, 0, &data, 0, sizeof(data), NULL);
3678 if (!NT_STATUS_IS_OK(status)) {
3680 "cli_writeall failed: %s\n",
3685 status = cli_locktype(
3686 cli, fnum1, 0, 1, 0, LOCKING_ANDX_EXCLUSIVE_LOCK);
3687 if (!NT_STATUS_IS_OK(status)) {
3689 "cli_locktype failed: %s\n",
3694 req = lock_ntcancel_send(ev, ev, cli, fnum2);
3696 d_fprintf(stderr, "lock_ntcancel_send failed\n");
3700 ok = tevent_req_poll_ntstatus(req, ev, &status);
3702 d_fprintf(stderr, "tevent_req_poll_ntstatus failed\n");
3706 if (!NT_STATUS_IS_OK(status)) {
3708 "tevent_req_poll_ntstatus returned %s\n",
3713 status = lock_ntcancel_recv(req);
3714 if (!NT_STATUS_IS_OK(status)) {
3716 "lock_ntcancel returned %s\n",
3724 torture_close_connection(cli);
3730 test whether fnums and tids open on one VC are available on another (a major
3733 static bool run_fdpasstest(int dummy)
3735 struct cli_state *cli1, *cli2;
3736 const char *fname = "\\fdpass.tst";
3741 if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
3744 smbXcli_conn_set_sockopt(cli1->conn, sockops);
3745 smbXcli_conn_set_sockopt(cli2->conn, sockops);
3747 printf("starting fdpasstest\n");
3749 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3751 status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
3753 if (!NT_STATUS_IS_OK(status)) {
3754 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
3758 status = cli_writeall(cli1, fnum1, 0, (const uint8_t *)"hello world\n", 0,
3760 if (!NT_STATUS_IS_OK(status)) {
3761 printf("write failed (%s)\n", nt_errstr(status));
3765 cli_state_set_uid(cli2, cli_state_get_uid(cli1));
3766 cli_state_set_tid(cli2, cli_state_get_tid(cli1));
3767 cli_setpid(cli2, cli_getpid(cli1));
3769 if (test_cli_read(cli2, fnum1, buf, 0, 13, NULL, 13)) {
3770 printf("read succeeded! nasty security hole [%s]\n", buf);
3774 cli_close(cli1, fnum1);
3775 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3777 torture_close_connection(cli1);
3778 torture_close_connection(cli2);
3780 printf("finished fdpasstest\n");
3784 static bool run_fdsesstest(int dummy)
3786 struct cli_state *cli;
3788 uint16_t saved_vuid;
3790 uint32_t saved_cnum;
3791 const char *fname = "\\fdsess.tst";
3792 const char *fname1 = "\\fdsess1.tst";
3799 if (!torture_open_connection(&cli, 0))
3801 smbXcli_conn_set_sockopt(cli->conn, sockops);
3803 if (!torture_cli_session_setup2(cli, &new_vuid))
3806 saved_cnum = cli_state_get_tid(cli);
3807 if (!NT_STATUS_IS_OK(cli_tree_connect(cli, share, "?????", NULL)))
3809 new_cnum = cli_state_get_tid(cli);
3810 cli_state_set_tid(cli, saved_cnum);
3812 printf("starting fdsesstest\n");
3814 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3815 cli_unlink(cli, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3817 status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
3818 if (!NT_STATUS_IS_OK(status)) {
3819 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
3823 status = cli_writeall(cli, fnum1, 0, (const uint8_t *)"hello world\n", 0, 13,
3825 if (!NT_STATUS_IS_OK(status)) {
3826 printf("write failed (%s)\n", nt_errstr(status));
3830 saved_vuid = cli_state_get_uid(cli);
3831 cli_state_set_uid(cli, new_vuid);
3833 if (test_cli_read(cli, fnum1, buf, 0, 13, NULL, 13)) {
3834 printf("read succeeded with different vuid! "
3835 "nasty security hole [%s]\n", buf);
3838 /* Try to open a file with different vuid, samba cnum. */
3839 if (NT_STATUS_IS_OK(cli_openx(cli, fname1, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum2))) {
3840 printf("create with different vuid, same cnum succeeded.\n");
3841 cli_close(cli, fnum2);
3842 cli_unlink(cli, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3844 printf("create with different vuid, same cnum failed.\n");
3845 printf("This will cause problems with service clients.\n");
3849 cli_state_set_uid(cli, saved_vuid);
3851 /* Try with same vuid, different cnum. */
3852 cli_state_set_tid(cli, new_cnum);
3854 if (test_cli_read(cli, fnum1, buf, 0, 13, NULL, 13)) {
3855 printf("read succeeded with different cnum![%s]\n", buf);
3859 cli_state_set_tid(cli, saved_cnum);
3860 cli_close(cli, fnum1);
3861 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3863 torture_close_connection(cli);
3865 printf("finished fdsesstest\n");
3870 This test checks that
3872 1) the server does not allow an unlink on a file that is open
3874 static bool run_unlinktest(int dummy)
3876 struct cli_state *cli;
3877 const char *fname = "\\unlink.tst";
3879 bool correct = True;
3882 if (!torture_open_connection(&cli, 0)) {
3886 smbXcli_conn_set_sockopt(cli->conn, sockops);
3888 printf("starting unlink test\n");
3890 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3894 status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
3895 if (!NT_STATUS_IS_OK(status)) {
3896 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
3900 status = cli_unlink(cli, fname,
3901 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3902 if (NT_STATUS_IS_OK(status)) {
3903 printf("error: server allowed unlink on an open file\n");
3906 correct = check_error(__LINE__, status, ERRDOS, ERRbadshare,
3907 NT_STATUS_SHARING_VIOLATION);
3910 cli_close(cli, fnum);
3911 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3913 if (!torture_close_connection(cli)) {
3917 printf("unlink test finished\n");
3924 test how many open files this server supports on the one socket
3926 static bool run_maxfidtest(int dummy)
3928 struct cli_state *cli;
3930 uint16_t fnums[0x11000];
3933 bool correct = True;
3939 printf("failed to connect\n");
3943 smbXcli_conn_set_sockopt(cli->conn, sockops);
3945 for (i=0; i<0x11000; i++) {
3946 slprintf(fname,sizeof(fname)-1,"\\maxfid.%d.%d", i,(int)getpid());
3947 status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_TRUNC, DENY_NONE,
3949 if (!NT_STATUS_IS_OK(status)) {
3950 printf("open of %s failed (%s)\n",
3951 fname, nt_errstr(status));
3952 printf("maximum fnum is %d\n", i);
3960 printf("cleaning up\n");
3962 slprintf(fname,sizeof(fname)-1,"\\maxfid.%d.%d", i,(int)getpid());
3963 cli_close(cli, fnums[i]);
3965 status = cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3966 if (!NT_STATUS_IS_OK(status)) {
3967 printf("unlink of %s failed (%s)\n",
3968 fname, nt_errstr(status));
3975 printf("maxfid test finished\n");
3976 if (!torture_close_connection(cli)) {
3982 /* generate a random buffer */
3983 static void rand_buf(char *buf, int len)
3986 *buf = (char)sys_random();
3991 /* send smb negprot commands, not reading the response */
3992 static bool run_negprot_nowait(int dummy)
3994 struct tevent_context *ev;
3996 struct cli_state *cli;
3997 bool correct = True;
3999 printf("starting negprot nowait test\n");
4001 ev = samba_tevent_context_init(talloc_tos());
4006 if (!(cli = open_nbt_connection())) {
4011 for (i=0;i<50000;i++) {
4012 struct tevent_req *req;
4014 req = smbXcli_negprot_send(
4027 if (!tevent_req_poll(req, ev)) {
4028 d_fprintf(stderr, "tevent_req_poll failed: %s\n",
4036 if (torture_close_connection(cli)) {
4040 printf("finished negprot nowait test\n");
4045 /* send smb negprot commands, not reading the response */
4046 static bool run_bad_nbt_session(int dummy)
4048 struct nmb_name called, calling;
4049 struct sockaddr_storage ss;
4054 printf("starting bad nbt session test\n");
4056 make_nmb_name(&calling, myname, 0x0);
4057 make_nmb_name(&called , host, 0x20);
4059 if (!resolve_name(host, &ss, 0x20, true)) {
4060 d_fprintf(stderr, "Could not resolve name %s\n", host);
4064 status = open_socket_out(&ss, NBT_SMB_PORT, 10000, &fd);
4065 if (!NT_STATUS_IS_OK(status)) {
4066 d_fprintf(stderr, "open_socket_out failed: %s\n",
4071 ret = cli_bad_session_request(fd, &calling, &called);
4074 d_fprintf(stderr, "open_socket_out failed: %s\n",
4079 printf("finished bad nbt session test\n");
4083 /* send random IPC commands */
4084 static bool run_randomipc(int dummy)
4086 char *rparam = NULL;
4088 unsigned int rdrcnt,rprcnt;
4090 int api, param_len, i;
4091 struct cli_state *cli;
4092 bool correct = True;
4095 printf("starting random ipc test\n");
4097 if (!torture_open_connection(&cli, 0)) {
4101 for (i=0;i<count;i++) {
4102 api = sys_random() % 500;
4103 param_len = (sys_random() % 64);
4105 rand_buf(param, param_len);
4110 param, param_len, 8,
4111 NULL, 0, CLI_BUFFER_SIZE,
4115 printf("%d/%d\r", i,count);
4118 printf("%d/%d\n", i, count);
4120 if (!torture_close_connection(cli)) {
4127 printf("finished random ipc test\n");
4134 static void browse_callback(const char *sname, uint32_t stype,
4135 const char *comment, void *state)
4137 printf("\t%20.20s %08x %s\n", sname, stype, comment);
4143 This test checks the browse list code
4146 static bool run_browsetest(int dummy)
4148 static struct cli_state *cli;
4149 bool correct = True;
4151 printf("starting browse test\n");
4153 if (!torture_open_connection(&cli, 0)) {
4157 printf("domain list:\n");
4158 cli_NetServerEnum(cli, cli->server_domain,
4159 SV_TYPE_DOMAIN_ENUM,
4160 browse_callback, NULL);
4162 printf("machine list:\n");
4163 cli_NetServerEnum(cli, cli->server_domain,
4165 browse_callback, NULL);
4167 if (!torture_close_connection(cli)) {
4171 printf("browse test finished\n");
4177 static bool check_attributes(struct cli_state *cli,
4179 uint32_t expected_attrs)
4182 NTSTATUS status = cli_getatr(cli,
4187 if (!NT_STATUS_IS_OK(status)) {
4188 printf("cli_getatr failed with %s\n",
4192 if (attrs != expected_attrs) {
4193 printf("Attributes incorrect 0x%x, should be 0x%x\n",
4194 (unsigned int)attrs,
4195 (unsigned int)expected_attrs);
4202 This checks how the getatr calls works
4204 static bool run_attrtest(int dummy)
4206 struct cli_state *cli;
4209 const char *fname = "\\attrib123456789.tst";
4210 bool correct = True;
4213 printf("starting attrib test\n");
4215 if (!torture_open_connection(&cli, 0)) {
4219 /* Ensure we can't unlink with out-of-range (unknown) attribute. */
4220 status = cli_unlink(cli, fname, 0x20000);
4221 if (!NT_STATUS_EQUAL(status, NT_STATUS_INVALID_PARAMETER)) {
4226 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4227 cli_openx(cli, fname,
4228 O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum);
4229 cli_close(cli, fnum);
4231 status = cli_getatr(cli, fname, NULL, NULL, &t);
4232 if (!NT_STATUS_IS_OK(status)) {
4233 printf("getatr failed (%s)\n", nt_errstr(status));
4237 if (labs(t - time(NULL)) > 60*60*24*10) {
4238 printf("ERROR: SMBgetatr bug. time is %s",
4244 t2 = t-60*60*24; /* 1 day ago */
4246 /* Ensure we can't set with out-of-range (unknown) attribute. */
4247 status = cli_setatr(cli, fname, 0x20000, t2);
4248 if (!NT_STATUS_EQUAL(status, NT_STATUS_INVALID_PARAMETER)) {
4253 status = cli_setatr(cli, fname, 0, t2);
4254 if (!NT_STATUS_IS_OK(status)) {
4255 printf("setatr failed (%s)\n", nt_errstr(status));
4259 status = cli_getatr(cli, fname, NULL, NULL, &t);
4260 if (!NT_STATUS_IS_OK(status)) {
4261 printf("getatr failed (%s)\n", nt_errstr(status));
4266 printf("ERROR: getatr/setatr bug. times are\n%s",
4268 printf("%s", ctime(&t2));
4272 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4274 /* Check cli_setpathinfo_ext() */
4275 /* Re-create the file. */
4276 status = cli_openx(cli, fname,
4277 O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum);
4278 if (!NT_STATUS_IS_OK(status)) {
4279 printf("Failed to recreate %s (%s)\n",
4280 fname, nt_errstr(status));
4283 cli_close(cli, fnum);
4285 status = cli_setpathinfo_ext(
4288 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* create */
4289 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* access */
4290 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* write */
4291 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* change */
4292 FILE_ATTRIBUTE_SYSTEM |
4293 FILE_ATTRIBUTE_HIDDEN |
4294 FILE_ATTRIBUTE_READONLY);
4295 if (!NT_STATUS_IS_OK(status)) {
4296 printf("cli_setpathinfo_ext failed with %s\n",
4301 /* Check attributes are correct. */
4302 correct = check_attributes(cli,
4304 FILE_ATTRIBUTE_SYSTEM |
4305 FILE_ATTRIBUTE_HIDDEN |
4306 FILE_ATTRIBUTE_READONLY);
4307 if (correct == false) {
4311 /* Setting to FILE_ATTRIBUTE_NORMAL should be ignored. */
4312 status = cli_setpathinfo_ext(
4315 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* create */
4316 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* access */
4317 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* write */
4318 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* change */
4319 FILE_ATTRIBUTE_NORMAL);
4320 if (!NT_STATUS_IS_OK(status)) {
4321 printf("cli_setpathinfo_ext failed with %s\n",
4326 /* Check attributes are correct. */
4327 correct = check_attributes(cli,
4329 FILE_ATTRIBUTE_SYSTEM |
4330 FILE_ATTRIBUTE_HIDDEN |
4331 FILE_ATTRIBUTE_READONLY);
4332 if (correct == false) {
4336 /* Setting to (uint16_t)-1 should also be ignored. */
4337 status = cli_setpathinfo_ext(
4340 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* create */
4341 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* access */
4342 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* write */
4343 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* change */
4345 if (!NT_STATUS_IS_OK(status)) {
4346 printf("cli_setpathinfo_ext failed with %s\n",
4351 /* Check attributes are correct. */
4352 correct = check_attributes(cli,
4354 FILE_ATTRIBUTE_SYSTEM |
4355 FILE_ATTRIBUTE_HIDDEN |
4356 FILE_ATTRIBUTE_READONLY);
4357 if (correct == false) {
4361 /* Setting to 0 should clear them all. */
4362 status = cli_setpathinfo_ext(
4365 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* create */
4366 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* access */
4367 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* write */
4368 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* change */
4370 if (!NT_STATUS_IS_OK(status)) {
4371 printf("cli_setpathinfo_ext failed with %s\n",
4376 /* Check attributes are correct. */
4377 correct = check_attributes(cli,
4379 FILE_ATTRIBUTE_NORMAL);
4380 if (correct == false) {
4388 FILE_ATTRIBUTE_SYSTEM |
4389 FILE_ATTRIBUTE_HIDDEN|
4390 FILE_ATTRIBUTE_READONLY);
4392 if (!torture_close_connection(cli)) {
4396 printf("attrib test finished\n");
4401 static NTSTATUS cli_qfilename(
4402 struct cli_state *cli,
4404 TALLOC_CTX *mem_ctx,
4407 uint16_t recv_flags2;
4414 status = cli_qfileinfo(talloc_tos(),
4417 FSCC_FILE_NAME_INFORMATION,
4423 if (!NT_STATUS_IS_OK(status)) {
4427 namelen = IVAL(rdata, 0);
4428 if (namelen > (num_rdata - 4)) {
4430 return NT_STATUS_INVALID_NETWORK_RESPONSE;
4433 pull_string_talloc(mem_ctx,
4434 (const char *)rdata,
4441 status = map_nt_error_from_unix(errno);
4448 return NT_STATUS_OK;
4452 This checks a couple of trans2 calls
4454 static bool run_trans2test(int dummy)
4456 struct cli_state *cli;
4459 time_t c_time, a_time, m_time;
4460 struct timespec c_time_ts, a_time_ts, m_time_ts, w_time_ts, m_time2_ts;
4461 const char *fname = "\\trans2.tst";
4462 const char *dname = "\\trans2";
4463 const char *fname2 = "\\trans2\\trans2.tst";
4465 bool correct = True;
4470 printf("starting trans2 test\n");
4472 if (!torture_open_connection(&cli, 0)) {
4476 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
4477 /* Ensure ino is zero, SMB2 gets a real one. */
4480 /* Ensure ino is -1, SMB1 never gets a real one. */
4484 status = cli_get_fs_attr_info(cli, &fs_attr);
4485 if (!NT_STATUS_IS_OK(status)) {
4486 printf("ERROR: cli_get_fs_attr_info returned %s\n",
4491 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4492 cli_openx(cli, fname, O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum);
4493 status = cli_qfileinfo_basic(cli, fnum, NULL, &size, &c_time_ts,
4494 &a_time_ts, &w_time_ts, &m_time_ts, NULL);
4495 if (!NT_STATUS_IS_OK(status)) {
4496 printf("ERROR: qfileinfo failed (%s)\n", nt_errstr(status));
4500 status = cli_qfilename(cli, fnum, talloc_tos(), &pname);
4501 if (!NT_STATUS_IS_OK(status)) {
4502 printf("ERROR: qfilename failed (%s)\n", nt_errstr(status));
4505 else if (strcmp(pname, fname)) {
4506 printf("qfilename gave different name? [%s] [%s]\n",
4511 cli_close(cli, fnum);
4515 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4516 status = cli_openx(cli, fname, O_RDWR | O_CREAT | O_TRUNC, DENY_NONE,
4518 if (!NT_STATUS_IS_OK(status)) {
4519 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
4522 cli_close(cli, fnum);
4524 status = cli_qpathinfo1(cli, fname, &c_time, &a_time, &m_time, &size,
4526 if (!NT_STATUS_IS_OK(status)) {
4527 printf("ERROR: qpathinfo failed (%s)\n", nt_errstr(status));
4530 time_t t = time(NULL);
4532 if (c_time != m_time) {
4533 printf("create time=%s", ctime(&c_time));
4534 printf("modify time=%s", ctime(&m_time));
4535 printf("This system appears to have sticky create times\n");
4537 if ((labs(a_time - t) > 60) && (a_time % (60*60) == 0)) {
4538 printf("access time=%s", ctime(&a_time));
4539 printf("This system appears to set a midnight access time\n");
4543 if (labs(m_time - t) > 60*60*24*7) {
4544 printf("ERROR: totally incorrect times - maybe word reversed? mtime=%s", ctime(&m_time));
4550 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4551 cli_openx(cli, fname,
4552 O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum);
4553 cli_close(cli, fnum);
4554 status = cli_qpathinfo2(cli,
4564 if (!NT_STATUS_IS_OK(status)) {
4565 printf("ERROR: qpathinfo2 failed (%s)\n", nt_errstr(status));
4568 if (w_time_ts.tv_sec < 60*60*24*2) {
4569 printf("write time=%s", ctime(&w_time_ts.tv_sec));
4570 printf("This system appears to set a initial 0 write time\n");
4573 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
4574 /* SMB2 should always return an inode. */
4576 printf("SMB2 bad inode (0)\n");
4580 /* SMB1 must always return zero here. */
4582 printf("SMB1 bad inode (!0)\n");
4588 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4591 /* check if the server updates the directory modification time
4592 when creating a new file */
4593 status = cli_mkdir(cli, dname);
4594 if (!NT_STATUS_IS_OK(status)) {
4595 printf("ERROR: mkdir failed (%s)\n", nt_errstr(status));
4599 status = cli_qpathinfo2(cli,
4609 if (!NT_STATUS_IS_OK(status)) {
4610 printf("ERROR: qpathinfo2 failed (%s)\n", nt_errstr(status));
4614 cli_openx(cli, fname2,
4615 O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum);
4616 cli_writeall(cli, fnum, 0, (uint8_t *)&fnum, 0, sizeof(fnum), NULL);
4617 cli_close(cli, fnum);
4618 status = cli_qpathinfo2(cli,
4628 if (!NT_STATUS_IS_OK(status)) {
4629 printf("ERROR: qpathinfo2 failed (%s)\n", nt_errstr(status));
4632 if (memcmp(&m_time_ts, &m_time2_ts, sizeof(struct timespec))
4634 printf("This system does not update directory modification times\n");
4638 cli_unlink(cli, fname2, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4639 cli_rmdir(cli, dname);
4641 if (!torture_close_connection(cli)) {
4645 printf("trans2 test finished\n");
4651 This checks new W2K calls.
4654 static NTSTATUS new_trans(struct cli_state *pcli, int fnum, int level)
4656 uint8_t *buf = NULL;
4660 status = cli_qfileinfo(talloc_tos(), pcli, fnum, level, 0,
4661 CLI_BUFFER_SIZE, NULL, &buf, &len);
4662 if (!NT_STATUS_IS_OK(status)) {
4663 printf("ERROR: qfileinfo (%d) failed (%s)\n", level,
4666 printf("qfileinfo: level %d, len = %u\n", level, len);
4667 dump_data(0, (uint8_t *)buf, len);
4674 static bool run_w2ktest(int dummy)
4676 struct cli_state *cli;
4678 const char *fname = "\\w2ktest\\w2k.tst";
4680 bool correct = True;
4682 printf("starting w2k test\n");
4684 if (!torture_open_connection(&cli, 0)) {
4688 cli_openx(cli, fname,
4689 O_RDWR | O_CREAT , DENY_NONE, &fnum);
4691 for (level = 1004; level < 1040; level++) {
4692 new_trans(cli, fnum, level);
4695 cli_close(cli, fnum);
4697 if (!torture_close_connection(cli)) {
4701 printf("w2k test finished\n");
4708 this is a harness for some oplock tests
4710 static bool run_oplock1(int dummy)
4712 struct cli_state *cli1;
4713 const char *fname = "\\lockt1.lck";
4715 bool correct = True;
4718 printf("starting oplock test 1\n");
4720 if (!torture_open_connection(&cli1, 0)) {
4724 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4726 smbXcli_conn_set_sockopt(cli1->conn, sockops);
4728 cli1->use_oplocks = True;
4730 status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
4732 if (!NT_STATUS_IS_OK(status)) {
4733 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
4737 cli1->use_oplocks = False;
4739 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4740 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4742 status = cli_close(cli1, fnum1);
4743 if (!NT_STATUS_IS_OK(status)) {
4744 printf("close2 failed (%s)\n", nt_errstr(status));
4748 status = cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4749 if (!NT_STATUS_IS_OK(status)) {
4750 printf("unlink failed (%s)\n", nt_errstr(status));
4754 if (!torture_close_connection(cli1)) {
4758 printf("finished oplock test 1\n");
4763 static bool run_oplock2(int dummy)
4765 struct cli_state *cli1, *cli2;
4766 const char *fname = "\\lockt2.lck";
4767 uint16_t fnum1, fnum2;
4768 int saved_use_oplocks = use_oplocks;
4770 bool correct = True;
4771 volatile bool *shared_correct;
4775 shared_correct = (volatile bool *)anonymous_shared_allocate(sizeof(bool));
4776 *shared_correct = True;
4778 use_level_II_oplocks = True;
4781 printf("starting oplock test 2\n");
4783 if (!torture_open_connection(&cli1, 0)) {
4784 use_level_II_oplocks = False;
4785 use_oplocks = saved_use_oplocks;
4789 if (!torture_open_connection(&cli2, 1)) {
4790 use_level_II_oplocks = False;
4791 use_oplocks = saved_use_oplocks;
4795 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4797 smbXcli_conn_set_sockopt(cli1->conn, sockops);
4798 smbXcli_conn_set_sockopt(cli2->conn, sockops);
4800 status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
4802 if (!NT_STATUS_IS_OK(status)) {
4803 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
4807 /* Don't need the globals any more. */
4808 use_level_II_oplocks = False;
4809 use_oplocks = saved_use_oplocks;
4813 status = cli_openx(cli2, fname, O_RDWR, DENY_NONE, &fnum2);
4814 if (!NT_STATUS_IS_OK(status)) {
4815 printf("second open of %s failed (%s)\n", fname, nt_errstr(status));
4816 *shared_correct = False;
4822 status = cli_close(cli2, fnum2);
4823 if (!NT_STATUS_IS_OK(status)) {
4824 printf("close2 failed (%s)\n", nt_errstr(status));
4825 *shared_correct = False;
4833 /* Ensure cli1 processes the break. Empty file should always return 0
4835 status = cli_read(cli1, fnum1, buf, 0, 4, &nread);
4836 if (!NT_STATUS_IS_OK(status)) {
4837 printf("read on fnum1 failed (%s)\n", nt_errstr(status));
4839 } else if (nread != 0) {
4840 printf("read on empty fnum1 failed. recv %ld expected %d\n",
4841 (unsigned long)nread, 0);
4845 /* Should now be at level II. */
4846 /* Test if sending a write locks causes a break to none. */
4847 status = cli_lock32(cli1, fnum1, 0, 4, 0, READ_LOCK);
4848 if (!NT_STATUS_IS_OK(status)) {
4849 printf("lock failed (%s)\n", nt_errstr(status));
4853 cli_unlock(cli1, fnum1, 0, 4);
4857 status = cli_lock32(cli1, fnum1, 0, 4, 0, WRITE_LOCK);
4858 if (!NT_STATUS_IS_OK(status)) {
4859 printf("lock failed (%s)\n", nt_errstr(status));
4863 cli_unlock(cli1, fnum1, 0, 4);
4867 cli_read(cli1, fnum1, buf, 0, 4, NULL);
4869 status = cli_close(cli1, fnum1);
4870 if (!NT_STATUS_IS_OK(status)) {
4871 printf("close1 failed (%s)\n", nt_errstr(status));
4877 status = cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4878 if (!NT_STATUS_IS_OK(status)) {
4879 printf("unlink failed (%s)\n", nt_errstr(status));
4883 if (!torture_close_connection(cli1)) {
4887 if (!*shared_correct) {
4891 printf("finished oplock test 2\n");
4896 struct oplock4_state {
4897 struct tevent_context *ev;
4898 struct cli_state *cli;
4903 static void oplock4_got_break(struct tevent_req *req);
4904 static void oplock4_got_open(struct tevent_req *req);
4906 static bool run_oplock4(int dummy)
4908 struct tevent_context *ev;
4909 struct cli_state *cli1, *cli2;
4910 struct tevent_req *oplock_req, *open_req;
4911 const char *fname = "\\lockt4.lck";
4912 const char *fname_ln = "\\lockt4_ln.lck";
4913 uint16_t fnum1, fnum2;
4914 int saved_use_oplocks = use_oplocks;
4916 bool correct = true;
4920 struct oplock4_state *state;
4922 printf("starting oplock test 4\n");
4924 if (!torture_open_connection(&cli1, 0)) {
4925 use_level_II_oplocks = false;
4926 use_oplocks = saved_use_oplocks;
4930 if (!torture_open_connection(&cli2, 1)) {
4931 use_level_II_oplocks = false;
4932 use_oplocks = saved_use_oplocks;
4936 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4937 cli_unlink(cli1, fname_ln, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4939 smbXcli_conn_set_sockopt(cli1->conn, sockops);
4940 smbXcli_conn_set_sockopt(cli2->conn, sockops);
4942 /* Create the file. */
4943 status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
4945 if (!NT_STATUS_IS_OK(status)) {
4946 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
4950 status = cli_close(cli1, fnum1);
4951 if (!NT_STATUS_IS_OK(status)) {
4952 printf("close1 failed (%s)\n", nt_errstr(status));
4956 /* Now create a hardlink. */
4957 status = cli_hardlink(cli1, fname, fname_ln);
4958 if (!NT_STATUS_IS_OK(status)) {
4959 printf("nt hardlink failed (%s)\n", nt_errstr(status));
4963 /* Prove that opening hardlinks cause deny modes to conflict. */
4964 status = cli_openx(cli1, fname, O_RDWR, DENY_ALL, &fnum1);
4965 if (!NT_STATUS_IS_OK(status)) {
4966 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
4970 status = cli_openx(cli1, fname_ln, O_RDWR, DENY_NONE, &fnum2);
4971 if (NT_STATUS_IS_OK(status)) {
4972 printf("open of %s succeeded - should fail with sharing violation.\n",
4977 if (!NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
4978 printf("open of %s should fail with sharing violation. Got %s\n",
4979 fname_ln, nt_errstr(status));
4983 status = cli_close(cli1, fnum1);
4984 if (!NT_STATUS_IS_OK(status)) {
4985 printf("close1 failed (%s)\n", nt_errstr(status));
4989 cli1->use_oplocks = true;
4990 cli2->use_oplocks = true;
4992 status = cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
4993 if (!NT_STATUS_IS_OK(status)) {
4994 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
4998 ev = samba_tevent_context_init(talloc_tos());
5000 printf("tevent_context_init failed\n");
5004 state = talloc(ev, struct oplock4_state);
5005 if (state == NULL) {
5006 printf("talloc failed\n");
5011 state->got_break = &got_break;
5012 state->fnum2 = &fnum2;
5014 oplock_req = cli_smb_oplock_break_waiter_send(
5015 talloc_tos(), ev, cli1);
5016 if (oplock_req == NULL) {
5017 printf("cli_smb_oplock_break_waiter_send failed\n");
5020 tevent_req_set_callback(oplock_req, oplock4_got_break, state);
5022 open_req = cli_openx_send(
5023 talloc_tos(), ev, cli2, fname_ln, O_RDWR, DENY_NONE);
5024 if (open_req == NULL) {
5025 printf("cli_openx_send failed\n");
5028 tevent_req_set_callback(open_req, oplock4_got_open, state);
5033 while (!got_break || fnum2 == 0xffff) {
5035 ret = tevent_loop_once(ev);
5037 printf("tevent_loop_once failed: %s\n",
5043 status = cli_close(cli2, fnum2);
5044 if (!NT_STATUS_IS_OK(status)) {
5045 printf("close2 failed (%s)\n", nt_errstr(status));
5049 status = cli_close(cli1, fnum1);
5050 if (!NT_STATUS_IS_OK(status)) {
5051 printf("close1 failed (%s)\n", nt_errstr(status));
5055 status = cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5056 if (!NT_STATUS_IS_OK(status)) {
5057 printf("unlink failed (%s)\n", nt_errstr(status));
5061 status = cli_unlink(cli1, fname_ln, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5062 if (!NT_STATUS_IS_OK(status)) {
5063 printf("unlink failed (%s)\n", nt_errstr(status));
5067 if (!torture_close_connection(cli1)) {
5075 printf("finished oplock test 4\n");
5080 static void oplock4_got_break(struct tevent_req *req)
5082 struct oplock4_state *state = tevent_req_callback_data(
5083 req, struct oplock4_state);
5088 status = cli_smb_oplock_break_waiter_recv(req, &fnum, &level);
5090 if (!NT_STATUS_IS_OK(status)) {
5091 printf("cli_smb_oplock_break_waiter_recv returned %s\n",
5095 *state->got_break = true;
5097 req = cli_oplock_ack_send(state, state->ev, state->cli, fnum,
5100 printf("cli_oplock_ack_send failed\n");
5105 static void oplock4_got_open(struct tevent_req *req)
5107 struct oplock4_state *state = tevent_req_callback_data(
5108 req, struct oplock4_state);
5111 status = cli_openx_recv(req, state->fnum2);
5112 if (!NT_STATUS_IS_OK(status)) {
5113 printf("cli_openx_recv returned %s\n", nt_errstr(status));
5114 *state->fnum2 = 0xffff;
5118 #ifdef HAVE_KERNEL_OPLOCKS_LINUX
5120 struct oplock5_state {
5125 * Async open the file that has a kernel oplock, do an echo to get
5126 * that 100% across, close the file to signal to the child fd that the
5127 * oplock can be dropped, wait for the open reply.
5130 static void oplock5_opened(struct tevent_req *subreq);
5131 static void oplock5_pong(struct tevent_req *subreq);
5132 static void oplock5_timedout(struct tevent_req *subreq);
5134 static struct tevent_req *oplock5_send(
5135 TALLOC_CTX *mem_ctx,
5136 struct tevent_context *ev,
5137 struct cli_state *cli,
5141 struct tevent_req *req = NULL, *subreq = NULL;
5142 struct oplock5_state *state = NULL;
5143 static uint8_t data = 0;
5145 req = tevent_req_create(mem_ctx, &state, struct oplock5_state);
5149 state->pipe_down_fd = pipe_down_fd;
5151 subreq = cli_ntcreate_send(
5157 SEC_FILE_READ_DATA, /* DesiredAccess */
5158 FILE_ATTRIBUTE_NORMAL, /* FileAttributes */
5159 FILE_SHARE_WRITE|FILE_SHARE_READ, /* ShareAccess */
5160 FILE_OPEN, /* CreateDisposition */
5161 FILE_NON_DIRECTORY_FILE, /* CreateOptions */
5162 0, /* Impersonation */
5163 0); /* SecurityFlags */
5164 if (tevent_req_nomem(subreq, req)) {
5165 return tevent_req_post(req, ev);
5167 tevent_req_set_callback(subreq, oplock5_opened, req);
5169 subreq = cli_echo_send(
5174 (DATA_BLOB) { .data = &data, .length = sizeof(data) });
5175 if (tevent_req_nomem(subreq, req)) {
5176 return tevent_req_post(req, ev);
5178 tevent_req_set_callback(subreq, oplock5_pong, req);
5180 subreq = tevent_wakeup_send(state, ev, timeval_current_ofs(20, 0));
5181 if (tevent_req_nomem(subreq, req)) {
5182 return tevent_req_post(req, ev);
5184 tevent_req_set_callback(subreq, oplock5_timedout, req);
5189 static void oplock5_opened(struct tevent_req *subreq)
5191 struct tevent_req *req = tevent_req_callback_data(
5192 subreq, struct tevent_req);
5196 status = cli_ntcreate_recv(subreq, &fnum, NULL);
5197 TALLOC_FREE(subreq);
5198 if (tevent_req_nterror(req, status)) {
5201 tevent_req_done(req);
5204 static void oplock5_pong(struct tevent_req *subreq)
5206 struct tevent_req *req = tevent_req_callback_data(
5207 subreq, struct tevent_req);
5208 struct oplock5_state *state = tevent_req_data(
5209 req, struct oplock5_state);
5212 status = cli_echo_recv(subreq);
5213 TALLOC_FREE(subreq);
5214 if (tevent_req_nterror(req, status)) {
5218 close(state->pipe_down_fd);
5221 static void oplock5_timedout(struct tevent_req *subreq)
5223 struct tevent_req *req = tevent_req_callback_data(
5224 subreq, struct tevent_req);
5227 ok = tevent_wakeup_recv(subreq);
5228 TALLOC_FREE(subreq);
5230 tevent_req_oom(req);
5233 tevent_req_nterror(req, NT_STATUS_TIMEOUT);
5236 static NTSTATUS oplock5_recv(struct tevent_req *req)
5238 return tevent_req_simple_recv_ntstatus(req);
5241 static bool run_oplock5(int dummy)
5243 struct tevent_context *ev = NULL;
5244 struct tevent_req *req = NULL;
5245 struct cli_state *cli = NULL;
5246 const char *fname = "oplock5.txt";
5247 int pipe_down[2], pipe_up[2];
5254 printf("starting oplock5\n");
5256 if (local_path == NULL) {
5257 d_fprintf(stderr, "oplock5 must be given a local path via "
5258 "-l <localpath>\n");
5262 ret = pipe(pipe_down);
5264 d_fprintf(stderr, "pipe() failed: %s\n", strerror(errno));
5267 ret = pipe(pipe_up);
5269 d_fprintf(stderr, "pipe() failed: %s\n", strerror(errno));
5274 if (child_pid == -1) {
5275 d_fprintf(stderr, "fork() failed: %s\n", strerror(errno));
5279 if (child_pid == 0) {
5280 char *local_file = NULL;
5283 close(pipe_down[1]);
5286 local_file = talloc_asprintf(
5287 talloc_tos(), "%s/%s", local_path, fname);
5288 if (local_file == 0) {
5292 fd = open(local_file, O_RDWR|O_CREAT, 0644);
5295 "open(%s) in child failed: %s\n",
5302 signal(SIGIO, SIG_IGN);
5304 ret = fcntl(fd, F_SETLEASE, F_WRLCK);
5307 "SETLEASE in child failed: %s\n",
5314 ret = sys_write(pipe_up[1], &c, sizeof(c));
5317 "sys_write failed: %s\n",
5321 ret = sys_read(pipe_down[0], &c, sizeof(c));
5324 "sys_read failed: %s\n",
5332 close(pipe_down[0]);
5334 ret = sys_read(pipe_up[0], &c, sizeof(c));
5337 "sys_read failed: %s\n",
5342 d_fprintf(stderr, "got error code %"PRIu8"\n", c);
5346 ok = torture_open_connection(&cli, 0);
5348 d_fprintf(stderr, "torture_open_connection failed\n");
5352 ev = samba_tevent_context_init(talloc_tos());
5354 d_fprintf(stderr, "samba_tevent_context_init failed\n");
5358 req = oplock5_send(ev, ev, cli, fname, pipe_down[1]);
5360 d_fprintf(stderr, "oplock5_send failed\n");
5364 ok = tevent_req_poll_ntstatus(req, ev, &status);
5367 "tevent_req_poll_ntstatus failed: %s\n",
5372 status = oplock5_recv(req);
5374 if (!NT_STATUS_IS_OK(status)) {
5376 "oplock5 failed: %s\n",
5384 #endif /* HAVE_KERNEL_OPLOCKS_LINUX */
5387 Test delete on close semantics.
5389 static bool run_deletetest(int dummy)
5391 struct cli_state *cli1 = NULL;
5392 struct cli_state *cli2 = NULL;
5393 const char *fname = "\\delete.file";
5394 uint16_t fnum1 = (uint16_t)-1;
5395 uint16_t fnum2 = (uint16_t)-1;
5396 bool correct = false;
5399 printf("starting delete test\n");
5401 if (!torture_open_connection(&cli1, 0)) {
5405 smbXcli_conn_set_sockopt(cli1->conn, sockops);
5407 /* Test 1 - this should delete the file on close. */
5409 cli_setatr(cli1, fname, 0, 0);
5410 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5412 status = cli_ntcreate(cli1, fname, 0, GENERIC_ALL_ACCESS|DELETE_ACCESS,
5413 FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
5414 FILE_DELETE_ON_CLOSE, 0, &fnum1, NULL);
5415 if (!NT_STATUS_IS_OK(status)) {
5416 printf("[1] open of %s failed (%s)\n", fname, nt_errstr(status));
5420 status = cli_close(cli1, fnum1);
5421 if (!NT_STATUS_IS_OK(status)) {
5422 printf("[1] close failed (%s)\n", nt_errstr(status));
5426 status = cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
5427 if (NT_STATUS_IS_OK(status)) {
5428 printf("[1] open of %s succeeded (should fail)\n", fname);
5432 printf("first delete on close test succeeded.\n");
5434 /* Test 2 - this should delete the file on close. */
5436 cli_setatr(cli1, fname, 0, 0);
5437 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5439 status = cli_ntcreate(cli1, fname, 0, GENERIC_ALL_ACCESS,
5440 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
5441 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
5442 if (!NT_STATUS_IS_OK(status)) {
5443 printf("[2] open of %s failed (%s)\n", fname, nt_errstr(status));
5447 status = cli_nt_delete_on_close(cli1, fnum1, true);
5448 if (!NT_STATUS_IS_OK(status)) {
5449 printf("[2] setting delete_on_close failed (%s)\n", nt_errstr(status));
5453 status = cli_close(cli1, fnum1);
5454 if (!NT_STATUS_IS_OK(status)) {
5455 printf("[2] close failed (%s)\n", nt_errstr(status));
5459 status = cli_openx(cli1, fname, O_RDONLY, DENY_NONE, &fnum1);
5460 if (NT_STATUS_IS_OK(status)) {
5461 printf("[2] open of %s succeeded should have been deleted on close !\n", fname);
5462 status = cli_close(cli1, fnum1);
5463 if (!NT_STATUS_IS_OK(status)) {
5464 printf("[2] close failed (%s)\n", nt_errstr(status));
5466 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5470 printf("second delete on close test succeeded.\n");
5473 cli_setatr(cli1, fname, 0, 0);
5474 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5476 status = cli_ntcreate(cli1, fname, 0, GENERIC_ALL_ACCESS,
5477 FILE_ATTRIBUTE_NORMAL,
5478 FILE_SHARE_READ|FILE_SHARE_WRITE,
5479 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
5480 if (!NT_STATUS_IS_OK(status)) {
5481 printf("[3] open - 1 of %s failed (%s)\n", fname, nt_errstr(status));
5485 /* This should fail with a sharing violation - open for delete is only compatible
5486 with SHARE_DELETE. */
5488 status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
5489 FILE_ATTRIBUTE_NORMAL,
5490 FILE_SHARE_READ|FILE_SHARE_WRITE,
5491 FILE_OPEN, 0, 0, &fnum2, NULL);
5492 if (NT_STATUS_IS_OK(status)) {
5493 printf("[3] open - 2 of %s succeeded - should have failed.\n", fname);
5497 /* This should succeed. */
5498 status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
5499 FILE_ATTRIBUTE_NORMAL,
5500 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5501 FILE_OPEN, 0, 0, &fnum2, NULL);
5502 if (!NT_STATUS_IS_OK(status)) {
5503 printf("[3] open - 3 of %s failed (%s)\n", fname, nt_errstr(status));
5507 status = cli_nt_delete_on_close(cli1, fnum1, true);
5508 if (!NT_STATUS_IS_OK(status)) {
5509 printf("[3] setting delete_on_close failed (%s)\n", nt_errstr(status));
5513 status = cli_close(cli1, fnum1);
5514 if (!NT_STATUS_IS_OK(status)) {
5515 printf("[3] close 1 failed (%s)\n", nt_errstr(status));
5519 status = cli_close(cli1, fnum2);
5520 if (!NT_STATUS_IS_OK(status)) {
5521 printf("[3] close 2 failed (%s)\n", nt_errstr(status));
5525 /* This should fail - file should no longer be there. */
5527 status = cli_openx(cli1, fname, O_RDONLY, DENY_NONE, &fnum1);
5528 if (NT_STATUS_IS_OK(status)) {
5529 printf("[3] open of %s succeeded should have been deleted on close !\n", fname);
5530 status = cli_close(cli1, fnum1);
5531 if (!NT_STATUS_IS_OK(status)) {
5532 printf("[3] close failed (%s)\n", nt_errstr(status));
5534 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5538 printf("third delete on close test succeeded.\n");
5541 cli_setatr(cli1, fname, 0, 0);
5542 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5544 status = cli_ntcreate(cli1, fname, 0,
5545 FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
5546 FILE_ATTRIBUTE_NORMAL,
5547 FILE_SHARE_READ|FILE_SHARE_WRITE,
5548 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
5549 if (!NT_STATUS_IS_OK(status)) {
5550 printf("[4] open of %s failed (%s)\n", fname, nt_errstr(status));
5554 /* This should succeed. */
5555 status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
5556 FILE_ATTRIBUTE_NORMAL,
5557 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5558 FILE_OPEN, 0, 0, &fnum2, NULL);
5559 if (!NT_STATUS_IS_OK(status)) {
5560 printf("[4] open - 2 of %s failed (%s)\n", fname, nt_errstr(status));
5564 status = cli_close(cli1, fnum2);
5565 if (!NT_STATUS_IS_OK(status)) {
5566 printf("[4] close - 1 failed (%s)\n", nt_errstr(status));
5570 status = cli_nt_delete_on_close(cli1, fnum1, true);
5571 if (!NT_STATUS_IS_OK(status)) {
5572 printf("[4] setting delete_on_close failed (%s)\n", nt_errstr(status));
5576 /* This should fail - no more opens once delete on close set. */
5577 status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
5578 FILE_ATTRIBUTE_NORMAL,
5579 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5580 FILE_OPEN, 0, 0, &fnum2, NULL);
5581 if (NT_STATUS_IS_OK(status)) {
5582 printf("[4] open - 3 of %s succeeded ! Should have failed.\n", fname );
5586 status = cli_close(cli1, fnum1);
5587 if (!NT_STATUS_IS_OK(status)) {
5588 printf("[4] close - 2 failed (%s)\n", nt_errstr(status));
5592 printf("fourth delete on close test succeeded.\n");
5595 cli_setatr(cli1, fname, 0, 0);
5596 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5598 status = cli_openx(cli1, fname, O_RDWR|O_CREAT, DENY_NONE, &fnum1);
5599 if (!NT_STATUS_IS_OK(status)) {
5600 printf("[5] open of %s failed (%s)\n", fname, nt_errstr(status));
5604 /* This should fail - only allowed on NT opens with DELETE access. */
5606 status = cli_nt_delete_on_close(cli1, fnum1, true);
5607 if (NT_STATUS_IS_OK(status)) {
5608 printf("[5] setting delete_on_close on OpenX file succeeded - should fail !\n");
5612 status = cli_close(cli1, fnum1);
5613 if (!NT_STATUS_IS_OK(status)) {
5614 printf("[5] close failed (%s)\n", nt_errstr(status));
5618 printf("fifth delete on close test succeeded.\n");
5621 cli_setatr(cli1, fname, 0, 0);
5622 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5624 status = cli_ntcreate(cli1, fname, 0, FILE_READ_DATA|FILE_WRITE_DATA,
5625 FILE_ATTRIBUTE_NORMAL,
5626 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5627 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
5628 if (!NT_STATUS_IS_OK(status)) {
5629 printf("[6] open of %s failed (%s)\n", fname,
5634 /* This should fail - only allowed on NT opens with DELETE access. */
5636 status = cli_nt_delete_on_close(cli1, fnum1, true);
5637 if (NT_STATUS_IS_OK(status)) {
5638 printf("[6] setting delete_on_close on file with no delete access succeeded - should fail !\n");
5642 status = cli_close(cli1, fnum1);
5643 if (!NT_STATUS_IS_OK(status)) {
5644 printf("[6] close failed (%s)\n", nt_errstr(status));
5648 printf("sixth delete on close test succeeded.\n");
5651 cli_setatr(cli1, fname, 0, 0);
5652 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5654 status = cli_ntcreate(cli1, fname, 0,
5655 FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
5656 FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
5657 0, 0, &fnum1, NULL);
5658 if (!NT_STATUS_IS_OK(status)) {
5659 printf("[7] open of %s failed (%s)\n", fname, nt_errstr(status));
5663 status = cli_nt_delete_on_close(cli1, fnum1, true);
5664 if (!NT_STATUS_IS_OK(status)) {
5665 printf("[7] setting delete_on_close on file failed !\n");
5669 status = cli_nt_delete_on_close(cli1, fnum1, false);
5670 if (!NT_STATUS_IS_OK(status)) {
5671 printf("[7] unsetting delete_on_close on file failed !\n");
5675 status = cli_close(cli1, fnum1);
5676 if (!NT_STATUS_IS_OK(status)) {
5677 printf("[7] close - 1 failed (%s)\n", nt_errstr(status));
5681 /* This next open should succeed - we reset the flag. */
5682 status = cli_openx(cli1, fname, O_RDONLY, DENY_NONE, &fnum1);
5683 if (!NT_STATUS_IS_OK(status)) {
5684 printf("[7] open of %s failed (%s)\n", fname, nt_errstr(status));
5688 status = cli_close(cli1, fnum1);
5689 if (!NT_STATUS_IS_OK(status)) {
5690 printf("[7] close - 2 failed (%s)\n", nt_errstr(status));
5694 printf("seventh delete on close test succeeded.\n");
5697 cli_setatr(cli1, fname, 0, 0);
5698 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5700 if (!torture_open_connection(&cli2, 1)) {
5701 printf("[8] failed to open second connection.\n");
5705 smbXcli_conn_set_sockopt(cli1->conn, sockops);
5707 status = cli_ntcreate(cli1, fname, 0,
5708 FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
5709 FILE_ATTRIBUTE_NORMAL,
5710 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5711 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
5712 if (!NT_STATUS_IS_OK(status)) {
5713 printf("[8] open 1 of %s failed (%s)\n", fname, nt_errstr(status));
5717 status = cli_ntcreate(cli2, fname, 0,
5718 FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
5719 FILE_ATTRIBUTE_NORMAL,
5720 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5721 FILE_OPEN, 0, 0, &fnum2, NULL);
5722 if (!NT_STATUS_IS_OK(status)) {
5723 printf("[8] open 2 of %s failed (%s)\n", fname, nt_errstr(status));
5727 status = cli_nt_delete_on_close(cli1, fnum1, true);
5728 if (!NT_STATUS_IS_OK(status)) {
5729 printf("[8] setting delete_on_close on file failed !\n");
5733 status = cli_close(cli1, fnum1);
5734 if (!NT_STATUS_IS_OK(status)) {
5735 printf("[8] close - 1 failed (%s)\n", nt_errstr(status));
5739 status = cli_close(cli2, fnum2);
5740 if (!NT_STATUS_IS_OK(status)) {
5741 printf("[8] close - 2 failed (%s)\n", nt_errstr(status));
5745 /* This should fail.. */
5746 status = cli_openx(cli1, fname, O_RDONLY, DENY_NONE, &fnum1);
5747 if (NT_STATUS_IS_OK(status)) {
5748 printf("[8] open of %s succeeded should have been deleted on close !\n", fname);
5752 printf("eighth delete on close test succeeded.\n");
5756 /* This should fail - we need to set DELETE_ACCESS. */
5757 status = cli_ntcreate(cli1, fname, 0, FILE_READ_DATA|FILE_WRITE_DATA,
5758 FILE_ATTRIBUTE_NORMAL,
5761 FILE_DELETE_ON_CLOSE, 0, &fnum1, NULL);
5762 if (NT_STATUS_IS_OK(status)) {
5763 printf("[9] open of %s succeeded should have failed!\n", fname);
5767 printf("ninth delete on close test succeeded.\n");
5771 status = cli_ntcreate(cli1, fname, 0,
5772 FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
5773 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
5774 FILE_OVERWRITE_IF, FILE_DELETE_ON_CLOSE,
5776 if (!NT_STATUS_IS_OK(status)) {
5777 printf("[10] open of %s failed (%s)\n", fname, nt_errstr(status));
5781 /* This should delete the file. */
5782 status = cli_close(cli1, fnum1);
5783 if (!NT_STATUS_IS_OK(status)) {
5784 printf("[10] close failed (%s)\n", nt_errstr(status));
5788 /* This should fail.. */
5789 status = cli_openx(cli1, fname, O_RDONLY, DENY_NONE, &fnum1);
5790 if (NT_STATUS_IS_OK(status)) {
5791 printf("[10] open of %s succeeded should have been deleted on close !\n", fname);
5795 printf("tenth delete on close test succeeded.\n");
5799 cli_setatr(cli1, fname, 0, 0);
5800 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5802 /* Can we open a read-only file with delete access? */
5804 /* Create a readonly file. */
5805 status = cli_ntcreate(cli1, fname, 0, FILE_READ_DATA|FILE_WRITE_DATA,
5806 FILE_ATTRIBUTE_READONLY, FILE_SHARE_NONE,
5807 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
5808 if (!NT_STATUS_IS_OK(status)) {
5809 printf("[11] open of %s failed (%s)\n", fname, nt_errstr(status));
5813 status = cli_close(cli1, fnum1);
5814 if (!NT_STATUS_IS_OK(status)) {
5815 printf("[11] close failed (%s)\n", nt_errstr(status));
5819 /* Now try open for delete access. */
5820 status = cli_ntcreate(cli1, fname, 0,
5821 FILE_READ_ATTRIBUTES|DELETE_ACCESS,
5823 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5824 FILE_OPEN, 0, 0, &fnum1, NULL);
5825 if (!NT_STATUS_IS_OK(status)) {
5826 printf("[11] open of %s failed: %s\n", fname, nt_errstr(status));
5830 cli_close(cli1, fnum1);
5832 printf("eleventh delete on close test succeeded.\n");
5836 * like test 4 but with initial delete on close
5839 cli_setatr(cli1, fname, 0, 0);
5840 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5842 status = cli_ntcreate(cli1, fname, 0,
5843 FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
5844 FILE_ATTRIBUTE_NORMAL,
5845 FILE_SHARE_READ|FILE_SHARE_WRITE,
5847 FILE_DELETE_ON_CLOSE, 0, &fnum1, NULL);
5848 if (!NT_STATUS_IS_OK(status)) {
5849 printf("[12] open 1 of %s failed (%s)\n", fname, nt_errstr(status));
5853 status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
5854 FILE_ATTRIBUTE_NORMAL,
5855 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5856 FILE_OPEN, 0, 0, &fnum2, NULL);
5857 if (!NT_STATUS_IS_OK(status)) {
5858 printf("[12] open 2 of %s failed(%s).\n", fname, nt_errstr(status));
5862 status = cli_close(cli1, fnum2);
5863 if (!NT_STATUS_IS_OK(status)) {
5864 printf("[12] close 1 failed (%s)\n", nt_errstr(status));
5868 status = cli_nt_delete_on_close(cli1, fnum1, true);
5869 if (!NT_STATUS_IS_OK(status)) {
5870 printf("[12] setting delete_on_close failed (%s)\n", nt_errstr(status));
5874 /* This should fail - no more opens once delete on close set. */
5875 status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
5876 FILE_ATTRIBUTE_NORMAL,
5877 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5878 FILE_OPEN, 0, 0, &fnum2, NULL);
5879 if (NT_STATUS_IS_OK(status)) {
5880 printf("[12] open 3 of %s succeeded - should fail).\n", fname);
5884 status = cli_nt_delete_on_close(cli1, fnum1, false);
5885 if (!NT_STATUS_IS_OK(status)) {
5886 printf("[12] unsetting delete_on_close failed (%s)\n", nt_errstr(status));
5890 status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
5891 FILE_ATTRIBUTE_NORMAL,
5892 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5893 FILE_OPEN, 0, 0, &fnum2, NULL);
5894 if (!NT_STATUS_IS_OK(status)) {
5895 printf("[12] open 4 of %s failed (%s)\n", fname, nt_errstr(status));
5899 status = cli_close(cli1, fnum2);
5900 if (!NT_STATUS_IS_OK(status)) {
5901 printf("[12] close 2 failed (%s)\n", nt_errstr(status));
5905 status = cli_close(cli1, fnum1);
5906 if (!NT_STATUS_IS_OK(status)) {
5907 printf("[12] close 3 failed (%s)\n", nt_errstr(status));
5912 * setting delete on close on the handle does
5913 * not unset the initial delete on close...
5915 status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
5916 FILE_ATTRIBUTE_NORMAL,
5917 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5918 FILE_OPEN, 0, 0, &fnum2, NULL);
5919 if (NT_STATUS_IS_OK(status)) {
5920 printf("[12] open 5 of %s succeeded - should fail).\n", fname);
5922 } else if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
5923 printf("ntcreate returned %s, expected "
5924 "NT_STATUS_OBJECT_NAME_NOT_FOUND\n",
5929 printf("twelfth delete on close test succeeded.\n");
5932 printf("finished delete test\n");
5937 /* FIXME: This will crash if we aborted before cli2 got
5938 * initialized, because these functions don't handle
5939 * uninitialized connections. */
5941 if (fnum1 != (uint16_t)-1) cli_close(cli1, fnum1);
5942 if (fnum2 != (uint16_t)-1) cli_close(cli1, fnum2);
5943 cli_setatr(cli1, fname, 0, 0);
5944 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5946 if (cli1 && !torture_close_connection(cli1)) {
5949 if (cli2 && !torture_close_connection(cli2)) {
5955 struct delete_stream_state {
5959 static void delete_stream_unlinked(struct tevent_req *subreq);
5960 static void delete_stream_closed(struct tevent_req *subreq);
5962 static struct tevent_req *delete_stream_send(
5963 TALLOC_CTX *mem_ctx,
5964 struct tevent_context *ev,
5965 struct cli_state *cli,
5966 const char *base_fname,
5967 uint16_t stream_fnum)
5969 struct tevent_req *req = NULL, *subreq = NULL;
5970 struct delete_stream_state *state = NULL;
5972 req = tevent_req_create(
5973 mem_ctx, &state, struct delete_stream_state);
5978 subreq = cli_unlink_send(
5983 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5984 if (tevent_req_nomem(subreq, req)) {
5985 return tevent_req_post(req, ev);
5987 tevent_req_set_callback(subreq, delete_stream_unlinked, req);
5989 subreq = cli_close_send(state, ev, cli, stream_fnum, 0);
5990 if (tevent_req_nomem(subreq, req)) {
5991 return tevent_req_post(req, ev);
5993 tevent_req_set_callback(subreq, delete_stream_closed, req);
5998 static void delete_stream_unlinked(struct tevent_req *subreq)
6000 struct tevent_req *req = tevent_req_callback_data(
6001 subreq, struct tevent_req);
6002 struct delete_stream_state *state = tevent_req_data(
6003 req, struct delete_stream_state);
6006 status = cli_unlink_recv(subreq);
6007 TALLOC_FREE(subreq);
6008 if (!NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
6009 printf("cli_unlink returned %s\n",
6011 tevent_req_nterror(req, NT_STATUS_UNSUCCESSFUL);
6014 if (!state->closed) {
6015 /* close reply should have come in first */
6016 printf("Not closed\n");
6017 tevent_req_nterror(req, NT_STATUS_UNSUCCESSFUL);
6020 tevent_req_done(req);
6023 static void delete_stream_closed(struct tevent_req *subreq)
6025 struct tevent_req *req = tevent_req_callback_data(
6026 subreq, struct tevent_req);
6027 struct delete_stream_state *state = tevent_req_data(
6028 req, struct delete_stream_state);
6031 status = cli_close_recv(subreq);
6032 TALLOC_FREE(subreq);
6033 if (tevent_req_nterror(req, status)) {
6036 /* also waiting for the unlink to come back */
6037 state->closed = true;
6040 static NTSTATUS delete_stream_recv(struct tevent_req *req)
6042 return tevent_req_simple_recv_ntstatus(req);
6045 static bool run_delete_stream(int dummy)
6047 struct tevent_context *ev = NULL;
6048 struct tevent_req *req = NULL;
6049 struct cli_state *cli = NULL;
6050 const char fname[] = "delete_stream";
6051 const char fname_stream[] = "delete_stream:Zone.Identifier:$DATA";
6052 uint16_t fnum1, fnum2;
6056 printf("Starting stream delete test\n");
6058 ok = torture_open_connection(&cli, 0);
6063 cli_setatr(cli, fname, 0, 0);
6064 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6066 /* Create the file. */
6067 status = cli_ntcreate(
6071 READ_CONTROL_ACCESS,
6073 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6079 if (!NT_STATUS_IS_OK(status)) {
6081 "cli_ntcreate of %s failed (%s)\n",
6086 status = cli_close(cli, fnum1);
6087 if (!NT_STATUS_IS_OK(status)) {
6089 "cli_close of %s failed (%s)\n",
6095 /* Now create the stream. */
6096 status = cli_ntcreate(
6102 FILE_SHARE_READ|FILE_SHARE_WRITE,
6109 if (!NT_STATUS_IS_OK(status)) {
6111 "cli_ntcreate of %s failed (%s)\n",
6117 /* open it a second time */
6119 status = cli_ntcreate(
6125 FILE_SHARE_READ|FILE_SHARE_WRITE,
6132 if (!NT_STATUS_IS_OK(status)) {
6134 "2nd cli_ntcreate of %s failed (%s)\n",
6140 ev = samba_tevent_context_init(talloc_tos());
6142 d_fprintf(stderr, "samba_tevent_context_init failed\n");
6146 req = delete_stream_send(ev, ev, cli, fname, fnum1);
6148 d_fprintf(stderr, "delete_stream_send failed\n");
6152 ok = tevent_req_poll_ntstatus(req, ev, &status);
6155 "tevent_req_poll_ntstatus failed: %s\n",
6160 status = delete_stream_recv(req);
6162 if (!NT_STATUS_IS_OK(status)) {
6164 "delete_stream failed: %s\n",
6169 status = cli_close(cli, fnum2);
6170 if (!NT_STATUS_IS_OK(status)) {
6172 "close failed: %s\n",
6177 status = cli_unlink(
6178 cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6179 if (!NT_STATUS_IS_OK(status)) {
6181 "unlink failed: %s\n",
6190 Exercise delete on close semantics - use on the PRINT1 share in torture
6193 static bool run_delete_print_test(int dummy)
6195 struct cli_state *cli1 = NULL;
6196 const char *fname = "print_delete.file";
6197 uint16_t fnum1 = (uint16_t)-1;
6198 bool correct = false;
6199 const char *buf = "print file data\n";
6202 printf("starting print delete test\n");
6204 if (!torture_open_connection(&cli1, 0)) {
6208 smbXcli_conn_set_sockopt(cli1->conn, sockops);
6210 status = cli_ntcreate(cli1, fname, 0, GENERIC_ALL_ACCESS|DELETE_ACCESS,
6211 FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
6212 0, 0, &fnum1, NULL);
6213 if (!NT_STATUS_IS_OK(status)) {
6214 printf("open of %s failed (%s)\n",
6220 status = cli_writeall(cli1,
6223 (const uint8_t *)buf,
6225 strlen(buf), /* size */
6227 if (!NT_STATUS_IS_OK(status)) {
6228 printf("writing print file data failed (%s)\n",
6233 status = cli_nt_delete_on_close(cli1, fnum1, true);
6234 if (!NT_STATUS_IS_OK(status)) {
6235 printf("setting delete_on_close failed (%s)\n",
6240 status = cli_close(cli1, fnum1);
6241 if (!NT_STATUS_IS_OK(status)) {
6242 printf("close failed (%s)\n", nt_errstr(status));
6246 printf("finished print delete test\n");
6252 if (fnum1 != (uint16_t)-1) {
6253 cli_close(cli1, fnum1);
6256 if (cli1 && !torture_close_connection(cli1)) {
6262 static bool run_deletetest_ln(int dummy)
6264 struct cli_state *cli;
6265 const char *fname = "\\delete1";
6266 const char *fname_ln = "\\delete1_ln";
6270 bool correct = true;
6273 printf("starting deletetest-ln\n");
6275 if (!torture_open_connection(&cli, 0)) {
6279 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6280 cli_unlink(cli, fname_ln, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6282 smbXcli_conn_set_sockopt(cli->conn, sockops);
6284 /* Create the file. */
6285 status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
6286 if (!NT_STATUS_IS_OK(status)) {
6287 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
6291 status = cli_close(cli, fnum);
6292 if (!NT_STATUS_IS_OK(status)) {
6293 printf("close1 failed (%s)\n", nt_errstr(status));
6297 /* Now create a hardlink. */
6298 status = cli_hardlink(cli, fname, fname_ln);
6299 if (!NT_STATUS_IS_OK(status)) {
6300 printf("nt hardlink failed (%s)\n", nt_errstr(status));
6304 /* Open the original file. */
6305 status = cli_ntcreate(cli, fname, 0, FILE_READ_DATA,
6306 FILE_ATTRIBUTE_NORMAL,
6307 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6308 FILE_OPEN_IF, 0, 0, &fnum, NULL);
6309 if (!NT_STATUS_IS_OK(status)) {
6310 printf("ntcreate of %s failed (%s)\n", fname, nt_errstr(status));
6314 /* Unlink the hard link path. */
6315 status = cli_ntcreate(cli, fname_ln, 0, DELETE_ACCESS,
6316 FILE_ATTRIBUTE_NORMAL,
6317 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6318 FILE_OPEN_IF, 0, 0, &fnum1, NULL);
6319 if (!NT_STATUS_IS_OK(status)) {
6320 printf("ntcreate of %s failed (%s)\n", fname_ln, nt_errstr(status));
6323 status = cli_nt_delete_on_close(cli, fnum1, true);
6324 if (!NT_STATUS_IS_OK(status)) {
6325 d_printf("(%s) failed to set delete_on_close %s: %s\n",
6326 __location__, fname_ln, nt_errstr(status));
6330 status = cli_close(cli, fnum1);
6331 if (!NT_STATUS_IS_OK(status)) {
6332 printf("close %s failed (%s)\n",
6333 fname_ln, nt_errstr(status));
6337 status = cli_close(cli, fnum);
6338 if (!NT_STATUS_IS_OK(status)) {
6339 printf("close %s failed (%s)\n",
6340 fname, nt_errstr(status));
6344 /* Ensure the original file is still there. */
6345 status = cli_getatr(cli, fname, NULL, NULL, &t);
6346 if (!NT_STATUS_IS_OK(status)) {
6347 printf("%s getatr on file %s failed (%s)\n",
6354 /* Ensure the link path is gone. */
6355 status = cli_getatr(cli, fname_ln, NULL, NULL, &t);
6356 if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
6357 printf("%s, getatr for file %s returned wrong error code %s "
6358 "- should have been deleted\n",
6360 fname_ln, nt_errstr(status));
6364 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6365 cli_unlink(cli, fname_ln, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6367 if (!torture_close_connection(cli)) {
6371 printf("finished deletetest-ln\n");
6377 print out server properties
6379 static bool run_properties(int dummy)
6381 struct cli_state *cli;
6382 bool correct = True;
6384 printf("starting properties test\n");
6388 if (!torture_open_connection(&cli, 0)) {
6392 smbXcli_conn_set_sockopt(cli->conn, sockops);
6394 d_printf("Capabilities 0x%08x\n", smb1cli_conn_capabilities(cli->conn));
6396 if (!torture_close_connection(cli)) {
6405 /* FIRST_DESIRED_ACCESS 0xf019f */
6406 #define FIRST_DESIRED_ACCESS FILE_READ_DATA|FILE_WRITE_DATA|FILE_APPEND_DATA|\
6407 FILE_READ_EA| /* 0xf */ \
6408 FILE_WRITE_EA|FILE_READ_ATTRIBUTES| /* 0x90 */ \
6409 FILE_WRITE_ATTRIBUTES| /* 0x100 */ \
6410 DELETE_ACCESS|READ_CONTROL_ACCESS|\
6411 WRITE_DAC_ACCESS|WRITE_OWNER_ACCESS /* 0xf0000 */
6412 /* SECOND_DESIRED_ACCESS 0xe0080 */
6413 #define SECOND_DESIRED_ACCESS FILE_READ_ATTRIBUTES| /* 0x80 */ \
6414 READ_CONTROL_ACCESS|WRITE_DAC_ACCESS|\
6415 WRITE_OWNER_ACCESS /* 0xe0000 */
6418 #define THIRD_DESIRED_ACCESS FILE_READ_ATTRIBUTES| /* 0x80 */ \
6419 READ_CONTROL_ACCESS|WRITE_DAC_ACCESS|\
6421 WRITE_OWNER_ACCESS /* */
6425 Test ntcreate calls made by xcopy
6427 static bool run_xcopy(int dummy)
6429 static struct cli_state *cli1;
6430 const char *fname = "\\test.txt";
6431 bool correct = True;
6432 uint16_t fnum1, fnum2;
6435 printf("starting xcopy test\n");
6437 if (!torture_open_connection(&cli1, 0)) {
6441 status = cli_ntcreate(cli1, fname, 0, FIRST_DESIRED_ACCESS,
6442 FILE_ATTRIBUTE_ARCHIVE, FILE_SHARE_NONE,
6443 FILE_OVERWRITE_IF, 0x4044, 0, &fnum1, NULL);
6444 if (!NT_STATUS_IS_OK(status)) {
6445 printf("First open failed - %s\n", nt_errstr(status));
6449 status = cli_ntcreate(cli1, fname, 0, SECOND_DESIRED_ACCESS, 0,
6450 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6451 FILE_OPEN, 0x200000, 0, &fnum2, NULL);
6452 if (!NT_STATUS_IS_OK(status)) {
6453 printf("second open failed - %s\n", nt_errstr(status));
6457 if (!torture_close_connection(cli1)) {
6465 Test rename on files open with share delete and no share delete.
6467 static bool run_rename(int dummy)
6469 static struct cli_state *cli1;
6470 const char *fname = "\\test.txt";
6471 const char *fname1 = "\\test1.txt";
6472 bool correct = True;
6477 printf("starting rename test\n");
6479 if (!torture_open_connection(&cli1, 0)) {
6483 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6484 cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6486 status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
6487 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ,
6488 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
6489 if (!NT_STATUS_IS_OK(status)) {
6490 printf("First open failed - %s\n", nt_errstr(status));
6494 status = cli_rename(cli1, fname, fname1, false);
6495 if (!NT_STATUS_IS_OK(status)) {
6496 printf("First rename failed (SHARE_READ) (this is correct) - %s\n", nt_errstr(status));
6498 printf("First rename succeeded (SHARE_READ) - this should have failed !\n");
6502 status = cli_close(cli1, fnum1);
6503 if (!NT_STATUS_IS_OK(status)) {
6504 printf("close - 1 failed (%s)\n", nt_errstr(status));
6508 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6509 cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6510 status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS, FILE_ATTRIBUTE_NORMAL,
6512 FILE_SHARE_DELETE|FILE_SHARE_NONE,
6514 FILE_SHARE_DELETE|FILE_SHARE_READ,
6516 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
6517 if (!NT_STATUS_IS_OK(status)) {
6518 printf("Second open failed - %s\n", nt_errstr(status));
6522 status = cli_rename(cli1, fname, fname1, false);
6523 if (!NT_STATUS_IS_OK(status)) {
6524 printf("Second rename failed (SHARE_DELETE | SHARE_READ) - this should have succeeded - %s\n", nt_errstr(status));
6527 printf("Second rename succeeded (SHARE_DELETE | SHARE_READ)\n");
6530 status = cli_close(cli1, fnum1);
6531 if (!NT_STATUS_IS_OK(status)) {
6532 printf("close - 2 failed (%s)\n", nt_errstr(status));
6536 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6537 cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6539 status = cli_ntcreate(cli1, fname, 0, READ_CONTROL_ACCESS,
6540 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
6541 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
6542 if (!NT_STATUS_IS_OK(status)) {
6543 printf("Third open failed - %s\n", nt_errstr(status));
6548 status = cli_rename(cli1, fname, fname1, false);
6549 if (!NT_STATUS_IS_OK(status)) {
6550 printf("Third rename failed (SHARE_NONE) - this should have succeeded - %s\n", nt_errstr(status));
6553 printf("Third rename succeeded (SHARE_NONE)\n");
6556 status = cli_close(cli1, fnum1);
6557 if (!NT_STATUS_IS_OK(status)) {
6558 printf("close - 3 failed (%s)\n", nt_errstr(status));
6562 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6563 cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6567 status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
6568 FILE_ATTRIBUTE_NORMAL,
6569 FILE_SHARE_READ | FILE_SHARE_WRITE,
6570 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
6571 if (!NT_STATUS_IS_OK(status)) {
6572 printf("Fourth open failed - %s\n", nt_errstr(status));
6576 status = cli_rename(cli1, fname, fname1, false);
6577 if (!NT_STATUS_IS_OK(status)) {
6578 printf("Fourth rename failed (SHARE_READ | SHARE_WRITE) (this is correct) - %s\n", nt_errstr(status));
6580 printf("Fourth rename succeeded (SHARE_READ | SHARE_WRITE) - this should have failed !\n");
6584 status = cli_close(cli1, fnum1);
6585 if (!NT_STATUS_IS_OK(status)) {
6586 printf("close - 4 failed (%s)\n", nt_errstr(status));
6590 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6591 cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6595 status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
6596 FILE_ATTRIBUTE_NORMAL,
6597 FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
6598 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
6599 if (!NT_STATUS_IS_OK(status)) {
6600 printf("Fifth open failed - %s\n", nt_errstr(status));
6604 status = cli_rename(cli1, fname, fname1, false);
6605 if (!NT_STATUS_IS_OK(status)) {
6606 printf("Fifth rename failed (SHARE_READ | SHARE_WRITE | SHARE_DELETE) - this should have succeeded - %s ! \n", nt_errstr(status));
6609 printf("Fifth rename succeeded (SHARE_READ | SHARE_WRITE | SHARE_DELETE) (this is correct) - %s\n", nt_errstr(status));
6613 status = cli_close(cli1, fnum1);
6614 if (!NT_STATUS_IS_OK(status)) {
6615 printf("close - 5 failed (%s)\n", nt_errstr(status));
6619 /* Check that the renamed file has FILE_ATTRIBUTE_ARCHIVE. */
6620 status = cli_getatr(cli1, fname1, &attr, NULL, NULL);
6621 if (!NT_STATUS_IS_OK(status)) {
6622 printf("getatr on file %s failed - %s ! \n",
6623 fname1, nt_errstr(status));
6626 if (attr != FILE_ATTRIBUTE_ARCHIVE) {
6627 printf("Renamed file %s has wrong attr 0x%x "
6628 "(should be 0x%x)\n",
6631 (unsigned int)FILE_ATTRIBUTE_ARCHIVE);
6634 printf("Renamed file %s has archive bit set\n", fname1);
6638 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6639 cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6641 if (!torture_close_connection(cli1)) {
6649 Test rename into a directory with an ACL denying it.
6651 static bool run_rename_access(int dummy)
6653 static struct cli_state *cli = NULL;
6654 static struct cli_state *posix_cli = NULL;
6655 const char *src = "test.txt";
6656 const char *dname = "dir";
6657 const char *dst = "dir\\test.txt";
6658 const char *dsrc = "test.dir";
6659 const char *ddst = "dir\\test.dir";
6660 uint16_t fnum = (uint16_t)-1;
6661 struct security_descriptor *sd = NULL;
6662 struct security_descriptor *newsd = NULL;
6664 TALLOC_CTX *frame = NULL;
6666 frame = talloc_stackframe();
6667 printf("starting rename access test\n");
6669 /* Windows connection. */
6670 if (!torture_open_connection(&cli, 0)) {
6674 smbXcli_conn_set_sockopt(cli->conn, sockops);
6676 /* Posix connection. */
6677 if (!torture_open_connection(&posix_cli, 0)) {
6681 smbXcli_conn_set_sockopt(posix_cli->conn, sockops);
6683 status = torture_setup_unix_extensions(posix_cli);
6684 if (!NT_STATUS_IS_OK(status)) {
6688 /* Start with a clean slate. */
6689 cli_unlink(cli, src, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6690 cli_unlink(cli, dst, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6691 cli_rmdir(cli, dsrc);
6692 cli_rmdir(cli, ddst);
6693 cli_rmdir(cli, dname);
6696 * Setup the destination directory with a DENY ACE to
6697 * prevent new files within it.
6699 status = cli_ntcreate(cli,
6702 FILE_READ_ATTRIBUTES|READ_CONTROL_ACCESS|
6703 WRITE_DAC_ACCESS|FILE_READ_DATA|
6705 FILE_ATTRIBUTE_DIRECTORY,
6706 FILE_SHARE_READ|FILE_SHARE_WRITE,
6708 FILE_DIRECTORY_FILE,
6712 if (!NT_STATUS_IS_OK(status)) {
6713 printf("Create of %s - %s\n", dname, nt_errstr(status));
6717 status = cli_query_secdesc(cli,
6721 if (!NT_STATUS_IS_OK(status)) {
6722 printf("cli_query_secdesc failed for %s (%s)\n",
6723 dname, nt_errstr(status));
6727 newsd = security_descriptor_dacl_create(frame,
6732 SEC_ACE_TYPE_ACCESS_DENIED,
6733 SEC_DIR_ADD_FILE|SEC_DIR_ADD_SUBDIR,
6736 if (newsd == NULL) {
6739 sd->dacl = security_acl_concatenate(frame,
6742 if (sd->dacl == NULL) {
6745 status = cli_set_secdesc(cli, fnum, sd);
6746 if (!NT_STATUS_IS_OK(status)) {
6747 printf("cli_set_secdesc failed for %s (%s)\n",
6748 dname, nt_errstr(status));
6751 status = cli_close(cli, fnum);
6752 if (!NT_STATUS_IS_OK(status)) {
6753 printf("close failed for %s (%s)\n",
6754 dname, nt_errstr(status));
6757 /* Now go around the back and chmod to 777 via POSIX. */
6758 status = cli_posix_chmod(posix_cli, dname, 0777);
6759 if (!NT_STATUS_IS_OK(status)) {
6760 printf("cli_posix_chmod failed for %s (%s)\n",
6761 dname, nt_errstr(status));
6765 /* Check we can't create a file within dname via Windows. */
6766 status = cli_openx(cli, dst, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
6767 if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
6768 cli_close(posix_cli, fnum);
6769 printf("Create of %s should be ACCESS denied, was %s\n",
6770 dst, nt_errstr(status));
6774 /* Make the sample file/directory. */
6775 status = cli_openx(cli, src, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
6776 if (!NT_STATUS_IS_OK(status)) {
6777 printf("open of %s failed (%s)\n", src, nt_errstr(status));
6780 status = cli_close(cli, fnum);
6781 if (!NT_STATUS_IS_OK(status)) {
6782 printf("cli_close failed (%s)\n", nt_errstr(status));
6786 status = cli_mkdir(cli, dsrc);
6787 if (!NT_STATUS_IS_OK(status)) {
6788 printf("cli_mkdir of %s failed (%s)\n",
6789 dsrc, nt_errstr(status));
6794 * OK - renames of the new file and directory into the
6795 * dst directory should fail.
6798 status = cli_rename(cli, src, dst, false);
6799 if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
6800 printf("rename of %s -> %s should be ACCESS denied, was %s\n",
6801 src, dst, nt_errstr(status));
6804 status = cli_rename(cli, dsrc, ddst, false);
6805 if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
6806 printf("rename of %s -> %s should be ACCESS denied, was %s\n",
6807 src, dst, nt_errstr(status));
6817 torture_close_connection(posix_cli);
6821 if (fnum != (uint16_t)-1) {
6822 cli_close(cli, fnum);
6824 cli_unlink(cli, src,
6825 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6826 cli_unlink(cli, dst,
6827 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6828 cli_rmdir(cli, dsrc);
6829 cli_rmdir(cli, ddst);
6830 cli_rmdir(cli, dname);
6832 torture_close_connection(cli);
6840 Test owner rights ACE.
6842 static bool run_owner_rights(int dummy)
6844 static struct cli_state *cli = NULL;
6845 const char *fname = "owner_rights.txt";
6846 uint16_t fnum = (uint16_t)-1;
6847 struct security_descriptor *sd = NULL;
6848 struct security_descriptor *newsd = NULL;
6850 TALLOC_CTX *frame = NULL;
6852 frame = talloc_stackframe();
6853 printf("starting owner rights test\n");
6855 /* Windows connection. */
6856 if (!torture_open_connection(&cli, 0)) {
6860 smbXcli_conn_set_sockopt(cli->conn, sockops);
6862 /* Start with a clean slate. */
6863 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6865 /* Create the test file. */
6866 /* Now try and open for read and write-dac. */
6867 status = cli_ntcreate(cli,
6871 FILE_ATTRIBUTE_NORMAL,
6872 FILE_SHARE_READ|FILE_SHARE_WRITE|
6879 if (!NT_STATUS_IS_OK(status)) {
6880 printf("Create of %s - %s\n", fname, nt_errstr(status));
6884 /* Get the original SD. */
6885 status = cli_query_secdesc(cli,
6889 if (!NT_STATUS_IS_OK(status)) {
6890 printf("cli_query_secdesc failed for %s (%s)\n",
6891 fname, nt_errstr(status));
6896 * Add an "owner-rights" ACE denying WRITE_DATA,
6897 * and an "owner-rights" ACE allowing READ_DATA.
6900 newsd = security_descriptor_dacl_create(frame,
6905 SEC_ACE_TYPE_ACCESS_DENIED,
6909 SEC_ACE_TYPE_ACCESS_ALLOWED,
6913 if (newsd == NULL) {
6916 sd->dacl = security_acl_concatenate(frame,
6919 if (sd->dacl == NULL) {
6922 status = cli_set_secdesc(cli, fnum, sd);
6923 if (!NT_STATUS_IS_OK(status)) {
6924 printf("cli_set_secdesc failed for %s (%s)\n",
6925 fname, nt_errstr(status));
6928 status = cli_close(cli, fnum);
6929 if (!NT_STATUS_IS_OK(status)) {
6930 printf("close failed for %s (%s)\n",
6931 fname, nt_errstr(status));
6934 fnum = (uint16_t)-1;
6936 /* Try and open for FILE_WRITE_DATA */
6937 status = cli_ntcreate(cli,
6941 FILE_ATTRIBUTE_NORMAL,
6942 FILE_SHARE_READ|FILE_SHARE_WRITE|
6949 if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
6950 printf("Open of %s - %s\n", fname, nt_errstr(status));
6954 /* Now try and open for FILE_READ_DATA */
6955 status = cli_ntcreate(cli,
6959 FILE_ATTRIBUTE_NORMAL,
6960 FILE_SHARE_READ|FILE_SHARE_WRITE|
6967 if (!NT_STATUS_IS_OK(status)) {
6968 printf("Open of %s - %s\n", fname, nt_errstr(status));
6972 status = cli_close(cli, fnum);
6973 if (!NT_STATUS_IS_OK(status)) {
6974 printf("close failed for %s (%s)\n",
6975 fname, nt_errstr(status));
6979 /* Restore clean slate. */
6981 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6983 /* Create the test file. */
6984 status = cli_ntcreate(cli,
6988 FILE_ATTRIBUTE_NORMAL,
6989 FILE_SHARE_READ|FILE_SHARE_WRITE|
6996 if (!NT_STATUS_IS_OK(status)) {
6997 printf("Create of %s - %s\n", fname, nt_errstr(status));
7001 /* Get the original SD. */
7002 status = cli_query_secdesc(cli,
7006 if (!NT_STATUS_IS_OK(status)) {
7007 printf("cli_query_secdesc failed for %s (%s)\n",
7008 fname, nt_errstr(status));
7013 * Add an "owner-rights ACE denying WRITE_DATA,
7014 * and an "owner-rights ACE allowing READ_DATA|WRITE_DATA.
7017 newsd = security_descriptor_dacl_create(frame,
7022 SEC_ACE_TYPE_ACCESS_DENIED,
7026 SEC_ACE_TYPE_ACCESS_ALLOWED,
7027 FILE_READ_DATA|FILE_WRITE_DATA,
7030 if (newsd == NULL) {
7033 sd->dacl = security_acl_concatenate(frame,
7036 if (sd->dacl == NULL) {
7039 status = cli_set_secdesc(cli, fnum, sd);
7040 if (!NT_STATUS_IS_OK(status)) {
7041 printf("cli_set_secdesc failed for %s (%s)\n",
7042 fname, nt_errstr(status));
7045 status = cli_close(cli, fnum);
7046 if (!NT_STATUS_IS_OK(status)) {
7047 printf("close failed for %s (%s)\n",
7048 fname, nt_errstr(status));
7051 fnum = (uint16_t)-1;
7053 /* Try and open for FILE_WRITE_DATA */
7054 status = cli_ntcreate(cli,
7058 FILE_ATTRIBUTE_NORMAL,
7059 FILE_SHARE_READ|FILE_SHARE_WRITE|
7066 if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
7067 printf("Open of %s - %s\n", fname, nt_errstr(status));
7071 /* Now try and open for FILE_READ_DATA */
7072 status = cli_ntcreate(cli,
7076 FILE_ATTRIBUTE_NORMAL,
7077 FILE_SHARE_READ|FILE_SHARE_WRITE|
7084 if (!NT_STATUS_IS_OK(status)) {
7085 printf("Open of %s - %s\n", fname, nt_errstr(status));
7089 status = cli_close(cli, fnum);
7090 if (!NT_STATUS_IS_OK(status)) {
7091 printf("close failed for %s (%s)\n",
7092 fname, nt_errstr(status));
7096 /* Restore clean slate. */
7098 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7101 /* Create the test file. */
7102 status = cli_ntcreate(cli,
7106 FILE_ATTRIBUTE_NORMAL,
7107 FILE_SHARE_READ|FILE_SHARE_WRITE|
7114 if (!NT_STATUS_IS_OK(status)) {
7115 printf("Create of %s - %s\n", fname, nt_errstr(status));
7119 /* Get the original SD. */
7120 status = cli_query_secdesc(cli,
7124 if (!NT_STATUS_IS_OK(status)) {
7125 printf("cli_query_secdesc failed for %s (%s)\n",
7126 fname, nt_errstr(status));
7131 * Add an "authenticated users" ACE allowing READ_DATA,
7132 * add an "owner-rights" denying READ_DATA,
7133 * and an "authenticated users" ACE allowing WRITE_DATA.
7136 newsd = security_descriptor_dacl_create(frame,
7140 SID_NT_AUTHENTICATED_USERS,
7141 SEC_ACE_TYPE_ACCESS_ALLOWED,
7145 SEC_ACE_TYPE_ACCESS_DENIED,
7148 SID_NT_AUTHENTICATED_USERS,
7149 SEC_ACE_TYPE_ACCESS_ALLOWED,
7153 if (newsd == NULL) {
7154 printf("newsd == NULL\n");
7157 sd->dacl = security_acl_concatenate(frame,
7160 if (sd->dacl == NULL) {
7161 printf("sd->dacl == NULL\n");
7164 status = cli_set_secdesc(cli, fnum, sd);
7165 if (!NT_STATUS_IS_OK(status)) {
7166 printf("cli_set_secdesc failed for %s (%s)\n",
7167 fname, nt_errstr(status));
7170 status = cli_close(cli, fnum);
7171 if (!NT_STATUS_IS_OK(status)) {
7172 printf("close failed for %s (%s)\n",
7173 fname, nt_errstr(status));
7176 fnum = (uint16_t)-1;
7178 /* Now try and open for FILE_READ_DATA|FILE_WRITE_DATA */
7179 status = cli_ntcreate(cli,
7182 FILE_READ_DATA|FILE_WRITE_DATA,
7183 FILE_ATTRIBUTE_NORMAL,
7184 FILE_SHARE_READ|FILE_SHARE_WRITE|
7191 if (!NT_STATUS_IS_OK(status)) {
7192 printf("Open of %s - %s\n", fname, nt_errstr(status));
7196 status = cli_close(cli, fnum);
7197 if (!NT_STATUS_IS_OK(status)) {
7198 printf("close failed for %s (%s)\n",
7199 fname, nt_errstr(status));
7203 cli_unlink(cli, fname,
7204 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7212 if (fnum != (uint16_t)-1) {
7213 cli_close(cli, fnum);
7215 cli_unlink(cli, fname,
7216 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7217 torture_close_connection(cli);
7225 * Test SMB1-specific open with SEC_FLAG_SYSTEM_SECURITY.
7226 * Note this test only works with a user with SeSecurityPrivilege set.
7228 * NB. This is also tested in samba3.base.createx_access
7229 * but this makes it very explicit what we're looking for.
7231 static bool run_smb1_system_security(int dummy)
7233 static struct cli_state *cli = NULL;
7234 const char *fname = "system_security.txt";
7235 uint16_t fnum = (uint16_t)-1;
7237 TALLOC_CTX *frame = NULL;
7239 frame = talloc_stackframe();
7240 printf("starting smb1 system security test\n");
7242 /* SMB1 connection - torture_open_connection() forces this. */
7243 if (!torture_open_connection(&cli, 0)) {
7247 smbXcli_conn_set_sockopt(cli->conn, sockops);
7249 /* Start with a clean slate. */
7250 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7252 /* Create the test file. */
7253 status = cli_ntcreate(cli,
7257 FILE_ATTRIBUTE_NORMAL,
7258 FILE_SHARE_READ|FILE_SHARE_WRITE|
7265 if (!NT_STATUS_IS_OK(status)) {
7266 printf("Create of %s - %s\n", fname, nt_errstr(status));
7270 status = cli_close(cli, fnum);
7272 /* Open with SEC_FLAG_SYSTEM_SECURITY only. */
7274 * On SMB1 this succeeds - SMB2 it fails,
7275 * see the SMB2-SACL test.
7277 status = cli_ntcreate(cli,
7280 SEC_FLAG_SYSTEM_SECURITY,
7281 FILE_ATTRIBUTE_NORMAL,
7282 FILE_SHARE_READ|FILE_SHARE_WRITE|
7289 if (!NT_STATUS_IS_OK(status)) {
7290 printf("Open of %s - %s\n", fname, nt_errstr(status));
7294 status = cli_close(cli, fnum);
7296 cli_unlink(cli, fname,
7297 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7299 torture_close_connection(cli);
7306 if (fnum != (uint16_t)-1) {
7307 cli_close(cli, fnum);
7309 cli_unlink(cli, fname,
7310 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7311 torture_close_connection(cli);
7318 static bool run_pipe_number(int dummy)
7320 struct cli_state *cli1;
7321 const char *pipe_name = "\\SPOOLSS";
7326 printf("starting pipenumber test\n");
7327 if (!torture_open_connection(&cli1, 0)) {
7331 smbXcli_conn_set_sockopt(cli1->conn, sockops);
7333 status = cli_ntcreate(cli1, pipe_name, 0, FILE_READ_DATA,
7334 FILE_ATTRIBUTE_NORMAL,
7335 FILE_SHARE_READ|FILE_SHARE_WRITE,
7336 FILE_OPEN_IF, 0, 0, &fnum, NULL);
7337 if (!NT_STATUS_IS_OK(status)) {
7338 printf("Open of pipe %s failed with error (%s)\n", pipe_name, nt_errstr(status));
7342 printf("\r%6d", num_pipes);
7345 printf("pipe_number test - we can open %d %s pipes.\n", num_pipes, pipe_name );
7346 torture_close_connection(cli1);
7351 Test open mode returns on read-only files.
7353 static bool run_opentest(int dummy)
7355 static struct cli_state *cli1;
7356 static struct cli_state *cli2;
7357 const char *fname = "\\readonly.file";
7358 uint16_t fnum1, fnum2;
7361 bool correct = True;
7365 printf("starting open test\n");
7367 if (!torture_open_connection(&cli1, 0)) {
7371 cli_setatr(cli1, fname, 0, 0);
7372 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7374 smbXcli_conn_set_sockopt(cli1->conn, sockops);
7376 status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
7377 if (!NT_STATUS_IS_OK(status)) {
7378 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
7382 status = cli_close(cli1, fnum1);
7383 if (!NT_STATUS_IS_OK(status)) {
7384 printf("close2 failed (%s)\n", nt_errstr(status));
7388 status = cli_setatr(cli1, fname, FILE_ATTRIBUTE_READONLY, 0);
7389 if (!NT_STATUS_IS_OK(status)) {
7390 printf("cli_setatr failed (%s)\n", nt_errstr(status));
7394 status = cli_openx(cli1, fname, O_RDONLY, DENY_WRITE, &fnum1);
7395 if (!NT_STATUS_IS_OK(status)) {
7396 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
7400 /* This will fail - but the error should be ERRnoaccess, not ERRbadshare. */
7401 status = cli_openx(cli1, fname, O_RDWR, DENY_ALL, &fnum2);
7403 if (check_error(__LINE__, status, ERRDOS, ERRnoaccess,
7404 NT_STATUS_ACCESS_DENIED)) {
7405 printf("correct error code ERRDOS/ERRnoaccess returned\n");
7408 printf("finished open test 1\n");
7410 cli_close(cli1, fnum1);
7412 /* Now try not readonly and ensure ERRbadshare is returned. */
7414 cli_setatr(cli1, fname, 0, 0);
7416 status = cli_openx(cli1, fname, O_RDONLY, DENY_WRITE, &fnum1);
7417 if (!NT_STATUS_IS_OK(status)) {
7418 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
7422 /* This will fail - but the error should be ERRshare. */
7423 status = cli_openx(cli1, fname, O_RDWR, DENY_ALL, &fnum2);
7425 if (check_error(__LINE__, status, ERRDOS, ERRbadshare,
7426 NT_STATUS_SHARING_VIOLATION)) {
7427 printf("correct error code ERRDOS/ERRbadshare returned\n");
7430 status = cli_close(cli1, fnum1);
7431 if (!NT_STATUS_IS_OK(status)) {
7432 printf("close2 failed (%s)\n", nt_errstr(status));
7436 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7438 printf("finished open test 2\n");
7440 /* Test truncate open disposition on file opened for read. */
7441 status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
7442 if (!NT_STATUS_IS_OK(status)) {
7443 printf("(3) open (1) of %s failed (%s)\n", fname, nt_errstr(status));
7447 /* write 20 bytes. */
7449 memset(buf, '\0', 20);
7451 status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 0, 20, NULL);
7452 if (!NT_STATUS_IS_OK(status)) {
7453 printf("write failed (%s)\n", nt_errstr(status));
7457 status = cli_close(cli1, fnum1);
7458 if (!NT_STATUS_IS_OK(status)) {
7459 printf("(3) close1 failed (%s)\n", nt_errstr(status));
7463 /* Ensure size == 20. */
7464 status = cli_getatr(cli1, fname, NULL, &fsize, NULL);
7465 if (!NT_STATUS_IS_OK(status)) {
7466 printf("(3) getatr failed (%s)\n", nt_errstr(status));
7471 printf("(3) file size != 20\n");
7475 /* Now test if we can truncate a file opened for readonly. */
7476 status = cli_openx(cli1, fname, O_RDONLY|O_TRUNC, DENY_NONE, &fnum1);
7477 if (!NT_STATUS_IS_OK(status)) {
7478 printf("(3) open (2) of %s failed (%s)\n", fname, nt_errstr(status));
7482 status = cli_close(cli1, fnum1);
7483 if (!NT_STATUS_IS_OK(status)) {
7484 printf("close2 failed (%s)\n", nt_errstr(status));
7488 /* Ensure size == 0. */
7489 status = cli_getatr(cli1, fname, NULL, &fsize, NULL);
7490 if (!NT_STATUS_IS_OK(status)) {
7491 printf("(3) getatr failed (%s)\n", nt_errstr(status));
7496 printf("(3) file size != 0\n");
7499 printf("finished open test 3\n");
7501 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7503 printf("Do ctemp tests\n");
7504 status = cli_ctemp(cli1, talloc_tos(), "\\", &fnum1, &tmp_path);
7505 if (!NT_STATUS_IS_OK(status)) {
7506 printf("ctemp failed (%s)\n", nt_errstr(status));
7510 printf("ctemp gave path %s\n", tmp_path);
7511 status = cli_close(cli1, fnum1);
7512 if (!NT_STATUS_IS_OK(status)) {
7513 printf("close of temp failed (%s)\n", nt_errstr(status));
7516 status = cli_unlink(cli1, tmp_path, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7517 if (!NT_STATUS_IS_OK(status)) {
7518 printf("unlink of temp failed (%s)\n", nt_errstr(status));
7521 /* Test the non-io opens... */
7523 if (!torture_open_connection(&cli2, 1)) {
7527 cli_setatr(cli2, fname, 0, 0);
7528 cli_unlink(cli2, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7530 smbXcli_conn_set_sockopt(cli2->conn, sockops);
7532 printf("TEST #1 testing 2 non-io opens (no delete)\n");
7533 status = cli_ntcreate(cli1, fname, 0, FILE_READ_ATTRIBUTES,
7534 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7535 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
7536 if (!NT_STATUS_IS_OK(status)) {
7537 printf("TEST #1 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
7541 status = cli_ntcreate(cli2, fname, 0, FILE_READ_ATTRIBUTES,
7542 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7543 FILE_OPEN_IF, 0, 0, &fnum2, NULL);
7544 if (!NT_STATUS_IS_OK(status)) {
7545 printf("TEST #1 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
7549 status = cli_close(cli1, fnum1);
7550 if (!NT_STATUS_IS_OK(status)) {
7551 printf("TEST #1 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
7555 status = cli_close(cli2, fnum2);
7556 if (!NT_STATUS_IS_OK(status)) {
7557 printf("TEST #1 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
7561 printf("non-io open test #1 passed.\n");
7563 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7565 printf("TEST #2 testing 2 non-io opens (first with delete)\n");
7567 status = cli_ntcreate(cli1, fname, 0,
7568 DELETE_ACCESS|FILE_READ_ATTRIBUTES,
7569 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7570 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
7571 if (!NT_STATUS_IS_OK(status)) {
7572 printf("TEST #2 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
7576 status = cli_ntcreate(cli2, fname, 0, FILE_READ_ATTRIBUTES,
7577 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7578 FILE_OPEN_IF, 0, 0, &fnum2, NULL);
7579 if (!NT_STATUS_IS_OK(status)) {
7580 printf("TEST #2 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
7584 status = cli_close(cli1, fnum1);
7585 if (!NT_STATUS_IS_OK(status)) {
7586 printf("TEST #2 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
7590 status = cli_close(cli2, fnum2);
7591 if (!NT_STATUS_IS_OK(status)) {
7592 printf("TEST #2 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
7596 printf("non-io open test #2 passed.\n");
7598 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7600 printf("TEST #3 testing 2 non-io opens (second with delete)\n");
7602 status = cli_ntcreate(cli1, fname, 0, FILE_READ_ATTRIBUTES,
7603 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7604 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
7605 if (!NT_STATUS_IS_OK(status)) {
7606 printf("TEST #3 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
7610 status = cli_ntcreate(cli2, fname, 0,
7611 DELETE_ACCESS|FILE_READ_ATTRIBUTES,
7612 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7613 FILE_OPEN_IF, 0, 0, &fnum2, NULL);
7614 if (!NT_STATUS_IS_OK(status)) {
7615 printf("TEST #3 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
7619 status = cli_close(cli1, fnum1);
7620 if (!NT_STATUS_IS_OK(status)) {
7621 printf("TEST #3 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
7625 status = cli_close(cli2, fnum2);
7626 if (!NT_STATUS_IS_OK(status)) {
7627 printf("TEST #3 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
7631 printf("non-io open test #3 passed.\n");
7633 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7635 printf("TEST #4 testing 2 non-io opens (both with delete)\n");
7637 status = cli_ntcreate(cli1, fname, 0,
7638 DELETE_ACCESS|FILE_READ_ATTRIBUTES,
7639 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7640 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
7641 if (!NT_STATUS_IS_OK(status)) {
7642 printf("TEST #4 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
7646 status = cli_ntcreate(cli2, fname, 0,
7647 DELETE_ACCESS|FILE_READ_ATTRIBUTES,
7648 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7649 FILE_OPEN_IF, 0, 0, &fnum2, NULL);
7650 if (NT_STATUS_IS_OK(status)) {
7651 printf("TEST #4 open 2 of %s SUCCEEDED - should have failed (%s)\n", fname, nt_errstr(status));
7655 printf("TEST #4 open 2 of %s gave %s (correct error should be %s)\n", fname, nt_errstr(status), "sharing violation");
7657 status = cli_close(cli1, fnum1);
7658 if (!NT_STATUS_IS_OK(status)) {
7659 printf("TEST #4 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
7663 printf("non-io open test #4 passed.\n");
7665 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7667 printf("TEST #5 testing 2 non-io opens (both with delete - both with file share delete)\n");
7669 status = cli_ntcreate(cli1, fname, 0,
7670 DELETE_ACCESS|FILE_READ_ATTRIBUTES,
7671 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_DELETE,
7672 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
7673 if (!NT_STATUS_IS_OK(status)) {
7674 printf("TEST #5 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
7678 status = cli_ntcreate(cli2, fname, 0,
7679 DELETE_ACCESS|FILE_READ_ATTRIBUTES,
7680 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_DELETE,
7681 FILE_OPEN_IF, 0, 0, &fnum2, NULL);
7682 if (!NT_STATUS_IS_OK(status)) {
7683 printf("TEST #5 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
7687 status = cli_close(cli1, fnum1);
7688 if (!NT_STATUS_IS_OK(status)) {
7689 printf("TEST #5 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
7693 status = cli_close(cli2, fnum2);
7694 if (!NT_STATUS_IS_OK(status)) {
7695 printf("TEST #5 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
7699 printf("non-io open test #5 passed.\n");
7701 printf("TEST #6 testing 1 non-io open, one io open\n");
7703 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7705 status = cli_ntcreate(cli1, fname, 0, FILE_READ_DATA,
7706 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7707 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
7708 if (!NT_STATUS_IS_OK(status)) {
7709 printf("TEST #6 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
7713 status = cli_ntcreate(cli2, fname, 0, FILE_READ_ATTRIBUTES,
7714 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ,
7715 FILE_OPEN_IF, 0, 0, &fnum2, NULL);
7716 if (!NT_STATUS_IS_OK(status)) {
7717 printf("TEST #6 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
7721 status = cli_close(cli1, fnum1);
7722 if (!NT_STATUS_IS_OK(status)) {
7723 printf("TEST #6 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
7727 status = cli_close(cli2, fnum2);
7728 if (!NT_STATUS_IS_OK(status)) {
7729 printf("TEST #6 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
7733 printf("non-io open test #6 passed.\n");
7735 printf("TEST #7 testing 1 non-io open, one io open with delete\n");
7737 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7739 status = cli_ntcreate(cli1, fname, 0, FILE_READ_DATA,
7740 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7741 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
7742 if (!NT_STATUS_IS_OK(status)) {
7743 printf("TEST #7 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
7747 status = cli_ntcreate(cli2, fname, 0,
7748 DELETE_ACCESS|FILE_READ_ATTRIBUTES,
7749 FILE_ATTRIBUTE_NORMAL,
7750 FILE_SHARE_READ|FILE_SHARE_DELETE,
7751 FILE_OPEN_IF, 0, 0, &fnum2, NULL);
7752 if (NT_STATUS_IS_OK(status)) {
7753 printf("TEST #7 open 2 of %s SUCCEEDED - should have failed (%s)\n", fname, nt_errstr(status));
7757 printf("TEST #7 open 2 of %s gave %s (correct error should be %s)\n", fname, nt_errstr(status), "sharing violation");
7759 status = cli_close(cli1, fnum1);
7760 if (!NT_STATUS_IS_OK(status)) {
7761 printf("TEST #7 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
7765 printf("non-io open test #7 passed.\n");
7767 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7769 printf("TEST #8 testing open without WRITE_ATTRIBUTES, updating close write time.\n");
7770 status = cli_ntcreate(cli1, fname, 0, FILE_WRITE_DATA, FILE_ATTRIBUTE_NORMAL,
7771 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
7772 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
7773 if (!NT_STATUS_IS_OK(status)) {
7774 printf("TEST #8 open of %s failed (%s)\n", fname, nt_errstr(status));
7779 /* Write to ensure we have to update the file time. */
7780 status = cli_writeall(cli1, fnum1, 0, (const uint8_t *)"TEST DATA\n", 0, 10,
7782 if (!NT_STATUS_IS_OK(status)) {
7783 printf("TEST #8 cli_write failed: %s\n", nt_errstr(status));
7788 status = cli_close(cli1, fnum1);
7789 if (!NT_STATUS_IS_OK(status)) {
7790 printf("TEST #8 close of %s failed (%s)\n", fname, nt_errstr(status));
7796 if (!torture_close_connection(cli1)) {
7799 if (!torture_close_connection(cli2)) {
7806 NTSTATUS torture_setup_unix_extensions(struct cli_state *cli)
7808 uint16_t major, minor;
7809 uint32_t caplow, caphigh;
7812 if (!SERVER_HAS_UNIX_CIFS(cli)) {
7813 printf("Server doesn't support UNIX CIFS extensions.\n");
7814 return NT_STATUS_NOT_SUPPORTED;
7817 status = cli_unix_extensions_version(cli, &major, &minor, &caplow,
7819 if (!NT_STATUS_IS_OK(status)) {
7820 printf("Server didn't return UNIX CIFS extensions: %s\n",
7825 status = cli_set_unix_extensions_capabilities(cli, major, minor,
7827 if (!NT_STATUS_IS_OK(status)) {
7828 printf("Server doesn't support setting UNIX CIFS extensions: "
7829 "%s.\n", nt_errstr(status));
7833 return NT_STATUS_OK;
7837 Test POSIX open /mkdir calls.
7839 static bool run_simple_posix_open_test(int dummy)
7841 static struct cli_state *cli1;
7842 const char *fname = "posix:file";
7843 const char *hname = "posix:hlink";
7844 const char *sname = "posix:symlink";
7845 const char *dname = "posix:dir";
7847 char *target = NULL;
7848 uint16_t fnum1 = (uint16_t)-1;
7849 SMB_STRUCT_STAT sbuf;
7850 bool correct = false;
7853 const char *fname_windows = "windows_file";
7854 uint16_t fnum2 = (uint16_t)-1;
7857 printf("Starting simple POSIX open test\n");
7859 if (!torture_open_connection(&cli1, 0)) {
7863 smbXcli_conn_set_sockopt(cli1->conn, sockops);
7865 status = torture_setup_unix_extensions(cli1);
7866 if (!NT_STATUS_IS_OK(status)) {
7870 cli_setatr(cli1, fname, 0, 0);
7871 cli_posix_unlink(cli1, fname);
7872 cli_setatr(cli1, dname, 0, 0);
7873 cli_posix_rmdir(cli1, dname);
7874 cli_setatr(cli1, hname, 0, 0);
7875 cli_posix_unlink(cli1, hname);
7876 cli_setatr(cli1, sname, 0, 0);
7877 cli_posix_unlink(cli1, sname);
7878 cli_setatr(cli1, fname_windows, 0, 0);
7879 cli_posix_unlink(cli1, fname_windows);
7881 /* Create a directory. */
7882 status = cli_posix_mkdir(cli1, dname, 0777);
7883 if (!NT_STATUS_IS_OK(status)) {
7884 printf("POSIX mkdir of %s failed (%s)\n", dname, nt_errstr(status));
7888 status = cli_posix_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL,
7890 if (!NT_STATUS_IS_OK(status)) {
7891 printf("POSIX create of %s failed (%s)\n", fname, nt_errstr(status));
7895 /* Test ftruncate - set file size. */
7896 status = cli_ftruncate(cli1, fnum1, 1000);
7897 if (!NT_STATUS_IS_OK(status)) {
7898 printf("ftruncate failed (%s)\n", nt_errstr(status));
7902 /* Ensure st_size == 1000 */
7903 status = cli_posix_stat(cli1, fname, &sbuf);
7904 if (!NT_STATUS_IS_OK(status)) {
7905 printf("stat failed (%s)\n", nt_errstr(status));
7909 if (sbuf.st_ex_size != 1000) {
7910 printf("ftruncate - stat size (%u) != 1000\n", (unsigned int)sbuf.st_ex_size);
7914 /* Ensure st_mode == 0600 */
7915 if ((sbuf.st_ex_mode & 07777) != 0600) {
7916 printf("posix_open - bad permissions 0%o != 0600\n",
7917 (unsigned int)(sbuf.st_ex_mode & 07777));
7921 /* Test ftruncate - set file size back to zero. */
7922 status = cli_ftruncate(cli1, fnum1, 0);
7923 if (!NT_STATUS_IS_OK(status)) {
7924 printf("ftruncate failed (%s)\n", nt_errstr(status));
7928 status = cli_close(cli1, fnum1);
7929 if (!NT_STATUS_IS_OK(status)) {
7930 printf("close failed (%s)\n", nt_errstr(status));
7934 /* Now open the file again for read only. */
7935 status = cli_posix_open(cli1, fname, O_RDONLY, 0, &fnum1);
7936 if (!NT_STATUS_IS_OK(status)) {
7937 printf("POSIX open of %s failed (%s)\n", fname, nt_errstr(status));
7941 /* Now unlink while open. */
7942 status = cli_posix_unlink(cli1, fname);
7943 if (!NT_STATUS_IS_OK(status)) {
7944 printf("POSIX unlink of %s failed (%s)\n", fname, nt_errstr(status));
7948 status = cli_close(cli1, fnum1);
7949 if (!NT_STATUS_IS_OK(status)) {
7950 printf("close(2) failed (%s)\n", nt_errstr(status));
7954 /* Ensure the file has gone. */
7955 status = cli_posix_open(cli1, fname, O_RDONLY, 0, &fnum1);
7956 if (NT_STATUS_IS_OK(status)) {
7957 printf("POSIX open of %s succeeded, should have been deleted.\n", fname);
7961 /* Create again to test open with O_TRUNC. */
7962 status = cli_posix_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL, 0600, &fnum1);
7963 if (!NT_STATUS_IS_OK(status)) {
7964 printf("POSIX create of %s failed (%s)\n", fname, nt_errstr(status));
7968 /* Test ftruncate - set file size. */
7969 status = cli_ftruncate(cli1, fnum1, 1000);
7970 if (!NT_STATUS_IS_OK(status)) {
7971 printf("ftruncate failed (%s)\n", nt_errstr(status));
7975 /* Ensure st_size == 1000 */
7976 status = cli_posix_stat(cli1, fname, &sbuf);
7977 if (!NT_STATUS_IS_OK(status)) {
7978 printf("stat failed (%s)\n", nt_errstr(status));
7982 if (sbuf.st_ex_size != 1000) {
7983 printf("ftruncate - stat size (%u) != 1000\n", (unsigned int)sbuf.st_ex_size);
7987 status = cli_close(cli1, fnum1);
7988 if (!NT_STATUS_IS_OK(status)) {
7989 printf("close(2) failed (%s)\n", nt_errstr(status));
7993 /* Re-open with O_TRUNC. */
7994 status = cli_posix_open(cli1, fname, O_WRONLY|O_TRUNC, 0600, &fnum1);
7995 if (!NT_STATUS_IS_OK(status)) {
7996 printf("POSIX create of %s failed (%s)\n", fname, nt_errstr(status));
8000 /* Ensure st_size == 0 */
8001 status = cli_posix_stat(cli1, fname, &sbuf);
8002 if (!NT_STATUS_IS_OK(status)) {
8003 printf("stat failed (%s)\n", nt_errstr(status));
8007 if (sbuf.st_ex_size != 0) {
8008 printf("O_TRUNC - stat size (%u) != 0\n", (unsigned int)sbuf.st_ex_size);
8012 status = cli_close(cli1, fnum1);
8013 if (!NT_STATUS_IS_OK(status)) {
8014 printf("close failed (%s)\n", nt_errstr(status));
8018 status = cli_posix_unlink(cli1, fname);
8019 if (!NT_STATUS_IS_OK(status)) {
8020 printf("POSIX unlink of %s failed (%s)\n", fname, nt_errstr(status));
8024 status = cli_posix_open(cli1, dname, O_RDONLY, 0, &fnum1);
8025 if (!NT_STATUS_IS_OK(status)) {
8026 printf("POSIX open directory O_RDONLY of %s failed (%s)\n",
8027 dname, nt_errstr(status));
8031 cli_close(cli1, fnum1);
8033 /* What happens when we try and POSIX open a directory for write ? */
8034 status = cli_posix_open(cli1, dname, O_RDWR, 0, &fnum1);
8035 if (NT_STATUS_IS_OK(status)) {
8036 printf("POSIX open of directory %s succeeded, "
8037 "should have failed.\n",
8041 if (!check_both_error(__LINE__, status, ERRDOS, EISDIR,
8042 NT_STATUS_FILE_IS_A_DIRECTORY)) {
8047 /* Create the file. */
8048 status = cli_posix_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL,
8050 if (!NT_STATUS_IS_OK(status)) {
8051 printf("POSIX create of %s failed (%s)\n", fname, nt_errstr(status));
8055 /* Write some data into it. */
8056 status = cli_writeall(cli1, fnum1, 0, (const uint8_t *)"TEST DATA\n", 0, 10,
8058 if (!NT_STATUS_IS_OK(status)) {
8059 printf("cli_write failed: %s\n", nt_errstr(status));
8063 cli_close(cli1, fnum1);
8065 /* Now create a hardlink. */
8066 status = cli_posix_hardlink(cli1, fname, hname);
8067 if (!NT_STATUS_IS_OK(status)) {
8068 printf("POSIX hardlink of %s failed (%s)\n", hname, nt_errstr(status));
8072 /* Now create a symlink. */
8073 status = cli_posix_symlink(cli1, fname, sname);
8074 if (!NT_STATUS_IS_OK(status)) {
8075 printf("POSIX symlink of %s failed (%s)\n", sname, nt_errstr(status));
8079 /* Open the hardlink for read. */
8080 status = cli_posix_open(cli1, hname, O_RDONLY, 0, &fnum1);
8081 if (!NT_STATUS_IS_OK(status)) {
8082 printf("POSIX open of %s failed (%s)\n", hname, nt_errstr(status));
8086 status = cli_read(cli1, fnum1, buf, 0, 10, &nread);
8087 if (!NT_STATUS_IS_OK(status)) {
8088 printf("POSIX read of %s failed (%s)\n", hname,
8091 } else if (nread != 10) {
8092 printf("POSIX read of %s failed. Received %ld, expected %d\n",
8093 hname, (unsigned long)nread, 10);
8097 if (memcmp(buf, "TEST DATA\n", 10)) {
8098 printf("invalid data read from hardlink\n");
8102 /* Do a POSIX lock/unlock. */
8103 status = cli_posix_lock(cli1, fnum1, 0, 100, true, READ_LOCK);
8104 if (!NT_STATUS_IS_OK(status)) {
8105 printf("POSIX lock failed %s\n", nt_errstr(status));
8109 /* Punch a hole in the locked area. */
8110 status = cli_posix_unlock(cli1, fnum1, 10, 80);
8111 if (!NT_STATUS_IS_OK(status)) {
8112 printf("POSIX unlock failed %s\n", nt_errstr(status));
8116 cli_close(cli1, fnum1);
8118 /* Open the symlink for read - this should fail. A POSIX
8119 client should not be doing opens on a symlink. */
8120 status = cli_posix_open(cli1, sname, O_RDONLY, 0, &fnum1);
8121 if (NT_STATUS_IS_OK(status)) {
8122 printf("POSIX open of %s succeeded (should have failed)\n", sname);
8125 ok = check_both_error(
8126 __LINE__, status, ERRDOS, ERRbadpath,
8127 NT_STATUS_OBJECT_NAME_NOT_FOUND);
8129 printf("POSIX open of %s should have failed "
8130 "with NT_STATUS_OBJECT_NAME_NOT_FOUND, "
8131 "failed with %s instead.\n",
8132 sname, nt_errstr(status));
8136 status = cli_readlink(cli1, sname, talloc_tos(), &target, NULL, NULL);
8137 if (!NT_STATUS_IS_OK(status)) {
8138 printf("POSIX readlink on %s failed (%s)\n", sname, nt_errstr(status));
8142 if (strcmp(target, fname) != 0) {
8143 printf("POSIX readlink on %s failed to match name %s (read %s)\n",
8144 sname, fname, target);
8148 status = cli_posix_rmdir(cli1, dname);
8149 if (!NT_STATUS_IS_OK(status)) {
8150 printf("POSIX rmdir failed (%s)\n", nt_errstr(status));
8154 /* Check directory opens with a specific permission. */
8155 status = cli_posix_mkdir(cli1, dname, 0700);
8156 if (!NT_STATUS_IS_OK(status)) {
8157 printf("POSIX mkdir of %s failed (%s)\n", dname, nt_errstr(status));
8161 /* Ensure st_mode == 0700 */
8162 status = cli_posix_stat(cli1, dname, &sbuf);
8163 if (!NT_STATUS_IS_OK(status)) {
8164 printf("stat failed (%s)\n", nt_errstr(status));
8168 if ((sbuf.st_ex_mode & 07777) != 0700) {
8169 printf("posix_mkdir - bad permissions 0%o != 0700\n",
8170 (unsigned int)(sbuf.st_ex_mode & 07777));
8175 * Now create a Windows file, and attempt a POSIX unlink.
8176 * This should fail with a sharing violation but due to:
8178 * [Bug 9571] Unlink after open causes smbd to panic
8180 * ensure we've fixed the lock ordering violation.
8183 status = cli_ntcreate(cli1, fname_windows, 0,
8184 FILE_READ_DATA|FILE_WRITE_DATA, 0,
8185 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
8187 0x0, 0x0, &fnum2, NULL);
8188 if (!NT_STATUS_IS_OK(status)) {
8189 printf("Windows create of %s failed (%s)\n", fname_windows,
8194 /* Now try posix_unlink. */
8195 status = cli_posix_unlink(cli1, fname_windows);
8196 if (!NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
8197 printf("POSIX unlink of %s should fail "
8198 "with NT_STATUS_SHARING_VIOLATION "
8199 "got %s instead !\n",
8205 cli_close(cli1, fnum2);
8207 printf("Simple POSIX open test passed\n");
8212 if (fnum1 != (uint16_t)-1) {
8213 cli_close(cli1, fnum1);
8214 fnum1 = (uint16_t)-1;
8217 if (fnum2 != (uint16_t)-1) {
8218 cli_close(cli1, fnum2);
8219 fnum2 = (uint16_t)-1;
8222 cli_setatr(cli1, sname, 0, 0);
8223 cli_posix_unlink(cli1, sname);
8224 cli_setatr(cli1, hname, 0, 0);
8225 cli_posix_unlink(cli1, hname);
8226 cli_setatr(cli1, fname, 0, 0);
8227 cli_posix_unlink(cli1, fname);
8228 cli_setatr(cli1, dname, 0, 0);
8229 cli_posix_rmdir(cli1, dname);
8230 cli_setatr(cli1, fname_windows, 0, 0);
8231 cli_posix_unlink(cli1, fname_windows);
8233 if (!torture_close_connection(cli1)) {
8241 Test POSIX and Windows ACLs are rejected on symlinks.
8243 static bool run_acl_symlink_test(int dummy)
8245 static struct cli_state *cli;
8246 const char *fname = "posix_file";
8247 const char *sname = "posix_symlink";
8248 uint16_t fnum = (uint16_t)-1;
8249 bool correct = false;
8251 char *posix_acl = NULL;
8252 size_t posix_acl_len = 0;
8253 char *posix_acl_sym = NULL;
8254 size_t posix_acl_len_sym = 0;
8255 struct security_descriptor *sd = NULL;
8256 TALLOC_CTX *frame = NULL;
8258 frame = talloc_stackframe();
8260 printf("Starting acl symlink test\n");
8262 if (!torture_open_connection(&cli, 0)) {
8267 smbXcli_conn_set_sockopt(cli->conn, sockops);
8269 status = torture_setup_unix_extensions(cli);
8270 if (!NT_STATUS_IS_OK(status)) {
8275 cli_setatr(cli, fname, 0, 0);
8276 cli_posix_unlink(cli, fname);
8277 cli_setatr(cli, sname, 0, 0);
8278 cli_posix_unlink(cli, sname);
8280 status = cli_ntcreate(cli,
8283 READ_CONTROL_ACCESS,
8285 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
8292 if (!NT_STATUS_IS_OK(status)) {
8293 printf("cli_ntcreate of %s failed (%s)\n",
8299 /* Get the Windows ACL on the file. */
8300 status = cli_query_secdesc(cli,
8304 if (!NT_STATUS_IS_OK(status)) {
8305 printf("cli_query_secdesc failed (%s)\n",
8310 /* Get the POSIX ACL on the file. */
8311 status = cli_posix_getacl(cli,
8317 if (!NT_STATUS_IS_OK(status)) {
8318 printf("cli_posix_getacl failed (%s)\n",
8323 status = cli_close(cli, fnum);
8324 if (!NT_STATUS_IS_OK(status)) {
8325 printf("close failed (%s)\n", nt_errstr(status));
8328 fnum = (uint16_t)-1;
8330 /* Now create a symlink. */
8331 status = cli_posix_symlink(cli, fname, sname);
8332 if (!NT_STATUS_IS_OK(status)) {
8333 printf("cli_posix_symlink of %s -> %s failed (%s)\n",
8340 /* Open a handle on the symlink for SD set/get should fail. */
8341 status = cli_ntcreate(cli,
8344 READ_CONTROL_ACCESS|SEC_STD_WRITE_DAC,
8346 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
8353 if (NT_STATUS_IS_OK(status)) {
8354 printf("Symlink open for getsd/setsd of %s "
8355 "succeeded (should fail)\n",
8360 /* Try a stat-open on the symlink, should also fail. */
8361 status = cli_ntcreate(cli,
8364 FILE_READ_ATTRIBUTES|FILE_WRITE_ATTRIBUTES,
8366 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
8373 if (NT_STATUS_IS_OK(status)) {
8374 printf("Stat-open of symlink succeeded (should fail)\n");
8378 /* Get the POSIX ACL on the symlink pathname. Should fail. */
8379 status = cli_posix_getacl(cli,
8385 if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
8386 printf("cli_posix_getacl on a symlink gave %s. "
8387 "Should be NT_STATUS_ACCESS_DENIED.\n",
8392 /* Set the POSIX ACL on the symlink pathname. Should fail. */
8393 status = cli_posix_setacl(cli,
8398 if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
8399 printf("cli_posix_setacl on a symlink gave %s. "
8400 "Should be NT_STATUS_ACCESS_DENIED.\n",
8405 printf("ACL symlink test passed\n");
8410 if (fnum != (uint16_t)-1) {
8411 cli_close(cli, fnum);
8412 fnum = (uint16_t)-1;
8415 cli_setatr(cli, sname, 0, 0);
8416 cli_posix_unlink(cli, sname);
8417 cli_setatr(cli, fname, 0, 0);
8418 cli_posix_unlink(cli, fname);
8420 if (!torture_close_connection(cli)) {
8429 Test POSIX can delete a file containing streams.
8431 static bool run_posix_stream_delete(int dummy)
8433 struct cli_state *cli1 = NULL;
8434 struct cli_state *cli2 = NULL;
8435 const char *fname = "streamfile";
8436 const char *stream_fname = "streamfile:Zone.Identifier:$DATA";
8437 uint16_t fnum1 = (uint16_t)-1;
8438 bool correct = false;
8440 TALLOC_CTX *frame = NULL;
8442 frame = talloc_stackframe();
8444 printf("Starting POSIX stream delete test\n");
8446 if (!torture_open_connection(&cli1, 0) ||
8447 !torture_open_connection(&cli2, 1)) {
8452 smbXcli_conn_set_sockopt(cli1->conn, sockops);
8453 smbXcli_conn_set_sockopt(cli2->conn, sockops);
8455 status = torture_setup_unix_extensions(cli2);
8456 if (!NT_STATUS_IS_OK(status)) {
8460 cli_setatr(cli1, fname, 0, 0);
8461 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
8463 /* Create the file. */
8464 status = cli_ntcreate(cli1,
8467 READ_CONTROL_ACCESS,
8469 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
8476 if (!NT_STATUS_IS_OK(status)) {
8477 printf("cli_ntcreate of %s failed (%s)\n",
8483 status = cli_close(cli1, fnum1);
8484 if (!NT_STATUS_IS_OK(status)) {
8485 printf("cli_close of %s failed (%s)\n",
8490 fnum1 = (uint16_t)-1;
8492 /* Now create the stream. */
8493 status = cli_ntcreate(cli1,
8498 FILE_SHARE_READ|FILE_SHARE_WRITE,
8505 if (!NT_STATUS_IS_OK(status)) {
8506 printf("cli_ntcreate of %s failed (%s)\n",
8512 /* Leave the stream handle open... */
8514 /* POSIX unlink should fail. */
8515 status = cli_posix_unlink(cli2, fname);
8516 if (NT_STATUS_IS_OK(status)) {
8517 printf("cli_posix_unlink of %s succeeded, should have failed\n",
8522 if (!NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
8523 printf("cli_posix_unlink of %s failed with (%s) "
8524 "should have been NT_STATUS_SHARING_VIOLATION\n",
8530 /* Close the stream handle. */
8531 status = cli_close(cli1, fnum1);
8532 if (!NT_STATUS_IS_OK(status)) {
8533 printf("cli_close of %s failed (%s)\n",
8538 fnum1 = (uint16_t)-1;
8540 /* POSIX unlink after stream handle closed should succeed. */
8541 status = cli_posix_unlink(cli2, fname);
8542 if (!NT_STATUS_IS_OK(status)) {
8543 printf("cli_posix_unlink of %s failed (%s)\n",
8549 printf("POSIX stream delete test passed\n");
8554 if (fnum1 != (uint16_t)-1) {
8555 cli_close(cli1, fnum1);
8556 fnum1 = (uint16_t)-1;
8559 cli_setatr(cli1, fname, 0, 0);
8560 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
8562 if (!torture_close_connection(cli1)) {
8565 if (!torture_close_connection(cli2)) {
8574 Test setting EA's are rejected on symlinks.
8576 static bool run_ea_symlink_test(int dummy)
8578 static struct cli_state *cli;
8579 const char *fname = "posix_file_ea";
8580 const char *sname = "posix_symlink_ea";
8581 const char *ea_name = "testea_name";
8582 const char *ea_value = "testea_value";
8583 uint16_t fnum = (uint16_t)-1;
8584 bool correct = false;
8587 struct ea_struct *eas = NULL;
8588 TALLOC_CTX *frame = NULL;
8590 frame = talloc_stackframe();
8592 printf("Starting EA symlink test\n");
8594 if (!torture_open_connection(&cli, 0)) {
8599 smbXcli_conn_set_sockopt(cli->conn, sockops);
8601 status = torture_setup_unix_extensions(cli);
8602 if (!NT_STATUS_IS_OK(status)) {
8607 cli_setatr(cli, fname, 0, 0);
8608 cli_posix_unlink(cli, fname);
8609 cli_setatr(cli, sname, 0, 0);
8610 cli_posix_unlink(cli, sname);
8612 status = cli_ntcreate(cli,
8615 READ_CONTROL_ACCESS,
8617 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
8624 if (!NT_STATUS_IS_OK(status)) {
8625 printf("cli_ntcreate of %s failed (%s)\n",
8631 status = cli_close(cli, fnum);
8632 if (!NT_STATUS_IS_OK(status)) {
8633 printf("close failed (%s)\n",
8637 fnum = (uint16_t)-1;
8639 /* Set an EA on the path. */
8640 status = cli_set_ea_path(cli,
8644 strlen(ea_value)+1);
8646 if (!NT_STATUS_IS_OK(status)) {
8647 printf("cli_set_ea_path failed (%s)\n",
8652 /* Now create a symlink. */
8653 status = cli_posix_symlink(cli, fname, sname);
8654 if (!NT_STATUS_IS_OK(status)) {
8655 printf("cli_posix_symlink of %s -> %s failed (%s)\n",
8662 /* Get the EA list on the path. Should return value set. */
8663 status = cli_get_ea_list_path(cli,
8669 if (!NT_STATUS_IS_OK(status)) {
8670 printf("cli_get_ea_list_path failed (%s)\n",
8675 /* Ensure the EA we set is there. */
8676 for (i=0; i<num_eas; i++) {
8677 if (strcmp(eas[i].name, ea_name) == 0 &&
8678 eas[i].value.length == strlen(ea_value)+1 &&
8679 memcmp(eas[i].value.data,
8681 eas[i].value.length) == 0) {
8687 printf("Didn't find EA on pathname %s\n",
8695 /* Get the EA list on the symlink. Should return empty list. */
8696 status = cli_get_ea_list_path(cli,
8702 if (!NT_STATUS_IS_OK(status)) {
8703 printf("cli_get_ea_list_path failed (%s)\n",
8709 printf("cli_get_ea_list_path failed (%s)\n",
8714 /* Set an EA on the symlink. Should fail. */
8715 status = cli_set_ea_path(cli,
8719 strlen(ea_value)+1);
8721 if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
8722 printf("cli_set_ea_path on a symlink gave %s. "
8723 "Should be NT_STATUS_ACCESS_DENIED.\n",
8728 printf("EA symlink test passed\n");
8733 if (fnum != (uint16_t)-1) {
8734 cli_close(cli, fnum);
8735 fnum = (uint16_t)-1;
8738 cli_setatr(cli, sname, 0, 0);
8739 cli_posix_unlink(cli, sname);
8740 cli_setatr(cli, fname, 0, 0);
8741 cli_posix_unlink(cli, fname);
8743 if (!torture_close_connection(cli)) {
8752 Test POSIX locks are OFD-locks.
8754 static bool run_posix_ofd_lock_test(int dummy)
8756 static struct cli_state *cli;
8757 const char *fname = "posix_file";
8758 uint16_t fnum1 = (uint16_t)-1;
8759 uint16_t fnum2 = (uint16_t)-1;
8760 bool correct = false;
8762 TALLOC_CTX *frame = NULL;
8764 frame = talloc_stackframe();
8766 printf("Starting POSIX ofd-lock test\n");
8768 if (!torture_open_connection(&cli, 0)) {
8773 smbXcli_conn_set_sockopt(cli->conn, sockops);
8775 status = torture_setup_unix_extensions(cli);
8776 if (!NT_STATUS_IS_OK(status)) {
8781 cli_setatr(cli, fname, 0, 0);
8782 cli_posix_unlink(cli, fname);
8784 /* Open the file twice. */
8785 status = cli_posix_open(cli, fname, O_RDWR|O_CREAT|O_EXCL,
8787 if (!NT_STATUS_IS_OK(status)) {
8788 printf("First POSIX open of %s failed\n", fname);
8792 status = cli_posix_open(cli, fname, O_RDWR, 0, &fnum2);
8793 if (!NT_STATUS_IS_OK(status)) {
8794 printf("First POSIX open of %s failed\n", fname);
8798 /* Set a 0-50 lock on fnum1. */
8799 status = cli_posix_lock(cli, fnum1, 0, 50, false, WRITE_LOCK);
8800 if (!NT_STATUS_IS_OK(status)) {
8801 printf("POSIX lock (1) failed %s\n", nt_errstr(status));
8805 /* Set a 60-100 lock on fnum2. */
8806 status = cli_posix_lock(cli, fnum2, 60, 100, false, WRITE_LOCK);
8807 if (!NT_STATUS_IS_OK(status)) {
8808 printf("POSIX lock (2) failed %s\n", nt_errstr(status));
8812 /* close fnum1 - 0-50 lock should go away. */
8813 status = cli_close(cli, fnum1);
8814 if (!NT_STATUS_IS_OK(status)) {
8815 printf("close failed (%s)\n",
8819 fnum1 = (uint16_t)-1;
8821 /* Change the lock context. */
8822 cli_setpid(cli, cli_getpid(cli) + 1);
8824 /* Re-open fnum1. */
8825 status = cli_posix_open(cli, fname, O_RDWR, 0, &fnum1);
8826 if (!NT_STATUS_IS_OK(status)) {
8827 printf("Third POSIX open of %s failed\n", fname);
8831 /* 60-100 lock should still be there. */
8832 status = cli_posix_lock(cli, fnum1, 60, 100, false, WRITE_LOCK);
8833 if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
8834 printf("POSIX lock 60-100 not there %s\n", nt_errstr(status));
8838 /* 0-50 lock should be gone. */
8839 status = cli_posix_lock(cli, fnum1, 0, 50, false, WRITE_LOCK);
8840 if (!NT_STATUS_IS_OK(status)) {
8841 printf("POSIX lock 0-50 failed %s\n", nt_errstr(status));
8845 printf("POSIX OFD lock test passed\n");
8850 if (fnum1 != (uint16_t)-1) {
8851 cli_close(cli, fnum1);
8852 fnum1 = (uint16_t)-1;
8854 if (fnum2 != (uint16_t)-1) {
8855 cli_close(cli, fnum2);
8856 fnum2 = (uint16_t)-1;
8859 cli_setatr(cli, fname, 0, 0);
8860 cli_posix_unlink(cli, fname);
8862 if (!torture_close_connection(cli)) {
8870 struct posix_blocking_state {
8871 struct tevent_context *ev;
8872 struct cli_state *cli1;
8874 struct cli_state *cli2;
8880 static void posix_blocking_locked(struct tevent_req *subreq);
8881 static void posix_blocking_gotblocked(struct tevent_req *subreq);
8882 static void posix_blocking_gotecho(struct tevent_req *subreq);
8883 static void posix_blocking_unlocked(struct tevent_req *subreq);
8885 static struct tevent_req *posix_blocking_send(
8886 TALLOC_CTX *mem_ctx,
8887 struct tevent_context *ev,
8888 struct cli_state *cli1,
8890 struct cli_state *cli2,
8893 struct tevent_req *req = NULL, *subreq = NULL;
8894 struct posix_blocking_state *state = NULL;
8896 req = tevent_req_create(mem_ctx, &state, struct posix_blocking_state);
8902 state->fnum1 = fnum1;
8904 state->fnum2 = fnum2;
8906 subreq = cli_posix_lock_send(
8915 if (tevent_req_nomem(subreq, req)) {
8916 return tevent_req_post(req, ev);
8918 tevent_req_set_callback(subreq, posix_blocking_locked, req);
8922 static void posix_blocking_locked(struct tevent_req *subreq)
8924 struct tevent_req *req = tevent_req_callback_data(
8925 subreq, struct tevent_req);
8926 struct posix_blocking_state *state = tevent_req_data(
8927 req, struct posix_blocking_state);
8930 status = cli_posix_lock_recv(subreq);
8931 TALLOC_FREE(subreq);
8932 if (tevent_req_nterror(req, status)) {
8936 subreq = cli_posix_lock_send(
8945 if (tevent_req_nomem(subreq, req)) {
8948 tevent_req_set_callback(subreq, posix_blocking_gotblocked, req);
8950 /* Make sure the blocking request is delivered */
8951 subreq = cli_echo_send(
8956 (DATA_BLOB) { .data = (uint8_t *)state, .length = 1 });
8957 if (tevent_req_nomem(subreq, req)) {
8960 tevent_req_set_callback(subreq, posix_blocking_gotecho, req);
8963 static void posix_blocking_gotblocked(struct tevent_req *subreq)
8965 struct tevent_req *req = tevent_req_callback_data(
8966 subreq, struct tevent_req);
8967 struct posix_blocking_state *state = tevent_req_data(
8968 req, struct posix_blocking_state);
8971 status = cli_posix_lock_recv(subreq);
8972 TALLOC_FREE(subreq);
8973 if (tevent_req_nterror(req, status)) {
8976 if (!state->gotecho) {
8977 printf("blocked req got through before echo\n");
8978 tevent_req_nterror(req, NT_STATUS_INVALID_LOCK_SEQUENCE);
8981 tevent_req_done(req);
8984 static void posix_blocking_gotecho(struct tevent_req *subreq)
8986 struct tevent_req *req = tevent_req_callback_data(
8987 subreq, struct tevent_req);
8988 struct posix_blocking_state *state = tevent_req_data(
8989 req, struct posix_blocking_state);
8992 status = cli_echo_recv(subreq);
8993 TALLOC_FREE(subreq);
8994 if (tevent_req_nterror(req, status)) {
8997 if (state->gotblocked) {
8998 printf("blocked req got through before echo\n");
8999 tevent_req_nterror(req, NT_STATUS_INVALID_LOCK_SEQUENCE);
9002 state->gotecho = true;
9004 subreq = cli_posix_lock_send(
9013 if (tevent_req_nomem(subreq, req)) {
9016 tevent_req_set_callback(subreq, posix_blocking_unlocked, req);
9019 static void posix_blocking_unlocked(struct tevent_req *subreq)
9021 struct tevent_req *req = tevent_req_callback_data(
9022 subreq, struct tevent_req);
9025 status = cli_posix_lock_recv(subreq);
9026 TALLOC_FREE(subreq);
9027 if (tevent_req_nterror(req, status)) {
9030 /* tevent_req_done in posix_blocking_gotlocked */
9033 static NTSTATUS posix_blocking_recv(struct tevent_req *req)
9035 return tevent_req_simple_recv_ntstatus(req);
9038 static bool run_posix_blocking_lock(int dummy)
9040 struct tevent_context *ev = NULL;
9041 struct cli_state *cli1 = NULL, *cli2 = NULL;
9042 const char *fname = "posix_blocking";
9043 uint16_t fnum1 = UINT16_MAX, fnum2 = UINT16_MAX;
9044 struct tevent_req *req = NULL;
9049 printf("Starting posix blocking lock test\n");
9051 ev = samba_tevent_context_init(NULL);
9056 ok = torture_open_connection(&cli1, 0);
9060 ok = torture_open_connection(&cli2, 0);
9065 smbXcli_conn_set_sockopt(cli1->conn, sockops);
9067 status = torture_setup_unix_extensions(cli1);
9068 if (!NT_STATUS_IS_OK(status)) {
9072 status = torture_setup_unix_extensions(cli2);
9073 if (!NT_STATUS_IS_OK(status)) {
9077 cli_setatr(cli1, fname, 0, 0);
9078 cli_posix_unlink(cli1, fname);
9080 status = cli_posix_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL,
9082 if (!NT_STATUS_IS_OK(status)) {
9083 printf("First POSIX open of %s failed: %s\n",
9089 status = cli_posix_open(cli2, fname, O_RDWR, 0600, &fnum2);
9090 if (!NT_STATUS_IS_OK(status)) {
9091 printf("Second POSIX open of %s failed: %s\n",
9097 req = posix_blocking_send(ev, ev, cli1, fnum1, cli2, fnum2);
9099 printf("cli_posix_blocking failed\n");
9103 ok = tevent_req_poll_ntstatus(req, ev, &status);
9105 printf("tevent_req_poll_ntstatus failed: %s\n",
9109 status = posix_blocking_recv(req);
9111 if (!NT_STATUS_IS_OK(status)) {
9112 printf("posix_blocking_recv returned %s\n",
9120 if (fnum1 != UINT16_MAX) {
9121 cli_close(cli1, fnum1);
9124 if (fnum2 != UINT16_MAX) {
9125 cli_close(cli2, fnum2);
9130 cli_setatr(cli1, fname, 0, 0);
9131 cli_posix_unlink(cli1, fname);
9137 ok &= torture_close_connection(cli1);
9141 ok &= torture_close_connection(cli2);
9153 Test POSIX mkdir is case-sensitive.
9155 static bool run_posix_mkdir_test(int dummy)
9157 static struct cli_state *cli;
9158 const char *fname_foo = "POSIX_foo";
9159 const char *fname_foo_Foo = "POSIX_foo/Foo";
9160 const char *fname_foo_foo = "POSIX_foo/foo";
9161 const char *fname_Foo = "POSIX_Foo";
9162 const char *fname_Foo_Foo = "POSIX_Foo/Foo";
9163 const char *fname_Foo_foo = "POSIX_Foo/foo";
9164 bool correct = false;
9166 TALLOC_CTX *frame = NULL;
9167 uint16_t fnum = (uint16_t)-1;
9169 frame = talloc_stackframe();
9171 printf("Starting POSIX mkdir test\n");
9173 if (!torture_open_connection(&cli, 0)) {
9178 smbXcli_conn_set_sockopt(cli->conn, sockops);
9180 status = torture_setup_unix_extensions(cli);
9181 if (!NT_STATUS_IS_OK(status)) {
9186 cli_posix_rmdir(cli, fname_foo_foo);
9187 cli_posix_rmdir(cli, fname_foo_Foo);
9188 cli_posix_rmdir(cli, fname_foo);
9190 cli_posix_rmdir(cli, fname_Foo_foo);
9191 cli_posix_rmdir(cli, fname_Foo_Foo);
9192 cli_posix_rmdir(cli, fname_Foo);
9195 * Create a file POSIX_foo then try
9196 * and use it in a directory path by
9197 * doing mkdir POSIX_foo/bar.
9198 * The mkdir should fail with
9199 * NT_STATUS_OBJECT_PATH_NOT_FOUND
9202 status = cli_posix_open(cli,
9207 if (!NT_STATUS_IS_OK(status)) {
9208 printf("cli_posix_open of %s failed error %s\n",
9214 status = cli_posix_mkdir(cli, fname_foo_foo, 0777);
9215 if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_PATH_NOT_FOUND)) {
9216 printf("cli_posix_mkdir of %s should fail with "
9217 "NT_STATUS_OBJECT_PATH_NOT_FOUND got "
9224 status = cli_close(cli, fnum);
9225 if (!NT_STATUS_IS_OK(status)) {
9226 printf("cli_close failed %s\n", nt_errstr(status));
9229 fnum = (uint16_t)-1;
9231 status = cli_posix_unlink(cli, fname_foo);
9232 if (!NT_STATUS_IS_OK(status)) {
9233 printf("cli_posix_unlink of %s failed error %s\n",
9240 * Now we've deleted everything, posix_mkdir, posix_rmdir,
9241 * posix_open, posix_unlink, on
9242 * POSIX_foo/foo should return NT_STATUS_OBJECT_PATH_NOT_FOUND
9243 * not silently create POSIX_foo/foo.
9246 status = cli_posix_mkdir(cli, fname_foo_foo, 0777);
9247 if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_PATH_NOT_FOUND)) {
9248 printf("cli_posix_mkdir of %s should fail with "
9249 "NT_STATUS_OBJECT_PATH_NOT_FOUND got "
9256 status = cli_posix_rmdir(cli, fname_foo_foo);
9257 if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_PATH_NOT_FOUND)) {
9258 printf("cli_posix_rmdir of %s should fail with "
9259 "NT_STATUS_OBJECT_PATH_NOT_FOUND got "
9266 status = cli_posix_open(cli,
9271 if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_PATH_NOT_FOUND)) {
9272 printf("cli_posix_open of %s should fail with "
9273 "NT_STATUS_OBJECT_PATH_NOT_FOUND got "
9280 status = cli_posix_unlink(cli, fname_foo_foo);
9281 if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_PATH_NOT_FOUND)) {
9282 printf("cli_posix_unlink of %s should fail with "
9283 "NT_STATUS_OBJECT_PATH_NOT_FOUND got "
9290 status = cli_posix_mkdir(cli, fname_foo, 0777);
9291 if (!NT_STATUS_IS_OK(status)) {
9292 printf("cli_posix_mkdir of %s failed\n", fname_foo);
9296 status = cli_posix_mkdir(cli, fname_Foo, 0777);
9297 if (!NT_STATUS_IS_OK(status)) {
9298 printf("cli_posix_mkdir of %s failed\n", fname_Foo);
9302 status = cli_posix_mkdir(cli, fname_foo_foo, 0777);
9303 if (!NT_STATUS_IS_OK(status)) {
9304 printf("cli_posix_mkdir of %s failed\n", fname_foo_foo);
9308 status = cli_posix_mkdir(cli, fname_foo_Foo, 0777);
9309 if (!NT_STATUS_IS_OK(status)) {
9310 printf("cli_posix_mkdir of %s failed\n", fname_foo_Foo);
9314 status = cli_posix_mkdir(cli, fname_Foo_foo, 0777);
9315 if (!NT_STATUS_IS_OK(status)) {
9316 printf("cli_posix_mkdir of %s failed\n", fname_Foo_foo);
9320 status = cli_posix_mkdir(cli, fname_Foo_Foo, 0777);
9321 if (!NT_STATUS_IS_OK(status)) {
9322 printf("cli_posix_mkdir of %s failed\n", fname_Foo_Foo);
9326 printf("POSIX mkdir test passed\n");
9331 if (fnum != (uint16_t)-1) {
9332 cli_close(cli, fnum);
9333 fnum = (uint16_t)-1;
9336 cli_posix_rmdir(cli, fname_foo_foo);
9337 cli_posix_rmdir(cli, fname_foo_Foo);
9338 cli_posix_rmdir(cli, fname_foo);
9340 cli_posix_rmdir(cli, fname_Foo_foo);
9341 cli_posix_rmdir(cli, fname_Foo_Foo);
9342 cli_posix_rmdir(cli, fname_Foo);
9344 if (!torture_close_connection(cli)) {
9352 struct posix_acl_oplock_state {
9353 struct tevent_context *ev;
9354 struct cli_state *cli;
9360 static void posix_acl_oplock_got_break(struct tevent_req *req)
9362 struct posix_acl_oplock_state *state = tevent_req_callback_data(
9363 req, struct posix_acl_oplock_state);
9368 status = cli_smb_oplock_break_waiter_recv(req, &fnum, &level);
9370 if (!NT_STATUS_IS_OK(status)) {
9371 printf("cli_smb_oplock_break_waiter_recv returned %s\n",
9375 *state->got_break = true;
9377 req = cli_oplock_ack_send(state, state->ev, state->cli, fnum,
9380 printf("cli_oplock_ack_send failed\n");
9385 static void posix_acl_oplock_got_acl(struct tevent_req *req)
9387 struct posix_acl_oplock_state *state = tevent_req_callback_data(
9388 req, struct posix_acl_oplock_state);
9389 size_t ret_size = 0;
9390 char *ret_data = NULL;
9392 state->status = cli_posix_getacl_recv(req,
9397 if (!NT_STATUS_IS_OK(state->status)) {
9398 printf("cli_posix_getacl_recv returned %s\n",
9399 nt_errstr(state->status));
9401 *state->acl_ret = true;
9404 static bool run_posix_acl_oplock_test(int dummy)
9406 struct tevent_context *ev;
9407 struct cli_state *cli1, *cli2;
9408 struct tevent_req *oplock_req, *getacl_req;
9409 const char *fname = "posix_acl_oplock";
9411 int saved_use_oplocks = use_oplocks;
9413 bool correct = true;
9414 bool got_break = false;
9415 bool acl_ret = false;
9417 struct posix_acl_oplock_state *state;
9419 printf("starting posix_acl_oplock test\n");
9421 if (!torture_open_connection(&cli1, 0)) {
9422 use_level_II_oplocks = false;
9423 use_oplocks = saved_use_oplocks;
9427 if (!torture_open_connection(&cli2, 1)) {
9428 use_level_II_oplocks = false;
9429 use_oplocks = saved_use_oplocks;
9433 /* Setup posix on cli2 only. */
9434 status = torture_setup_unix_extensions(cli2);
9435 if (!NT_STATUS_IS_OK(status)) {
9439 smbXcli_conn_set_sockopt(cli1->conn, sockops);
9440 smbXcli_conn_set_sockopt(cli2->conn, sockops);
9442 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
9444 /* Create the file on the Windows connection. */
9445 status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
9447 if (!NT_STATUS_IS_OK(status)) {
9448 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
9452 status = cli_close(cli1, fnum);
9453 if (!NT_STATUS_IS_OK(status)) {
9454 printf("close1 failed (%s)\n", nt_errstr(status));
9458 cli1->use_oplocks = true;
9460 /* Open with oplock. */
9461 status = cli_ntcreate(cli1,
9465 FILE_ATTRIBUTE_NORMAL,
9466 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
9473 if (!NT_STATUS_IS_OK(status)) {
9474 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
9478 ev = samba_tevent_context_init(talloc_tos());
9480 printf("tevent_context_init failed\n");
9484 state = talloc_zero(ev, struct posix_acl_oplock_state);
9485 if (state == NULL) {
9486 printf("talloc failed\n");
9491 state->got_break = &got_break;
9492 state->acl_ret = &acl_ret;
9494 oplock_req = cli_smb_oplock_break_waiter_send(
9495 talloc_tos(), ev, cli1);
9496 if (oplock_req == NULL) {
9497 printf("cli_smb_oplock_break_waiter_send failed\n");
9500 tevent_req_set_callback(oplock_req, posix_acl_oplock_got_break, state);
9502 /* Get ACL on POSIX connection - should break oplock. */
9503 getacl_req = cli_posix_getacl_send(talloc_tos(),
9507 if (getacl_req == NULL) {
9508 printf("cli_posix_getacl_send failed\n");
9511 tevent_req_set_callback(getacl_req, posix_acl_oplock_got_acl, state);
9513 while (!got_break || !acl_ret) {
9515 ret = tevent_loop_once(ev);
9517 printf("tevent_loop_once failed: %s\n",
9523 if (!NT_STATUS_IS_OK(state->status)) {
9524 printf("getacl failed (%s)\n", nt_errstr(state->status));
9528 status = cli_close(cli1, fnum);
9529 if (!NT_STATUS_IS_OK(status)) {
9530 printf("close2 failed (%s)\n", nt_errstr(status));
9534 status = cli_unlink(cli1,
9536 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
9537 if (!NT_STATUS_IS_OK(status)) {
9538 printf("unlink failed (%s)\n", nt_errstr(status));
9542 if (!torture_close_connection(cli1)) {
9545 if (!torture_close_connection(cli2)) {
9553 printf("finished posix acl oplock test\n");
9558 static bool run_posix_acl_shareroot_test(int dummy)
9560 struct cli_state *cli;
9562 bool correct = false;
9563 char *posix_acl = NULL;
9564 size_t posix_acl_len = 0;
9565 uint16_t num_file_acls = 0;
9566 uint16_t num_dir_acls = 0;
9568 uint32_t expected_size = 0;
9569 bool got_user = false;
9570 bool got_group = false;
9571 bool got_other = false;
9572 TALLOC_CTX *frame = NULL;
9574 frame = talloc_stackframe();
9576 printf("starting posix_acl_shareroot test\n");
9578 if (!torture_open_connection(&cli, 0)) {
9583 smbXcli_conn_set_sockopt(cli->conn, sockops);
9585 status = torture_setup_unix_extensions(cli);
9586 if (!NT_STATUS_IS_OK(status)) {
9587 printf("Failed to setup unix extensions\n");
9591 /* Get the POSIX ACL on the root of the share. */
9592 status = cli_posix_getacl(cli,
9598 if (!NT_STATUS_IS_OK(status)) {
9599 printf("cli_posix_getacl of '.' failed (%s)\n",
9604 if (posix_acl_len < 6 ||
9605 SVAL(posix_acl,0) != SMB_POSIX_ACL_VERSION) {
9606 printf("getfacl ., unknown POSIX acl version %u.\n",
9607 (unsigned int)CVAL(posix_acl,0) );
9611 num_file_acls = SVAL(posix_acl,2);
9612 num_dir_acls = SVAL(posix_acl,4);
9613 expected_size = SMB_POSIX_ACL_HEADER_SIZE +
9614 SMB_POSIX_ACL_ENTRY_SIZE*
9615 (num_file_acls+num_dir_acls);
9617 if (posix_acl_len != expected_size) {
9618 printf("incorrect POSIX acl buffer size "
9619 "(should be %u, was %u).\n",
9620 (unsigned int)expected_size,
9621 (unsigned int)posix_acl_len);
9626 * We don't need to know what the ACL's are
9627 * we just need to know we have at least 3
9628 * file entries (u,g,o).
9631 for (i = 0; i < num_file_acls; i++) {
9632 unsigned char tagtype =
9634 SMB_POSIX_ACL_HEADER_SIZE+
9635 (i*SMB_POSIX_ACL_ENTRY_SIZE));
9638 case SMB_POSIX_ACL_USER_OBJ:
9641 case SMB_POSIX_ACL_GROUP_OBJ:
9644 case SMB_POSIX_ACL_OTHER:
9653 printf("Missing user entry\n");
9658 printf("Missing group entry\n");
9663 printf("Missing other entry\n");
9671 if (!torture_close_connection(cli)) {
9675 printf("finished posix acl shareroot test\n");
9681 static uint32_t open_attrs_table[] = {
9682 FILE_ATTRIBUTE_NORMAL,
9683 FILE_ATTRIBUTE_ARCHIVE,
9684 FILE_ATTRIBUTE_READONLY,
9685 FILE_ATTRIBUTE_HIDDEN,
9686 FILE_ATTRIBUTE_SYSTEM,
9688 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY,
9689 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN,
9690 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM,
9691 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN,
9692 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM,
9693 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM,
9695 FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN,
9696 FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM,
9697 FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM,
9698 FILE_ATTRIBUTE_HIDDEN,FILE_ATTRIBUTE_SYSTEM,
9701 struct trunc_open_results {
9704 uint32_t trunc_attr;
9705 uint32_t result_attr;
9708 static struct trunc_open_results attr_results[] = {
9709 { 0, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_ARCHIVE },
9710 { 1, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_ARCHIVE },
9711 { 2, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_READONLY, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY },
9712 { 16, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_ARCHIVE },
9713 { 17, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_ARCHIVE },
9714 { 18, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_READONLY, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY },
9715 { 51, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
9716 { 54, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
9717 { 56, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN },
9718 { 68, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
9719 { 71, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
9720 { 73, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM },
9721 { 99, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_HIDDEN,FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
9722 { 102, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
9723 { 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 },
9724 { 116, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
9725 { 119, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
9726 { 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 },
9727 { 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 },
9728 { 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 },
9729 { 227, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
9730 { 230, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
9731 { 232, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN },
9732 { 244, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
9733 { 247, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
9734 { 249, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM }
9737 static bool run_openattrtest(int dummy)
9739 static struct cli_state *cli1;
9740 const char *fname = "\\openattr.file";
9742 bool correct = True;
9744 unsigned int i, j, k, l;
9747 printf("starting open attr test\n");
9749 if (!torture_open_connection(&cli1, 0)) {
9753 smbXcli_conn_set_sockopt(cli1->conn, sockops);
9755 for (k = 0, i = 0; i < sizeof(open_attrs_table)/sizeof(uint32_t); i++) {
9756 cli_setatr(cli1, fname, 0, 0);
9757 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
9759 status = cli_ntcreate(cli1, fname, 0, FILE_WRITE_DATA,
9760 open_attrs_table[i], FILE_SHARE_NONE,
9761 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
9762 if (!NT_STATUS_IS_OK(status)) {
9763 printf("open %d (1) of %s failed (%s)\n", i, fname, nt_errstr(status));
9767 status = cli_close(cli1, fnum1);
9768 if (!NT_STATUS_IS_OK(status)) {
9769 printf("close %d (1) of %s failed (%s)\n", i, fname, nt_errstr(status));
9773 for (j = 0; j < sizeof(open_attrs_table)/sizeof(uint32_t); j++) {
9774 status = cli_ntcreate(cli1, fname, 0,
9775 FILE_READ_DATA|FILE_WRITE_DATA,
9776 open_attrs_table[j],
9777 FILE_SHARE_NONE, FILE_OVERWRITE,
9778 0, 0, &fnum1, NULL);
9779 if (!NT_STATUS_IS_OK(status)) {
9780 for (l = 0; l < sizeof(attr_results)/sizeof(struct trunc_open_results); l++) {
9781 if (attr_results[l].num == k) {
9782 printf("[%d] trunc open 0x%x -> 0x%x of %s failed - should have succeeded !(0x%x:%s)\n",
9783 k, open_attrs_table[i],
9784 open_attrs_table[j],
9785 fname, NT_STATUS_V(status), nt_errstr(status));
9790 if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
9791 printf("[%d] trunc open 0x%x -> 0x%x failed with wrong error code %s\n",
9792 k, open_attrs_table[i], open_attrs_table[j],
9797 printf("[%d] trunc open 0x%x -> 0x%x failed\n", k, open_attrs_table[i], open_attrs_table[j]);
9803 status = cli_close(cli1, fnum1);
9804 if (!NT_STATUS_IS_OK(status)) {
9805 printf("close %d (2) of %s failed (%s)\n", j, fname, nt_errstr(status));
9809 status = cli_getatr(cli1, fname, &attr, NULL, NULL);
9810 if (!NT_STATUS_IS_OK(status)) {
9811 printf("getatr(2) failed (%s)\n", nt_errstr(status));
9816 printf("[%d] getatr check [0x%x] trunc [0x%x] got attr 0x%x\n",
9817 k, open_attrs_table[i], open_attrs_table[j], attr );
9820 for (l = 0; l < sizeof(attr_results)/sizeof(struct trunc_open_results); l++) {
9821 if (attr_results[l].num == k) {
9822 if (attr != attr_results[l].result_attr ||
9823 open_attrs_table[i] != attr_results[l].init_attr ||
9824 open_attrs_table[j] != attr_results[l].trunc_attr) {
9825 printf("getatr check failed. [0x%x] trunc [0x%x] got attr 0x%x, should be 0x%x\n",
9826 open_attrs_table[i],
9827 open_attrs_table[j],
9829 attr_results[l].result_attr);
9839 cli_setatr(cli1, fname, 0, 0);
9840 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
9842 printf("open attr test %s.\n", correct ? "passed" : "failed");
9844 if (!torture_close_connection(cli1)) {
9850 static NTSTATUS list_fn(struct file_info *finfo,
9851 const char *name, void *state)
9853 int *matched = (int *)state;
9854 if (matched != NULL) {
9857 return NT_STATUS_OK;
9861 test directory listing speed
9863 static bool run_dirtest(int dummy)
9866 static struct cli_state *cli;
9868 struct timeval core_start;
9869 bool correct = True;
9872 printf("starting directory test\n");
9874 if (!torture_open_connection(&cli, 0)) {
9878 smbXcli_conn_set_sockopt(cli->conn, sockops);
9881 for (i=0;i<torture_numops;i++) {
9883 slprintf(fname, sizeof(fname), "\\%x", (int)random());
9884 if (!NT_STATUS_IS_OK(cli_openx(cli, fname, O_RDWR|O_CREAT, DENY_NONE, &fnum))) {
9885 fprintf(stderr,"Failed to open %s\n", fname);
9888 cli_close(cli, fnum);
9891 core_start = timeval_current();
9894 cli_list(cli, "a*.*", 0, list_fn, &matched);
9895 printf("Matched %d\n", matched);
9898 cli_list(cli, "b*.*", 0, list_fn, &matched);
9899 printf("Matched %d\n", matched);
9902 cli_list(cli, "xyzabc", 0, list_fn, &matched);
9903 printf("Matched %d\n", matched);
9905 printf("dirtest core %g seconds\n", timeval_elapsed(&core_start));
9908 for (i=0;i<torture_numops;i++) {
9910 slprintf(fname, sizeof(fname), "\\%x", (int)random());
9911 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
9914 if (!torture_close_connection(cli)) {
9918 printf("finished dirtest\n");
9923 static NTSTATUS del_fn(struct file_info *finfo, const char *mask,
9926 struct cli_state *pcli = (struct cli_state *)state;
9928 slprintf(fname, sizeof(fname), "\\LISTDIR\\%s", finfo->name);
9930 if (strcmp(finfo->name, ".") == 0 || strcmp(finfo->name, "..") == 0)
9931 return NT_STATUS_OK;
9933 if (finfo->attr & FILE_ATTRIBUTE_DIRECTORY) {
9934 if (!NT_STATUS_IS_OK(cli_rmdir(pcli, fname)))
9935 printf("del_fn: failed to rmdir %s\n,", fname );
9937 if (!NT_STATUS_IS_OK(cli_unlink(pcli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN)))
9938 printf("del_fn: failed to unlink %s\n,", fname );
9940 return NT_STATUS_OK;
9945 send a raw ioctl - used by the torture code
9947 static NTSTATUS cli_raw_ioctl(struct cli_state *cli,
9955 PUSH_LE_U16(vwv + 0, 0, fnum);
9956 PUSH_LE_U16(vwv + 1, 0, code >> 16);
9957 PUSH_LE_U16(vwv + 2, 0, (code & 0xFFFF));
9959 status = cli_smb(talloc_tos(),
9973 if (!NT_STATUS_IS_OK(status)) {
9976 *blob = data_blob_null;
9977 return NT_STATUS_OK;
9981 sees what IOCTLs are supported
9983 bool torture_ioctl_test(int dummy)
9985 static struct cli_state *cli;
9986 uint16_t device, function;
9988 const char *fname = "\\ioctl.dat";
9992 if (!torture_open_connection(&cli, 0)) {
9996 printf("starting ioctl test\n");
9998 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
10000 status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
10001 if (!NT_STATUS_IS_OK(status)) {
10002 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
10006 status = cli_raw_ioctl(cli, fnum, 0x2d0000 | (0x0420<<2), &blob);
10007 printf("ioctl device info: %s\n", nt_errstr(status));
10009 status = cli_raw_ioctl(cli, fnum, IOCTL_QUERY_JOB_INFO, &blob);
10010 printf("ioctl job info: %s\n", nt_errstr(status));
10012 for (device=0;device<0x100;device++) {
10013 printf("ioctl test with device = 0x%x\n", device);
10014 for (function=0;function<0x100;function++) {
10015 uint32_t code = (device<<16) | function;
10017 status = cli_raw_ioctl(cli, fnum, code, &blob);
10019 if (NT_STATUS_IS_OK(status)) {
10020 printf("ioctl 0x%x OK : %d bytes\n", (int)code,
10022 data_blob_free(&blob);
10027 if (!torture_close_connection(cli)) {
10036 tries variants of chkpath
10038 bool torture_chkpath_test(int dummy)
10040 static struct cli_state *cli;
10045 if (!torture_open_connection(&cli, 0)) {
10049 printf("starting chkpath test\n");
10051 /* cleanup from an old run */
10052 torture_deltree(cli, "\\chkpath.dir");
10054 status = cli_mkdir(cli, "\\chkpath.dir");
10055 if (!NT_STATUS_IS_OK(status)) {
10056 printf("mkdir1 failed : %s\n", nt_errstr(status));
10060 status = cli_mkdir(cli, "\\chkpath.dir\\dir2");
10061 if (!NT_STATUS_IS_OK(status)) {
10062 printf("mkdir2 failed : %s\n", nt_errstr(status));
10066 status = cli_openx(cli, "\\chkpath.dir\\foo.txt", O_RDWR|O_CREAT|O_EXCL,
10068 if (!NT_STATUS_IS_OK(status)) {
10069 printf("open1 failed (%s)\n", nt_errstr(status));
10072 cli_close(cli, fnum);
10074 status = cli_chkpath(cli, "\\chkpath.dir");
10075 if (!NT_STATUS_IS_OK(status)) {
10076 printf("chkpath1 failed: %s\n", nt_errstr(status));
10080 status = cli_chkpath(cli, "\\chkpath.dir\\dir2");
10081 if (!NT_STATUS_IS_OK(status)) {
10082 printf("chkpath2 failed: %s\n", nt_errstr(status));
10086 status = cli_chkpath(cli, "\\chkpath.dir\\foo.txt");
10087 if (!NT_STATUS_IS_OK(status)) {
10088 ret = check_error(__LINE__, status, ERRDOS, ERRbadpath,
10089 NT_STATUS_NOT_A_DIRECTORY);
10091 printf("* chkpath on a file should fail\n");
10095 status = cli_chkpath(cli, "\\chkpath.dir\\bar.txt");
10096 if (!NT_STATUS_IS_OK(status)) {
10097 ret = check_error(__LINE__, status, ERRDOS, ERRbadfile,
10098 NT_STATUS_OBJECT_NAME_NOT_FOUND);
10100 printf("* chkpath on a non existent file should fail\n");
10104 status = cli_chkpath(cli, "\\chkpath.dir\\dirxx\\bar.txt");
10105 if (!NT_STATUS_IS_OK(status)) {
10106 ret = check_error(__LINE__, status, ERRDOS, ERRbadpath,
10107 NT_STATUS_OBJECT_PATH_NOT_FOUND);
10109 printf("* chkpath on a non existent component should fail\n");
10113 torture_deltree(cli, "\\chkpath.dir");
10115 if (!torture_close_connection(cli)) {
10122 static bool run_eatest(int dummy)
10124 static struct cli_state *cli;
10125 const char *fname = "\\eatest.txt";
10126 bool correct = True;
10129 struct ea_struct *ea_list = NULL;
10130 TALLOC_CTX *mem_ctx = talloc_init("eatest");
10133 printf("starting eatest\n");
10135 if (!torture_open_connection(&cli, 0)) {
10136 talloc_destroy(mem_ctx);
10140 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
10142 status = cli_ntcreate(cli, fname, 0,
10143 FIRST_DESIRED_ACCESS, FILE_ATTRIBUTE_ARCHIVE,
10144 FILE_SHARE_NONE, FILE_OVERWRITE_IF,
10145 0x4044, 0, &fnum, NULL);
10146 if (!NT_STATUS_IS_OK(status)) {
10147 printf("open failed - %s\n", nt_errstr(status));
10148 talloc_destroy(mem_ctx);
10152 for (i = 0; i < 10; i++) {
10153 fstring ea_name, ea_val;
10155 slprintf(ea_name, sizeof(ea_name), "EA_%zu", i);
10156 memset(ea_val, (char)i+1, i+1);
10157 status = cli_set_ea_fnum(cli, fnum, ea_name, ea_val, i+1);
10158 if (!NT_STATUS_IS_OK(status)) {
10159 printf("ea_set of name %s failed - %s\n", ea_name,
10160 nt_errstr(status));
10161 talloc_destroy(mem_ctx);
10166 cli_close(cli, fnum);
10167 for (i = 0; i < 10; i++) {
10168 fstring ea_name, ea_val;
10170 slprintf(ea_name, sizeof(ea_name), "EA_%zu", i+10);
10171 memset(ea_val, (char)i+1, i+1);
10172 status = cli_set_ea_path(cli, fname, ea_name, ea_val, i+1);
10173 if (!NT_STATUS_IS_OK(status)) {
10174 printf("ea_set of name %s failed - %s\n", ea_name,
10175 nt_errstr(status));
10176 talloc_destroy(mem_ctx);
10181 status = cli_get_ea_list_path(cli, fname, mem_ctx, &num_eas, &ea_list);
10182 if (!NT_STATUS_IS_OK(status)) {
10183 printf("ea_get list failed - %s\n", nt_errstr(status));
10187 printf("num_eas = %d\n", (int)num_eas);
10189 if (num_eas != 20) {
10190 printf("Should be 20 EA's stored... failing.\n");
10194 for (i = 0; i < num_eas; i++) {
10195 printf("%zu: ea_name = %s. Val = ", i, ea_list[i].name);
10196 dump_data(0, ea_list[i].value.data,
10197 ea_list[i].value.length);
10200 /* Setting EA's to zero length deletes them. Test this */
10201 printf("Now deleting all EA's - case independent....\n");
10204 cli_set_ea_path(cli, fname, "", "", 0);
10206 for (i = 0; i < 20; i++) {
10208 slprintf(ea_name, sizeof(ea_name), "ea_%d", i);
10209 status = cli_set_ea_path(cli, fname, ea_name, "", 0);
10210 if (!NT_STATUS_IS_OK(status)) {
10211 printf("ea_set of name %s failed - %s\n", ea_name,
10212 nt_errstr(status));
10213 talloc_destroy(mem_ctx);
10219 status = cli_get_ea_list_path(cli, fname, mem_ctx, &num_eas, &ea_list);
10220 if (!NT_STATUS_IS_OK(status)) {
10221 printf("ea_get list failed - %s\n", nt_errstr(status));
10225 printf("num_eas = %d\n", (int)num_eas);
10226 for (i = 0; i < num_eas; i++) {
10227 printf("%zu: ea_name = %s. Val = ", i, ea_list[i].name);
10228 dump_data(0, ea_list[i].value.data,
10229 ea_list[i].value.length);
10232 if (num_eas != 0) {
10233 printf("deleting EA's failed.\n");
10237 /* Try and delete a non existent EA. */
10238 status = cli_set_ea_path(cli, fname, "foo", "", 0);
10239 if (!NT_STATUS_IS_OK(status)) {
10240 printf("deleting non-existent EA 'foo' should succeed. %s\n",
10241 nt_errstr(status));
10245 talloc_destroy(mem_ctx);
10246 if (!torture_close_connection(cli)) {
10253 static bool run_dirtest1(int dummy)
10256 static struct cli_state *cli;
10259 bool correct = True;
10261 printf("starting directory test\n");
10263 if (!torture_open_connection(&cli, 0)) {
10267 smbXcli_conn_set_sockopt(cli->conn, sockops);
10269 cli_list(cli, "\\LISTDIR\\*", 0, del_fn, cli);
10270 cli_list(cli, "\\LISTDIR\\*", FILE_ATTRIBUTE_DIRECTORY, del_fn, cli);
10271 cli_rmdir(cli, "\\LISTDIR");
10272 cli_mkdir(cli, "\\LISTDIR");
10274 /* Create 1000 files and 1000 directories. */
10275 for (i=0;i<1000;i++) {
10277 slprintf(fname, sizeof(fname), "\\LISTDIR\\f%d", i);
10278 if (!NT_STATUS_IS_OK(cli_ntcreate(cli, fname, 0, GENERIC_ALL_ACCESS, FILE_ATTRIBUTE_ARCHIVE,
10279 FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OVERWRITE_IF,
10280 0, 0, &fnum, NULL))) {
10281 fprintf(stderr,"Failed to open %s\n", fname);
10284 cli_close(cli, fnum);
10286 for (i=0;i<1000;i++) {
10288 slprintf(fname, sizeof(fname), "\\LISTDIR\\d%d", i);
10289 if (!NT_STATUS_IS_OK(cli_mkdir(cli, fname))) {
10290 fprintf(stderr,"Failed to open %s\n", fname);
10295 /* Now ensure that doing an old list sees both files and directories. */
10297 cli_list_old(cli, "\\LISTDIR\\*", FILE_ATTRIBUTE_DIRECTORY, list_fn, &num_seen);
10298 printf("num_seen = %d\n", num_seen );
10299 /* We should see 100 files + 1000 directories + . and .. */
10300 if (num_seen != 2002)
10303 /* Ensure if we have the "must have" bits we only see the
10304 * relevant entries.
10307 cli_list_old(cli, "\\LISTDIR\\*", (FILE_ATTRIBUTE_DIRECTORY<<8)|FILE_ATTRIBUTE_DIRECTORY, list_fn, &num_seen);
10308 printf("num_seen = %d\n", num_seen );
10309 if (num_seen != 1002)
10313 cli_list_old(cli, "\\LISTDIR\\*", (FILE_ATTRIBUTE_ARCHIVE<<8)|FILE_ATTRIBUTE_DIRECTORY, list_fn, &num_seen);
10314 printf("num_seen = %d\n", num_seen );
10315 if (num_seen != 1000)
10318 /* Delete everything. */
10319 cli_list(cli, "\\LISTDIR\\*", 0, del_fn, cli);
10320 cli_list(cli, "\\LISTDIR\\*", FILE_ATTRIBUTE_DIRECTORY, del_fn, cli);
10321 cli_rmdir(cli, "\\LISTDIR");
10324 printf("Matched %d\n", cli_list(cli, "a*.*", 0, list_fn, NULL));
10325 printf("Matched %d\n", cli_list(cli, "b*.*", 0, list_fn, NULL));
10326 printf("Matched %d\n", cli_list(cli, "xyzabc", 0, list_fn, NULL));
10329 if (!torture_close_connection(cli)) {
10333 printf("finished dirtest1\n");
10338 static bool run_error_map_extract(int dummy) {
10340 static struct cli_state *c_dos;
10341 static struct cli_state *c_nt;
10349 NTSTATUS nt_status;
10353 /* NT-Error connection */
10355 disable_spnego = true;
10356 if (!(c_nt = open_nbt_connection())) {
10357 disable_spnego = false;
10360 disable_spnego = false;
10362 status = smbXcli_negprot(c_nt->conn,
10370 if (!NT_STATUS_IS_OK(status)) {
10371 printf("%s rejected the NT-error negprot (%s)\n", host,
10372 nt_errstr(status));
10373 cli_shutdown(c_nt);
10377 status = cli_session_setup_anon(c_nt);
10378 if (!NT_STATUS_IS_OK(status)) {
10379 printf("%s rejected the NT-error initial session setup (%s)\n",host, nt_errstr(status));
10383 /* DOS-Error connection */
10385 disable_spnego = true;
10386 force_dos_errors = true;
10387 if (!(c_dos = open_nbt_connection())) {
10388 disable_spnego = false;
10389 force_dos_errors = false;
10392 disable_spnego = false;
10393 force_dos_errors = false;
10395 status = smbXcli_negprot(c_dos->conn,
10402 if (!NT_STATUS_IS_OK(status)) {
10403 printf("%s rejected the DOS-error negprot (%s)\n", host,
10404 nt_errstr(status));
10405 cli_shutdown(c_dos);
10409 status = cli_session_setup_anon(c_dos);
10410 if (!NT_STATUS_IS_OK(status)) {
10411 printf("%s rejected the DOS-error initial session setup (%s)\n",
10412 host, nt_errstr(status));
10416 c_nt->map_dos_errors = false;
10417 c_dos->map_dos_errors = false;
10419 for (error=(0xc0000000 | 0x1); error < (0xc0000000| 0xFFF); error++) {
10420 struct cli_credentials *user_creds = NULL;
10422 fstr_sprintf(user, "%X", error);
10424 user_creds = cli_session_creds_init(talloc_tos(),
10429 false, /* use_kerberos */
10430 false, /* fallback_after_kerberos */
10431 false, /* use_ccache */
10432 false); /* password_is_nt_hash */
10433 if (user_creds == NULL) {
10434 printf("cli_session_creds_init(%s) failed\n", user);
10438 status = cli_session_setup_creds(c_nt, user_creds);
10439 if (NT_STATUS_IS_OK(status)) {
10440 printf("/** Session setup succeeded. This shouldn't happen...*/\n");
10443 /* Case #1: 32-bit NT errors */
10444 if (!NT_STATUS_IS_DOS(status)) {
10445 nt_status = status;
10447 printf("/** Dos error on NT connection! (%s) */\n",
10448 nt_errstr(status));
10449 nt_status = NT_STATUS(0xc0000000);
10452 status = cli_session_setup_creds(c_dos, user_creds);
10453 if (NT_STATUS_IS_OK(status)) {
10454 printf("/** Session setup succeeded. This shouldn't happen...*/\n");
10457 /* Case #1: 32-bit NT errors */
10458 if (NT_STATUS_IS_DOS(status)) {
10459 printf("/** NT error on DOS connection! (%s) */\n",
10460 nt_errstr(status));
10461 errnum = errclass = 0;
10463 errclass = NT_STATUS_DOS_CLASS(status);
10464 errnum = NT_STATUS_DOS_CODE(status);
10467 if (NT_STATUS_V(nt_status) != error) {
10468 printf("/*\t{ This NT error code was 'sqashed'\n\t from %s to %s \n\t during the session setup }\n*/\n",
10469 get_nt_error_c_code(talloc_tos(), NT_STATUS(error)),
10470 get_nt_error_c_code(talloc_tos(), nt_status));
10473 printf("\t{%s,\t%s,\t%s},\n",
10474 smb_dos_err_class(errclass),
10475 smb_dos_err_name(errclass, errnum),
10476 get_nt_error_c_code(talloc_tos(), NT_STATUS(error)));
10478 TALLOC_FREE(user_creds);
10483 static bool run_sesssetup_bench(int dummy)
10485 static struct cli_state *c;
10486 const char *fname = "\\file.dat";
10491 if (!torture_open_connection(&c, 0)) {
10495 status = cli_ntcreate(c, fname, 0, GENERIC_ALL_ACCESS|DELETE_ACCESS,
10496 FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
10497 FILE_DELETE_ON_CLOSE, 0, &fnum, NULL);
10498 if (!NT_STATUS_IS_OK(status)) {
10499 d_printf("open %s failed: %s\n", fname, nt_errstr(status));
10503 for (i=0; i<torture_numops; i++) {
10504 status = cli_session_setup_creds(c, torture_creds);
10505 if (!NT_STATUS_IS_OK(status)) {
10506 d_printf("(%s) cli_session_setup_creds failed: %s\n",
10507 __location__, nt_errstr(status));
10511 d_printf("\r%d ", (int)cli_state_get_uid(c));
10513 status = cli_ulogoff(c);
10514 if (!NT_STATUS_IS_OK(status)) {
10515 d_printf("(%s) cli_ulogoff failed: %s\n",
10516 __location__, nt_errstr(status));
10524 static bool subst_test(const char *str, const char *user, const char *domain,
10525 uid_t uid, gid_t gid, const char *expected)
10528 bool result = true;
10530 subst = talloc_sub_specified(talloc_tos(), str, user, NULL, domain, uid, gid);
10532 if (strcmp(subst, expected) != 0) {
10533 printf("sub_specified(%s, %s, %s, %d, %d) returned [%s], expected "
10534 "[%s]\n", str, user, domain, (int)uid, (int)gid, subst,
10539 TALLOC_FREE(subst);
10543 static void chain1_open_completion(struct tevent_req *req)
10547 status = cli_openx_recv(req, &fnum);
10550 d_printf("cli_openx_recv returned %s: %d\n",
10552 NT_STATUS_IS_OK(status) ? fnum : -1);
10555 static void chain1_write_completion(struct tevent_req *req)
10559 status = cli_write_andx_recv(req, &written);
10562 d_printf("cli_write_andx_recv returned %s: %d\n",
10564 NT_STATUS_IS_OK(status) ? (int)written : -1);
10567 static void chain1_close_completion(struct tevent_req *req)
10570 bool *done = (bool *)tevent_req_callback_data_void(req);
10572 status = cli_close_recv(req);
10577 d_printf("cli_close returned %s\n", nt_errstr(status));
10580 static bool run_chain1(int dummy)
10582 struct cli_state *cli1;
10583 struct tevent_context *evt = samba_tevent_context_init(NULL);
10584 struct tevent_req *reqs[3], *smbreqs[3];
10586 const char *str = "foobar";
10587 const char *fname = "\\test_chain";
10590 printf("starting chain1 test\n");
10591 if (!torture_open_connection(&cli1, 0)) {
10595 smbXcli_conn_set_sockopt(cli1->conn, sockops);
10597 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
10599 reqs[0] = cli_openx_create(talloc_tos(), evt, cli1, fname,
10600 O_CREAT|O_RDWR, 0, &smbreqs[0]);
10601 if (reqs[0] == NULL) return false;
10602 tevent_req_set_callback(reqs[0], chain1_open_completion, NULL);
10605 reqs[1] = cli_write_andx_create(talloc_tos(), evt, cli1, 0, 0,
10606 (const uint8_t *)str, 0, strlen(str)+1,
10607 smbreqs, 1, &smbreqs[1]);
10608 if (reqs[1] == NULL) return false;
10609 tevent_req_set_callback(reqs[1], chain1_write_completion, NULL);
10611 reqs[2] = cli_smb1_close_create(talloc_tos(), evt, cli1, 0, &smbreqs[2]);
10612 if (reqs[2] == NULL) return false;
10613 tevent_req_set_callback(reqs[2], chain1_close_completion, &done);
10615 status = smb1cli_req_chain_submit(smbreqs, ARRAY_SIZE(smbreqs));
10616 if (!NT_STATUS_IS_OK(status)) {
10621 tevent_loop_once(evt);
10624 torture_close_connection(cli1);
10628 static void chain2_sesssetup_completion(struct tevent_req *req)
10631 status = cli_session_setup_guest_recv(req);
10632 d_printf("sesssetup returned %s\n", nt_errstr(status));
10635 static void chain2_tcon_completion(struct tevent_req *req)
10637 bool *done = (bool *)tevent_req_callback_data_void(req);
10639 status = cli_tcon_andx_recv(req);
10640 d_printf("tcon_and_x returned %s\n", nt_errstr(status));
10644 static bool run_chain2(int dummy)
10646 struct cli_state *cli1;
10647 struct tevent_context *evt = samba_tevent_context_init(NULL);
10648 struct tevent_req *reqs[2], *smbreqs[2];
10651 int flags = CLI_FULL_CONNECTION_FORCE_SMB1;
10653 printf("starting chain2 test\n");
10654 status = cli_start_connection(talloc_tos(),
10660 SMB_SIGNING_DEFAULT,
10662 if (!NT_STATUS_IS_OK(status)) {
10666 smbXcli_conn_set_sockopt(cli1->conn, sockops);
10668 reqs[0] = cli_session_setup_guest_create(talloc_tos(), evt, cli1,
10670 if (reqs[0] == NULL) return false;
10671 tevent_req_set_callback(reqs[0], chain2_sesssetup_completion, NULL);
10673 reqs[1] = cli_tcon_andx_create(talloc_tos(), evt, cli1, "IPC$",
10674 "?????", NULL, 0, &smbreqs[1]);
10675 if (reqs[1] == NULL) return false;
10676 tevent_req_set_callback(reqs[1], chain2_tcon_completion, &done);
10678 status = smb1cli_req_chain_submit(smbreqs, ARRAY_SIZE(smbreqs));
10679 if (!NT_STATUS_IS_OK(status)) {
10684 tevent_loop_once(evt);
10687 torture_close_connection(cli1);
10692 struct torture_createdel_state {
10693 struct tevent_context *ev;
10694 struct cli_state *cli;
10697 static void torture_createdel_created(struct tevent_req *subreq);
10698 static void torture_createdel_closed(struct tevent_req *subreq);
10700 static struct tevent_req *torture_createdel_send(TALLOC_CTX *mem_ctx,
10701 struct tevent_context *ev,
10702 struct cli_state *cli,
10705 struct tevent_req *req, *subreq;
10706 struct torture_createdel_state *state;
10708 req = tevent_req_create(mem_ctx, &state,
10709 struct torture_createdel_state);
10716 subreq = cli_ntcreate_send(
10717 state, ev, cli, name, 0,
10718 FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
10719 FILE_ATTRIBUTE_NORMAL,
10720 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
10721 FILE_OPEN_IF, FILE_DELETE_ON_CLOSE,
10722 SMB2_IMPERSONATION_IMPERSONATION, 0);
10724 if (tevent_req_nomem(subreq, req)) {
10725 return tevent_req_post(req, ev);
10727 tevent_req_set_callback(subreq, torture_createdel_created, req);
10731 static void torture_createdel_created(struct tevent_req *subreq)
10733 struct tevent_req *req = tevent_req_callback_data(
10734 subreq, struct tevent_req);
10735 struct torture_createdel_state *state = tevent_req_data(
10736 req, struct torture_createdel_state);
10740 status = cli_ntcreate_recv(subreq, &fnum, NULL);
10741 TALLOC_FREE(subreq);
10742 if (tevent_req_nterror(req, status)) {
10743 DEBUG(10, ("cli_ntcreate_recv returned %s\n",
10744 nt_errstr(status)));
10748 subreq = cli_close_send(state, state->ev, state->cli, fnum, 0);
10749 if (tevent_req_nomem(subreq, req)) {
10752 tevent_req_set_callback(subreq, torture_createdel_closed, req);
10755 static void torture_createdel_closed(struct tevent_req *subreq)
10757 struct tevent_req *req = tevent_req_callback_data(
10758 subreq, struct tevent_req);
10761 status = cli_close_recv(subreq);
10762 if (tevent_req_nterror(req, status)) {
10763 DEBUG(10, ("cli_close_recv returned %s\n", nt_errstr(status)));
10766 tevent_req_done(req);
10769 static NTSTATUS torture_createdel_recv(struct tevent_req *req)
10771 return tevent_req_simple_recv_ntstatus(req);
10774 struct torture_createdels_state {
10775 struct tevent_context *ev;
10776 struct cli_state *cli;
10777 const char *base_name;
10781 struct tevent_req **reqs;
10784 static void torture_createdels_done(struct tevent_req *subreq);
10786 static struct tevent_req *torture_createdels_send(TALLOC_CTX *mem_ctx,
10787 struct tevent_context *ev,
10788 struct cli_state *cli,
10789 const char *base_name,
10793 struct tevent_req *req;
10794 struct torture_createdels_state *state;
10797 req = tevent_req_create(mem_ctx, &state,
10798 struct torture_createdels_state);
10804 state->base_name = talloc_strdup(state, base_name);
10805 if (tevent_req_nomem(state->base_name, req)) {
10806 return tevent_req_post(req, ev);
10808 state->num_files = MAX(num_parallel, num_files);
10810 state->received = 0;
10812 state->reqs = talloc_array(state, struct tevent_req *, num_parallel);
10813 if (tevent_req_nomem(state->reqs, req)) {
10814 return tevent_req_post(req, ev);
10817 for (i=0; i<num_parallel; i++) {
10820 name = talloc_asprintf(state, "%s%8.8d", state->base_name,
10822 if (tevent_req_nomem(name, req)) {
10823 return tevent_req_post(req, ev);
10825 state->reqs[i] = torture_createdel_send(
10826 state->reqs, state->ev, state->cli, name);
10827 if (tevent_req_nomem(state->reqs[i], req)) {
10828 return tevent_req_post(req, ev);
10830 name = talloc_move(state->reqs[i], &name);
10831 tevent_req_set_callback(state->reqs[i],
10832 torture_createdels_done, req);
10838 static void torture_createdels_done(struct tevent_req *subreq)
10840 struct tevent_req *req = tevent_req_callback_data(
10841 subreq, struct tevent_req);
10842 struct torture_createdels_state *state = tevent_req_data(
10843 req, struct torture_createdels_state);
10844 size_t i, num_parallel = talloc_array_length(state->reqs);
10848 status = torture_createdel_recv(subreq);
10849 if (!NT_STATUS_IS_OK(status)){
10850 DEBUG(10, ("torture_createdel_recv returned %s\n",
10851 nt_errstr(status)));
10852 TALLOC_FREE(subreq);
10853 tevent_req_nterror(req, status);
10857 for (i=0; i<num_parallel; i++) {
10858 if (subreq == state->reqs[i]) {
10862 if (i == num_parallel) {
10863 DEBUG(10, ("received something we did not send\n"));
10864 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
10867 TALLOC_FREE(state->reqs[i]);
10869 if (state->sent >= state->num_files) {
10870 tevent_req_done(req);
10874 name = talloc_asprintf(state, "%s%8.8d", state->base_name,
10876 if (tevent_req_nomem(name, req)) {
10879 state->reqs[i] = torture_createdel_send(state->reqs, state->ev,
10881 if (tevent_req_nomem(state->reqs[i], req)) {
10884 name = talloc_move(state->reqs[i], &name);
10885 tevent_req_set_callback(state->reqs[i], torture_createdels_done, req);
10889 static NTSTATUS torture_createdels_recv(struct tevent_req *req)
10891 return tevent_req_simple_recv_ntstatus(req);
10894 struct swallow_notify_state {
10895 struct tevent_context *ev;
10896 struct cli_state *cli;
10898 uint32_t completion_filter;
10900 bool (*fn)(uint32_t action, const char *name, void *priv);
10904 static void swallow_notify_done(struct tevent_req *subreq);
10906 static struct tevent_req *swallow_notify_send(TALLOC_CTX *mem_ctx,
10907 struct tevent_context *ev,
10908 struct cli_state *cli,
10910 uint32_t completion_filter,
10912 bool (*fn)(uint32_t action,
10917 struct tevent_req *req, *subreq;
10918 struct swallow_notify_state *state;
10920 req = tevent_req_create(mem_ctx, &state,
10921 struct swallow_notify_state);
10927 state->fnum = fnum;
10928 state->completion_filter = completion_filter;
10929 state->recursive = recursive;
10931 state->priv = priv;
10933 subreq = cli_notify_send(state, state->ev, state->cli, state->fnum,
10934 0xffff, state->completion_filter,
10936 if (tevent_req_nomem(subreq, req)) {
10937 return tevent_req_post(req, ev);
10939 tevent_req_set_callback(subreq, swallow_notify_done, req);
10943 static void swallow_notify_done(struct tevent_req *subreq)
10945 struct tevent_req *req = tevent_req_callback_data(
10946 subreq, struct tevent_req);
10947 struct swallow_notify_state *state = tevent_req_data(
10948 req, struct swallow_notify_state);
10950 uint32_t i, num_changes;
10951 struct notify_change *changes;
10953 status = cli_notify_recv(subreq, state, &num_changes, &changes);
10954 TALLOC_FREE(subreq);
10955 if (!NT_STATUS_IS_OK(status)) {
10956 DEBUG(10, ("cli_notify_recv returned %s\n",
10957 nt_errstr(status)));
10958 tevent_req_nterror(req, status);
10962 for (i=0; i<num_changes; i++) {
10963 state->fn(changes[i].action, changes[i].name, state->priv);
10965 TALLOC_FREE(changes);
10967 subreq = cli_notify_send(state, state->ev, state->cli, state->fnum,
10968 0xffff, state->completion_filter,
10970 if (tevent_req_nomem(subreq, req)) {
10973 tevent_req_set_callback(subreq, swallow_notify_done, req);
10976 static bool print_notifies(uint32_t action, const char *name, void *priv)
10978 if (DEBUGLEVEL > 5) {
10979 d_printf("%d %s\n", (int)action, name);
10984 static void notify_bench_done(struct tevent_req *req)
10986 int *num_finished = (int *)tevent_req_callback_data_void(req);
10987 *num_finished += 1;
10990 static bool run_notify_bench(int dummy)
10992 const char *dname = "\\notify-bench";
10993 struct tevent_context *ev;
10996 struct tevent_req *req1;
10997 struct tevent_req *req2 = NULL;
10998 int i, num_unc_names;
10999 int num_finished = 0;
11001 printf("starting notify-bench test\n");
11003 if (use_multishare_conn) {
11005 unc_list = file_lines_load(multishare_conn_fname,
11006 &num_unc_names, 0, NULL);
11007 if (!unc_list || num_unc_names <= 0) {
11008 d_printf("Failed to load unc names list from '%s'\n",
11009 multishare_conn_fname);
11012 TALLOC_FREE(unc_list);
11017 ev = samba_tevent_context_init(talloc_tos());
11019 d_printf("tevent_context_init failed\n");
11023 for (i=0; i<num_unc_names; i++) {
11024 struct cli_state *cli;
11027 base_fname = talloc_asprintf(talloc_tos(), "%s\\file%3.3d.",
11029 if (base_fname == NULL) {
11033 if (!torture_open_connection(&cli, i)) {
11037 status = cli_ntcreate(cli, dname, 0,
11038 MAXIMUM_ALLOWED_ACCESS,
11039 0, FILE_SHARE_READ|FILE_SHARE_WRITE|
11041 FILE_OPEN_IF, FILE_DIRECTORY_FILE, 0,
11044 if (!NT_STATUS_IS_OK(status)) {
11045 d_printf("Could not create %s: %s\n", dname,
11046 nt_errstr(status));
11050 req1 = swallow_notify_send(talloc_tos(), ev, cli, dnum,
11051 FILE_NOTIFY_CHANGE_FILE_NAME |
11052 FILE_NOTIFY_CHANGE_DIR_NAME |
11053 FILE_NOTIFY_CHANGE_ATTRIBUTES |
11054 FILE_NOTIFY_CHANGE_LAST_WRITE,
11055 false, print_notifies, NULL);
11056 if (req1 == NULL) {
11057 d_printf("Could not create notify request\n");
11061 req2 = torture_createdels_send(talloc_tos(), ev, cli,
11062 base_fname, 10, torture_numops);
11063 if (req2 == NULL) {
11064 d_printf("Could not create createdels request\n");
11067 TALLOC_FREE(base_fname);
11069 tevent_req_set_callback(req2, notify_bench_done,
11073 while (num_finished < num_unc_names) {
11075 ret = tevent_loop_once(ev);
11077 d_printf("tevent_loop_once failed\n");
11082 if (!tevent_req_poll(req2, ev)) {
11083 d_printf("tevent_req_poll failed\n");
11086 status = torture_createdels_recv(req2);
11087 d_printf("torture_createdels_recv returned %s\n", nt_errstr(status));
11092 static bool run_mangle1(int dummy)
11094 struct cli_state *cli;
11095 const char *fname = "this_is_a_long_fname_to_be_mangled.txt";
11100 printf("starting mangle1 test\n");
11101 if (!torture_open_connection(&cli, 0)) {
11105 smbXcli_conn_set_sockopt(cli->conn, sockops);
11107 status = cli_ntcreate(cli, fname, 0, GENERIC_ALL_ACCESS|DELETE_ACCESS,
11108 FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
11109 0, 0, &fnum, NULL);
11110 if (!NT_STATUS_IS_OK(status)) {
11111 d_printf("open %s failed: %s\n", fname, nt_errstr(status));
11114 cli_close(cli, fnum);
11116 status = cli_qpathinfo_alt_name(cli, fname, alt_name);
11117 if (!NT_STATUS_IS_OK(status)) {
11118 d_printf("cli_qpathinfo_alt_name failed: %s\n",
11119 nt_errstr(status));
11122 d_printf("alt_name: %s\n", alt_name);
11124 status = cli_openx(cli, alt_name, O_RDONLY, DENY_NONE, &fnum);
11125 if (!NT_STATUS_IS_OK(status)) {
11126 d_printf("cli_openx(%s) failed: %s\n", alt_name,
11127 nt_errstr(status));
11130 cli_close(cli, fnum);
11132 status = cli_qpathinfo1(cli, alt_name, NULL, NULL, NULL, NULL, NULL);
11133 if (!NT_STATUS_IS_OK(status)) {
11134 d_printf("cli_qpathinfo1(%s) failed: %s\n", alt_name,
11135 nt_errstr(status));
11142 static NTSTATUS mangle_illegal_list_shortname_fn(struct file_info *f,
11146 if (f->short_name == NULL) {
11147 return NT_STATUS_OK;
11150 if (strlen(f->short_name) == 0) {
11151 return NT_STATUS_OK;
11154 printf("unexpected shortname: %s\n", f->short_name);
11156 return NT_STATUS_OBJECT_NAME_INVALID;
11159 static NTSTATUS mangle_illegal_list_name_fn(struct file_info *f,
11163 char *name = state;
11165 printf("name: %s\n", f->name);
11166 fstrcpy(name, f->name);
11167 return NT_STATUS_OK;
11170 static bool run_mangle_illegal(int dummy)
11172 struct cli_state *cli = NULL;
11173 struct cli_state *cli_posix = NULL;
11174 const char *fname = "\\MANGLE_ILLEGAL\\this_is_a_long_fname_to_be_mangled.txt";
11175 const char *illegal_fname = "MANGLE_ILLEGAL/foo:bar";
11176 char *mangled_path = NULL;
11182 printf("starting mangle-illegal test\n");
11184 if (!torture_open_connection(&cli, 0)) {
11188 smbXcli_conn_set_sockopt(cli->conn, sockops);
11190 if (!torture_open_connection(&cli_posix, 0)) {
11194 smbXcli_conn_set_sockopt(cli_posix->conn, sockops);
11196 status = torture_setup_unix_extensions(cli_posix);
11197 if (!NT_STATUS_IS_OK(status)) {
11201 cli_rmdir(cli, "\\MANGLE_ILLEGAL");
11202 status = cli_mkdir(cli, "\\MANGLE_ILLEGAL");
11203 if (!NT_STATUS_IS_OK(status)) {
11204 printf("mkdir1 failed : %s\n", nt_errstr(status));
11209 * Create a file with illegal NTFS characters and test that we
11210 * get a usable mangled name
11213 cli_setatr(cli_posix, illegal_fname, 0, 0);
11214 cli_posix_unlink(cli_posix, illegal_fname);
11216 status = cli_posix_open(cli_posix, illegal_fname, O_RDWR|O_CREAT|O_EXCL,
11218 if (!NT_STATUS_IS_OK(status)) {
11219 printf("POSIX create of %s failed (%s)\n",
11220 illegal_fname, nt_errstr(status));
11224 status = cli_close(cli_posix, fnum);
11225 if (!NT_STATUS_IS_OK(status)) {
11226 printf("close failed (%s)\n", nt_errstr(status));
11230 status = cli_list(cli, "\\MANGLE_ILLEGAL\\*", 0, mangle_illegal_list_name_fn, &name);
11231 if (!NT_STATUS_IS_OK(status)) {
11232 d_printf("cli_list failed: %s\n", nt_errstr(status));
11236 mangled_path = talloc_asprintf(talloc_tos(), "\\MANGLE_ILLEGAL\\%s", name);
11237 if (mangled_path == NULL) {
11241 status = cli_openx(cli, mangled_path, O_RDONLY, DENY_NONE, &fnum);
11242 if (!NT_STATUS_IS_OK(status)) {
11243 d_printf("cli_openx(%s) failed: %s\n", mangled_path, nt_errstr(status));
11244 TALLOC_FREE(mangled_path);
11247 TALLOC_FREE(mangled_path);
11248 cli_close(cli, fnum);
11250 cli_setatr(cli_posix, illegal_fname, 0, 0);
11251 cli_posix_unlink(cli_posix, illegal_fname);
11254 * Create a file with a long name and check that we got *no* short name.
11257 status = cli_ntcreate(cli, fname, 0, GENERIC_ALL_ACCESS|DELETE_ACCESS,
11258 FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
11259 0, 0, &fnum, NULL);
11260 if (!NT_STATUS_IS_OK(status)) {
11261 d_printf("open %s failed: %s\n", fname, nt_errstr(status));
11264 cli_close(cli, fnum);
11266 status = cli_list(cli, fname, 0, mangle_illegal_list_shortname_fn, &alt_name);
11267 if (!NT_STATUS_IS_OK(status)) {
11268 d_printf("cli_list failed\n");
11272 cli_unlink(cli, fname, 0);
11273 cli_rmdir(cli, "\\MANGLE_ILLEGAL");
11275 if (!torture_close_connection(cli_posix)) {
11279 if (!torture_close_connection(cli)) {
11286 static size_t null_source(uint8_t *buf, size_t n, void *priv)
11288 size_t *to_pull = (size_t *)priv;
11289 size_t thistime = *to_pull;
11291 thistime = MIN(thistime, n);
11292 if (thistime == 0) {
11296 memset(buf, 0, thistime);
11297 *to_pull -= thistime;
11301 static bool run_windows_write(int dummy)
11303 struct cli_state *cli1;
11307 const char *fname = "\\writetest.txt";
11308 struct timeval start_time;
11313 printf("starting windows_write test\n");
11314 if (!torture_open_connection(&cli1, 0)) {
11318 status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
11319 if (!NT_STATUS_IS_OK(status)) {
11320 printf("open failed (%s)\n", nt_errstr(status));
11324 smbXcli_conn_set_sockopt(cli1->conn, sockops);
11326 start_time = timeval_current();
11328 for (i=0; i<torture_numops; i++) {
11330 off_t start = i * torture_blocksize;
11331 size_t to_pull = torture_blocksize - 1;
11333 status = cli_writeall(cli1, fnum, 0, &c,
11334 start + torture_blocksize - 1, 1, NULL);
11335 if (!NT_STATUS_IS_OK(status)) {
11336 printf("cli_write failed: %s\n", nt_errstr(status));
11340 status = cli_push(cli1, fnum, 0, i * torture_blocksize, torture_blocksize,
11341 null_source, &to_pull);
11342 if (!NT_STATUS_IS_OK(status)) {
11343 printf("cli_push returned: %s\n", nt_errstr(status));
11348 seconds = timeval_elapsed(&start_time);
11349 kbytes = (double)torture_blocksize * torture_numops;
11352 printf("Wrote %d kbytes in %.2f seconds: %d kb/sec\n", (int)kbytes,
11353 (double)seconds, (int)(kbytes/seconds));
11357 cli_close(cli1, fnum);
11358 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
11359 torture_close_connection(cli1);
11363 static size_t calc_expected_return(struct cli_state *cli, size_t len_requested)
11365 size_t max_pdu = 0x1FFFF;
11367 if (cli->server_posix_capabilities & CIFS_UNIX_LARGE_READ_CAP) {
11368 max_pdu = 0xFFFFFF;
11371 if (smb1cli_conn_signing_is_active(cli->conn)) {
11375 if (smb1cli_conn_encryption_on(cli->conn)) {
11376 max_pdu = CLI_BUFFER_SIZE;
11379 if ((len_requested & 0xFFFF0000) == 0xFFFF0000) {
11380 len_requested &= 0xFFFF;
11383 return MIN(len_requested,
11384 max_pdu - (MIN_SMB_SIZE + VWV(12) + 1 /* padding byte */));
11387 static bool check_read_call(struct cli_state *cli,
11390 size_t len_requested)
11393 struct tevent_req *subreq = NULL;
11394 ssize_t len_read = 0;
11395 size_t len_expected = 0;
11396 struct tevent_context *ev = NULL;
11398 ev = samba_tevent_context_init(talloc_tos());
11403 subreq = cli_read_andx_send(talloc_tos(),
11410 if (!tevent_req_poll_ntstatus(subreq, ev, &status)) {
11414 status = cli_read_andx_recv(subreq, &len_read, &buf);
11415 if (!NT_STATUS_IS_OK(status)) {
11416 d_printf("cli_read_andx_recv failed: %s\n", nt_errstr(status));
11420 TALLOC_FREE(subreq);
11423 len_expected = calc_expected_return(cli, len_requested);
11425 if (len_expected > 0x10000 && len_read == 0x10000) {
11426 /* Windows servers only return a max of 0x10000,
11427 doesn't matter if you set CAP_LARGE_READX in
11428 the client sessionsetupX call or not. */
11429 d_printf("Windows server - returned 0x10000 on a read of 0x%x\n",
11430 (unsigned int)len_requested);
11431 } else if (len_read != len_expected) {
11432 d_printf("read of 0x%x failed: got 0x%x, expected 0x%x\n",
11433 (unsigned int)len_requested,
11434 (unsigned int)len_read,
11435 (unsigned int)len_expected);
11438 d_printf("Correct read reply.\n");
11444 /* Test large readX variants. */
11445 static bool large_readx_tests(struct cli_state *cli,
11449 /* A read of 0xFFFF0001 should *always* return 1 byte. */
11450 if (check_read_call(cli, fnum, buf, 0xFFFF0001) == false) {
11453 /* A read of 0x10000 should return 0x10000 bytes. */
11454 if (check_read_call(cli, fnum, buf, 0x10000) == false) {
11457 /* A read of 0x10000 should return 0x10001 bytes. */
11458 if (check_read_call(cli, fnum, buf, 0x10001) == false) {
11461 /* A read of 0x1FFFF - (MIN_SMB_SIZE + VWV(12) should return
11462 the requested number of bytes. */
11463 if (check_read_call(cli, fnum, buf, 0x1FFFF - (MIN_SMB_SIZE + VWV(12))) == false) {
11466 /* A read of 1MB should return 1MB bytes (on Samba). */
11467 if (check_read_call(cli, fnum, buf, 0x100000) == false) {
11471 if (check_read_call(cli, fnum, buf, 0x20001) == false) {
11474 if (check_read_call(cli, fnum, buf, 0x22000001) == false) {
11477 if (check_read_call(cli, fnum, buf, 0xFFFE0001) == false) {
11483 static bool run_large_readx(int dummy)
11485 uint8_t *buf = NULL;
11486 struct cli_state *cli1 = NULL;
11487 struct cli_state *cli2 = NULL;
11488 bool correct = false;
11489 const char *fname = "\\large_readx.dat";
11491 uint16_t fnum1 = UINT16_MAX;
11492 uint32_t normal_caps = 0;
11493 size_t file_size = 20*1024*1024;
11494 TALLOC_CTX *frame = talloc_stackframe();
11498 enum smb_signing_setting signing_setting;
11499 enum protocol_types protocol;
11503 .signing_setting = SMB_SIGNING_IF_REQUIRED,
11504 .protocol = PROTOCOL_NT1,
11506 .name = "NT1 - SIGNING_REQUIRED",
11507 .signing_setting = SMB_SIGNING_REQUIRED,
11508 .protocol = PROTOCOL_NT1,
11512 printf("starting large_readx test\n");
11514 if (!torture_open_connection(&cli1, 0)) {
11518 normal_caps = smb1cli_conn_capabilities(cli1->conn);
11520 if (!(normal_caps & CAP_LARGE_READX)) {
11521 d_printf("Server doesn't have CAP_LARGE_READX 0x%x\n",
11522 (unsigned int)normal_caps);
11526 /* Create a file of size 4MB. */
11527 status = cli_ntcreate(cli1, fname, 0, GENERIC_ALL_ACCESS,
11528 FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
11529 0, 0, &fnum1, NULL);
11531 if (!NT_STATUS_IS_OK(status)) {
11532 d_printf("open %s failed: %s\n", fname, nt_errstr(status));
11536 /* Write file_size bytes. */
11537 buf = talloc_zero_array(frame, uint8_t, file_size);
11542 status = cli_writeall(cli1,
11549 if (!NT_STATUS_IS_OK(status)) {
11550 d_printf("cli_writeall failed: %s\n", nt_errstr(status));
11554 status = cli_close(cli1, fnum1);
11555 if (!NT_STATUS_IS_OK(status)) {
11556 d_printf("cli_close failed: %s\n", nt_errstr(status));
11560 fnum1 = UINT16_MAX;
11562 for (i=0; i < ARRAY_SIZE(runs); i++) {
11563 enum smb_signing_setting saved_signing_setting = signing_state;
11564 uint16_t fnum2 = -1;
11567 (runs[i].signing_setting == SMB_SIGNING_REQUIRED))
11569 d_printf("skip[%u] - %s\n", (unsigned)i, runs[i].name);
11573 d_printf("run[%u] - %s\n", (unsigned)i, runs[i].name);
11575 signing_state = runs[i].signing_setting;
11576 cli2 = open_nbt_connection();
11577 signing_state = saved_signing_setting;
11578 if (cli2 == NULL) {
11582 status = smbXcli_negprot(cli2->conn,
11589 if (!NT_STATUS_IS_OK(status)) {
11593 status = cli_session_setup_creds(cli2, torture_creds);
11594 if (!NT_STATUS_IS_OK(status)) {
11598 status = cli_tree_connect(cli2,
11602 if (!NT_STATUS_IS_OK(status)) {
11606 cli_set_timeout(cli2, 120000); /* set a really long timeout (2 minutes) */
11608 normal_caps = smb1cli_conn_capabilities(cli2->conn);
11610 if (!(normal_caps & CAP_LARGE_READX)) {
11611 d_printf("Server doesn't have CAP_LARGE_READX 0x%x\n",
11612 (unsigned int)normal_caps);
11617 if (force_cli_encryption(cli2, share) == false) {
11620 } else if (SERVER_HAS_UNIX_CIFS(cli2)) {
11621 uint16_t major, minor;
11622 uint32_t caplow, caphigh;
11624 status = cli_unix_extensions_version(cli2,
11626 &caplow, &caphigh);
11627 if (!NT_STATUS_IS_OK(status)) {
11632 status = cli_ntcreate(cli2, fname, 0, FILE_READ_DATA,
11633 FILE_ATTRIBUTE_NORMAL, 0, FILE_OPEN,
11634 0, 0, &fnum2, NULL);
11635 if (!NT_STATUS_IS_OK(status)) {
11636 d_printf("Second open %s failed: %s\n", fname, nt_errstr(status));
11640 /* All reads must return less than file_size bytes. */
11641 if (!large_readx_tests(cli2, fnum2, buf)) {
11645 status = cli_close(cli2, fnum2);
11646 if (!NT_STATUS_IS_OK(status)) {
11647 d_printf("cli_close failed: %s\n", nt_errstr(status));
11652 if (!torture_close_connection(cli2)) {
11659 printf("Success on large_readx test\n");
11664 if (!torture_close_connection(cli2)) {
11670 if (fnum1 != UINT16_MAX) {
11671 status = cli_close(cli1, fnum1);
11672 if (!NT_STATUS_IS_OK(status)) {
11673 d_printf("cli_close failed: %s\n", nt_errstr(status));
11675 fnum1 = UINT16_MAX;
11678 status = cli_unlink(cli1, fname,
11679 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
11680 if (!NT_STATUS_IS_OK(status)) {
11681 printf("unlink failed (%s)\n", nt_errstr(status));
11684 if (!torture_close_connection(cli1)) {
11689 TALLOC_FREE(frame);
11691 printf("finished large_readx test\n");
11695 static NTSTATUS msdfs_attribute_list_fn(struct file_info *finfo,
11697 void *private_data)
11699 uint32_t *p_attr = (uint32_t *)private_data;
11701 if (strequal(finfo->name, test_filename)) {
11702 *p_attr = finfo->attr;
11705 return NT_STATUS_OK;
11708 static bool run_msdfs_attribute(int dummy)
11710 static struct cli_state *cli;
11711 bool correct = false;
11715 printf("Starting MSDFS-ATTRIBUTE test\n");
11717 if (test_filename == NULL || test_filename[0] == '\0') {
11718 printf("MSDFS-ATTRIBUTE test "
11719 "needs -f filename-of-msdfs-link\n");
11724 * NB. We use torture_open_connection_flags() not
11725 * torture_open_connection() as the latter forces
11728 if (!torture_open_connection_flags(&cli, 0, 0)) {
11732 smbXcli_conn_set_sockopt(cli->conn, sockops);
11734 status = cli_list(cli,
11736 FILE_ATTRIBUTE_DIRECTORY,
11737 msdfs_attribute_list_fn,
11740 if (!NT_STATUS_IS_OK(status)) {
11741 printf("cli_list failed with %s\n",
11742 nt_errstr(status));
11745 if ((attr & FILE_ATTRIBUTE_REPARSE_POINT) == 0) {
11746 printf("file %s should have "
11747 "FILE_ATTRIBUTE_REPARSE_POINT set. attr = 0x%x\n",
11749 (unsigned int)attr);
11753 if ((attr & FILE_ATTRIBUTE_DIRECTORY) == 0) {
11754 printf("file %s should have "
11755 "FILE_ATTRIBUTE_DIRECTORY set. attr = 0x%x\n",
11757 (unsigned int)attr);
11765 torture_close_connection(cli);
11769 static bool run_cli_echo(int dummy)
11771 struct cli_state *cli;
11774 printf("starting cli_echo test\n");
11775 if (!torture_open_connection(&cli, 0)) {
11778 smbXcli_conn_set_sockopt(cli->conn, sockops);
11780 status = cli_echo(cli, 5, data_blob_const("hello", 5));
11782 d_printf("cli_echo returned %s\n", nt_errstr(status));
11784 torture_close_connection(cli);
11785 return NT_STATUS_IS_OK(status);
11788 static int splice_status(off_t written, void *priv)
11793 static bool run_cli_splice(int dummy)
11795 uint8_t *buf = NULL;
11796 struct cli_state *cli1 = NULL;
11797 bool correct = false;
11798 const char *fname_src = "\\splice_src.dat";
11799 const char *fname_dst = "\\splice_dst.dat";
11801 uint16_t fnum1 = UINT16_MAX;
11802 uint16_t fnum2 = UINT16_MAX;
11803 size_t file_size = 2*1024*1024;
11804 size_t splice_size = 1*1024*1024 + 713;
11805 uint8_t digest1[16], digest2[16];
11808 TALLOC_CTX *frame = talloc_stackframe();
11810 printf("starting cli_splice test\n");
11812 if (!torture_open_connection(&cli1, 0)) {
11816 cli_unlink(cli1, fname_src,
11817 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
11818 cli_unlink(cli1, fname_dst,
11819 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
11821 /* Create a file */
11822 status = cli_ntcreate(cli1, fname_src, 0, GENERIC_ALL_ACCESS,
11823 FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
11824 0, 0, &fnum1, NULL);
11826 if (!NT_STATUS_IS_OK(status)) {
11827 d_printf("open %s failed: %s\n", fname_src, nt_errstr(status));
11831 /* Write file_size bytes - must be bigger than splice_size. */
11832 buf = talloc_zero_array(frame, uint8_t, file_size);
11834 d_printf("talloc_fail\n");
11838 /* Fill it with random numbers. */
11839 generate_random_buffer(buf, file_size);
11841 /* MD5 the first 1MB + 713 bytes. */
11842 gnutls_hash_fast(GNUTLS_DIG_MD5,
11847 status = cli_writeall(cli1,
11854 if (!NT_STATUS_IS_OK(status)) {
11855 d_printf("cli_writeall failed: %s\n", nt_errstr(status));
11859 status = cli_ntcreate(cli1, fname_dst, 0, GENERIC_ALL_ACCESS,
11860 FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
11861 0, 0, &fnum2, NULL);
11863 if (!NT_STATUS_IS_OK(status)) {
11864 d_printf("open %s failed: %s\n", fname_dst, nt_errstr(status));
11868 /* Now splice 1MB + 713 bytes. */
11869 status = cli_splice(cli1,
11880 if (!NT_STATUS_IS_OK(status)) {
11881 d_printf("cli_splice failed: %s\n", nt_errstr(status));
11885 /* Clear the old buffer. */
11886 memset(buf, '\0', file_size);
11888 /* Read the new file. */
11889 status = cli_read(cli1, fnum2, (char *)buf, 0, splice_size, &nread);
11890 if (!NT_STATUS_IS_OK(status)) {
11891 d_printf("cli_read failed: %s\n", nt_errstr(status));
11894 if (nread != splice_size) {
11895 d_printf("bad read of 0x%x, should be 0x%x\n",
11896 (unsigned int)nread,
11897 (unsigned int)splice_size);
11901 /* MD5 the first 1MB + 713 bytes. */
11902 gnutls_hash_fast(GNUTLS_DIG_MD5,
11907 /* Must be the same. */
11908 if (memcmp(digest1, digest2, 16) != 0) {
11909 d_printf("bad MD5 compare\n");
11914 printf("Success on cli_splice test\n");
11919 if (fnum1 != UINT16_MAX) {
11920 cli_close(cli1, fnum1);
11922 if (fnum2 != UINT16_MAX) {
11923 cli_close(cli1, fnum2);
11926 cli_unlink(cli1, fname_src,
11927 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
11928 cli_unlink(cli1, fname_dst,
11929 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
11931 if (!torture_close_connection(cli1)) {
11936 TALLOC_FREE(frame);
11940 static bool run_uid_regression_test(int dummy)
11942 static struct cli_state *cli;
11945 bool correct = True;
11946 struct smbXcli_tcon *tcon_copy = NULL;
11949 printf("starting uid regression test\n");
11951 if (!torture_open_connection(&cli, 0)) {
11955 smbXcli_conn_set_sockopt(cli->conn, sockops);
11957 /* Ok - now save then logoff our current user. */
11958 old_vuid = cli_state_get_uid(cli);
11960 status = cli_ulogoff(cli);
11961 if (!NT_STATUS_IS_OK(status)) {
11962 d_printf("(%s) cli_ulogoff failed: %s\n",
11963 __location__, nt_errstr(status));
11968 cli_state_set_uid(cli, old_vuid);
11970 /* Try an operation. */
11971 status = cli_mkdir(cli, "\\uid_reg_test");
11972 if (NT_STATUS_IS_OK(status)) {
11973 d_printf("(%s) cli_mkdir succeeded\n",
11978 /* Should be bad uid. */
11979 if (!check_error(__LINE__, status, ERRSRV, ERRbaduid,
11980 NT_STATUS_USER_SESSION_DELETED)) {
11986 old_cnum = cli_state_get_tid(cli);
11988 * This is an SMB1-only test.
11989 * Copy the tcon, not "save/restore".
11991 * In SMB1 the cli_tdis() below frees
11992 * cli->smb1.tcon so we need a copy
11993 * of the struct to put back for the
11994 * second tdis call with invalid vuid.
11996 * This is a test-only hack. Real client code
11997 * uses cli_state_save_tcon_share()/cli_state_restore_tcon_share().
11999 tcon_copy = smbXcli_tcon_copy(cli, cli->smb1.tcon);
12000 if (tcon_copy == NULL) {
12005 /* Now try a SMBtdis with the invalid vuid set to zero. */
12006 cli_state_set_uid(cli, 0);
12008 /* This should succeed. */
12009 status = cli_tdis(cli);
12011 if (NT_STATUS_IS_OK(status)) {
12012 d_printf("First tdis with invalid vuid should succeed.\n");
12014 d_printf("First tdis failed (%s)\n", nt_errstr(status));
12016 cli->smb1.tcon = tcon_copy;
12020 cli->smb1.tcon = tcon_copy;
12021 cli_state_set_uid(cli, old_vuid);
12022 cli_state_set_tid(cli, old_cnum);
12024 /* This should fail. */
12025 status = cli_tdis(cli);
12026 if (NT_STATUS_IS_OK(status)) {
12027 d_printf("Second tdis with invalid vuid should fail - succeeded instead !.\n");
12031 /* Should be bad tid. */
12032 if (!check_error(__LINE__, status, ERRSRV, ERRinvnid,
12033 NT_STATUS_NETWORK_NAME_DELETED)) {
12039 cli_rmdir(cli, "\\uid_reg_test");
12048 static const char *illegal_chars = "*\\/?<>|\":";
12049 static char force_shortname_chars[] = " +,.[];=\177";
12051 static NTSTATUS shortname_del_fn(struct file_info *finfo,
12052 const char *mask, void *state)
12054 struct cli_state *pcli = (struct cli_state *)state;
12056 NTSTATUS status = NT_STATUS_OK;
12058 slprintf(fname, sizeof(fname), "\\shortname\\%s", finfo->name);
12060 if (strcmp(finfo->name, ".") == 0 || strcmp(finfo->name, "..") == 0)
12061 return NT_STATUS_OK;
12063 if (finfo->attr & FILE_ATTRIBUTE_DIRECTORY) {
12064 status = cli_rmdir(pcli, fname);
12065 if (!NT_STATUS_IS_OK(status)) {
12066 printf("del_fn: failed to rmdir %s\n,", fname );
12069 status = cli_unlink(pcli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
12070 if (!NT_STATUS_IS_OK(status)) {
12071 printf("del_fn: failed to unlink %s\n,", fname );
12083 static NTSTATUS shortname_list_fn(struct file_info *finfo,
12084 const char *name, void *state)
12086 struct sn_state *s = (struct sn_state *)state;
12090 printf("shortname list: i = %d, name = |%s|, shortname = |%s|\n",
12091 i, finfo->name, finfo->short_name);
12094 if (strchr(force_shortname_chars, i)) {
12095 if (!finfo->short_name) {
12096 /* Shortname not created when it should be. */
12097 d_printf("(%s) ERROR: Shortname was not created for file %s containing %d\n",
12098 __location__, finfo->name, i);
12101 } else if (finfo->short_name){
12102 /* Shortname created when it should not be. */
12103 d_printf("(%s) ERROR: Shortname %s was created for file %s\n",
12104 __location__, finfo->short_name, finfo->name);
12108 return NT_STATUS_OK;
12111 static bool run_shortname_test(int dummy)
12113 static struct cli_state *cli;
12114 bool correct = True;
12120 printf("starting shortname test\n");
12122 if (!torture_open_connection(&cli, 0)) {
12126 smbXcli_conn_set_sockopt(cli->conn, sockops);
12128 cli_list(cli, "\\shortname\\*", 0, shortname_del_fn, cli);
12129 cli_list(cli, "\\shortname\\*", FILE_ATTRIBUTE_DIRECTORY, shortname_del_fn, cli);
12130 cli_rmdir(cli, "\\shortname");
12132 status = cli_mkdir(cli, "\\shortname");
12133 if (!NT_STATUS_IS_OK(status)) {
12134 d_printf("(%s) cli_mkdir of \\shortname failed: %s\n",
12135 __location__, nt_errstr(status));
12140 if (strlcpy(fname, "\\shortname\\", sizeof(fname)) >= sizeof(fname)) {
12144 if (strlcat(fname, "test .txt", sizeof(fname)) >= sizeof(fname)) {
12151 for (i = 32; i < 128; i++) {
12152 uint16_t fnum = (uint16_t)-1;
12156 if (strchr(illegal_chars, i)) {
12161 status = cli_ntcreate(cli, fname, 0, GENERIC_ALL_ACCESS, FILE_ATTRIBUTE_NORMAL,
12162 FILE_SHARE_READ|FILE_SHARE_WRITE,
12163 FILE_OVERWRITE_IF, 0, 0, &fnum, NULL);
12164 if (!NT_STATUS_IS_OK(status)) {
12165 d_printf("(%s) cli_nt_create of %s failed: %s\n",
12166 __location__, fname, nt_errstr(status));
12170 cli_close(cli, fnum);
12173 status = cli_list(cli, "\\shortname\\test*.*", 0,
12174 shortname_list_fn, &s);
12175 if (s.matched != 1) {
12176 d_printf("(%s) failed to list %s: %s\n",
12177 __location__, fname, nt_errstr(status));
12182 status = cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
12183 if (!NT_STATUS_IS_OK(status)) {
12184 d_printf("(%s) failed to delete %s: %s\n",
12185 __location__, fname, nt_errstr(status));
12198 cli_list(cli, "\\shortname\\*", 0, shortname_del_fn, cli);
12199 cli_list(cli, "\\shortname\\*", FILE_ATTRIBUTE_DIRECTORY, shortname_del_fn, cli);
12200 cli_rmdir(cli, "\\shortname");
12201 torture_close_connection(cli);
12205 TLDAPRC callback_code;
12207 static void pagedsearch_cb(struct tevent_req *req)
12210 struct tldap_message *msg;
12213 rc = tldap_search_paged_recv(req, talloc_tos(), &msg);
12214 if (!TLDAP_RC_IS_SUCCESS(rc)) {
12215 d_printf("tldap_search_paged_recv failed: %s\n",
12216 tldap_rc2string(rc));
12217 callback_code = rc;
12220 if (tldap_msg_type(msg) != TLDAP_RES_SEARCH_ENTRY) {
12224 if (!tldap_entry_dn(msg, &dn)) {
12225 d_printf("tldap_entry_dn failed\n");
12228 d_printf("%s\n", dn);
12232 enum tldap_extended_val {
12239 * Construct an extended dn control with either no value, 0 or 1
12241 * No value and 0 are equivalent (non-hyphenated GUID)
12242 * 1 has the hyphenated GUID
12244 static struct tldap_control *
12245 tldap_build_extended_control(enum tldap_extended_val val)
12247 struct tldap_control empty_control;
12248 struct asn1_data *data;
12250 ZERO_STRUCT(empty_control);
12252 if (val != EXTENDED_NONE) {
12253 data = asn1_init(talloc_tos(), ASN1_MAX_TREE_DEPTH);
12259 if (!asn1_push_tag(data, ASN1_SEQUENCE(0))) {
12263 if (!asn1_write_Integer(data, (int)val)) {
12267 if (!asn1_pop_tag(data)) {
12271 if (!asn1_blob(data, &empty_control.value)) {
12276 empty_control.oid = "1.2.840.113556.1.4.529";
12277 empty_control.critical = true;
12279 return tldap_add_control(talloc_tos(), NULL, 0, &empty_control);
12283 static bool tldap_test_dn_guid_format(struct tldap_context *ld, const char *basedn,
12284 enum tldap_extended_val control_val)
12286 struct tldap_control *control = tldap_build_extended_control(control_val);
12288 struct tldap_message **msg;
12291 rc = tldap_search(ld, basedn, TLDAP_SCOPE_BASE,
12292 "(objectClass=*)", NULL, 0, 0,
12294 0, 0, 0, 0, talloc_tos(), &msg);
12295 if (!TLDAP_RC_IS_SUCCESS(rc)) {
12296 d_printf("tldap_search for domain DN failed: %s\n",
12297 tldap_errstr(talloc_tos(), ld, rc));
12301 if (!tldap_entry_dn(msg[0], &dn)) {
12302 d_printf("tldap_search domain DN fetch failed: %s\n",
12303 tldap_errstr(talloc_tos(), ld, rc));
12307 d_printf("%s\n", dn);
12310 uint32_t time_mid, time_hi_and_version;
12311 uint32_t clock_seq[2];
12315 switch (control_val) {
12316 case EXTENDED_NONE:
12317 case EXTENDED_ZERO:
12319 * When reading GUIDs with hyphens, scanf will treat
12320 * hyphen as a hex character (and counts as part of the
12321 * width). This creates leftover GUID string which we
12322 * check will for with 'next' and closing '>'.
12324 if (12 == sscanf(dn, "<GUID=%08x%04x%04x%02x%02x%02x%02x%02x%02x%02x%02x>%c",
12325 &time_low, &time_mid,
12326 &time_hi_and_version, &clock_seq[0],
12327 &clock_seq[1], &node[0], &node[1],
12328 &node[2], &node[3], &node[4],
12329 &node[5], &next)) {
12330 /* This GUID is good */
12332 d_printf("GUID format in control (no hyphens) doesn't match output\n");
12338 if (12 == sscanf(dn,
12339 "<GUID=%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x>%c",
12340 &time_low, &time_mid,
12341 &time_hi_and_version, &clock_seq[0],
12342 &clock_seq[1], &node[0], &node[1],
12343 &node[2], &node[3], &node[4],
12344 &node[5], &next)) {
12345 /* This GUID is good */
12347 d_printf("GUID format in control (with hyphens) doesn't match output\n");
12360 static bool run_tldap(int dummy)
12362 struct tldap_context *ld;
12366 struct sockaddr_storage addr;
12367 struct tevent_context *ev;
12368 struct tevent_req *req;
12370 const char *filter;
12371 struct loadparm_context *lp_ctx = NULL;
12372 int tcp_port = 389;
12373 bool use_tls = false;
12374 bool use_starttls = false;
12375 int wrap_flags = -1;
12376 uint32_t gensec_features = 0;
12378 lp_ctx = loadparm_init_s3(talloc_tos(), loadparm_s3_helpers());
12380 wrap_flags = lpcfg_client_ldap_sasl_wrapping(lp_ctx);
12382 if (wrap_flags & ADS_AUTH_SASL_LDAPS) {
12385 } else if (wrap_flags & ADS_AUTH_SASL_STARTTLS) {
12387 use_starttls = true;
12389 if (wrap_flags & ADS_AUTH_SASL_SEAL) {
12390 gensec_features |= GENSEC_FEATURE_SEAL;
12392 if (wrap_flags & ADS_AUTH_SASL_SIGN) {
12393 gensec_features |= GENSEC_FEATURE_SIGN;
12396 if (gensec_features != 0) {
12397 gensec_features |= GENSEC_FEATURE_LDAP_STYLE;
12400 if (!resolve_name(host, &addr, 0, false)) {
12401 d_printf("could not find host %s\n", host);
12404 status = open_socket_out(&addr, tcp_port, 9999, &fd);
12405 if (!NT_STATUS_IS_OK(status)) {
12406 d_printf("open_socket_out failed: %s\n", nt_errstr(status));
12410 ld = tldap_context_create(talloc_tos(), fd);
12413 d_printf("tldap_context_create failed\n");
12417 if (use_tls && !tldap_has_tls_tstream(ld)) {
12418 tldap_set_starttls_needed(ld, use_starttls);
12420 rc = tldap_tls_connect(ld, lp_ctx, host);
12421 if (!TLDAP_RC_IS_SUCCESS(rc)) {
12422 DBG_ERR("tldap_tls_connect(%s) failed: %s\n",
12423 host, tldap_errstr(talloc_tos(), ld, rc));
12428 rc = tldap_fetch_rootdse(ld);
12429 if (!TLDAP_RC_IS_SUCCESS(rc)) {
12430 d_printf("tldap_fetch_rootdse failed: %s\n",
12431 tldap_errstr(talloc_tos(), ld, rc));
12435 basedn = tldap_talloc_single_attribute(
12436 tldap_rootdse(ld), "defaultNamingContext", talloc_tos());
12437 if (basedn == NULL) {
12438 d_printf("no defaultNamingContext\n");
12441 d_printf("defaultNamingContext: %s\n", basedn);
12443 ev = samba_tevent_context_init(talloc_tos());
12445 d_printf("tevent_context_init failed\n");
12449 rc = tldap_gensec_bind(ld, torture_creds, "ldap", host, NULL,
12450 lp_ctx, gensec_features);
12451 if (!TLDAP_RC_IS_SUCCESS(rc)) {
12452 d_printf("tldap_gensec_bind failed\n");
12456 callback_code = TLDAP_SUCCESS;
12458 req = tldap_search_paged_send(talloc_tos(), ev, ld, basedn,
12459 TLDAP_SCOPE_SUB, "(objectclass=*)",
12461 NULL, 0, NULL, 0, 0, 0, 0, 5);
12463 d_printf("tldap_search_paged_send failed\n");
12466 tevent_req_set_callback(req, pagedsearch_cb, NULL);
12468 tevent_req_poll(req, ev);
12472 rc = callback_code;
12474 if (!TLDAP_RC_IS_SUCCESS(rc)) {
12475 d_printf("tldap_search with paging failed: %s\n",
12476 tldap_errstr(talloc_tos(), ld, rc));
12480 /* test search filters against rootDSE */
12481 filter = "(&(|(name=samba)(nextRid<=10000000)(usnChanged>=10)(samba~=ambas)(!(name=s*m*a)))"
12482 "(|(name:=samba)(name:dn:2.5.13.5:=samba)(:dn:2.5.13.5:=samba)(!(name=*samba))))";
12484 rc = tldap_search(ld, "", TLDAP_SCOPE_BASE, filter,
12485 NULL, 0, 0, NULL, 0, NULL, 0, 0, 0, 0,
12486 talloc_tos(), NULL);
12487 if (!TLDAP_RC_IS_SUCCESS(rc)) {
12488 d_printf("tldap_search with complex filter failed: %s\n",
12489 tldap_errstr(talloc_tos(), ld, rc));
12494 * Tests to check for regression of:
12496 * https://bugzilla.samba.org/show_bug.cgi?id=14029
12498 * TLDAP used here to pick apart the original string DN (with GUID)
12500 if (!tldap_test_dn_guid_format(ld, basedn, EXTENDED_NONE)) {
12501 d_printf("tldap_search with extended dn (no val) failed: %s\n",
12502 tldap_errstr(talloc_tos(), ld, rc));
12505 if (!tldap_test_dn_guid_format(ld, basedn, EXTENDED_ZERO)) {
12506 d_printf("tldap_search with extended dn (0) failed: %s\n",
12507 tldap_errstr(talloc_tos(), ld, rc));
12510 if (!tldap_test_dn_guid_format(ld, basedn, EXTENDED_ONE)) {
12511 d_printf("tldap_search with extended dn (1) failed: %s\n",
12512 tldap_errstr(talloc_tos(), ld, rc));
12520 /* Torture test to ensure no regression of :
12521 https://bugzilla.samba.org/show_bug.cgi?id=7084
12524 static bool run_dir_createtime(int dummy)
12526 struct cli_state *cli;
12527 const char *dname = "\\testdir_createtime";
12528 const char *fname = "\\testdir_createtime\\testfile";
12530 struct timespec create_time;
12531 struct timespec create_time1;
12536 if (!torture_open_connection(&cli, 0)) {
12540 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
12541 /* Ensure ino is zero, SMB2 gets a real one. */
12544 /* Ensure ino is -1, SMB1 never gets a real one. */
12545 ino = (uint64_t)-1;
12548 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
12549 cli_rmdir(cli, dname);
12551 status = cli_mkdir(cli, dname);
12552 if (!NT_STATUS_IS_OK(status)) {
12553 printf("mkdir failed: %s\n", nt_errstr(status));
12557 status = cli_qpathinfo2(cli,
12567 if (!NT_STATUS_IS_OK(status)) {
12568 printf("cli_qpathinfo2 returned %s\n",
12569 nt_errstr(status));
12573 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
12574 /* SMB2 should always return an inode. */
12576 printf("SMB2 bad inode (0)\n");
12580 /* SMB1 must always return zero here. */
12582 printf("SMB1 bad inode (!0)\n");
12587 /* Sleep 3 seconds, then create a file. */
12590 status = cli_openx(cli, fname, O_RDWR | O_CREAT | O_EXCL,
12592 if (!NT_STATUS_IS_OK(status)) {
12593 printf("cli_openx failed: %s\n", nt_errstr(status));
12597 status = cli_qpathinfo2(cli,
12607 if (!NT_STATUS_IS_OK(status)) {
12608 printf("cli_qpathinfo2 (2) returned %s\n",
12609 nt_errstr(status));
12613 if (timespec_compare(&create_time1, &create_time)) {
12614 printf("run_dir_createtime: create time was updated (error)\n");
12616 printf("run_dir_createtime: create time was not updated (correct)\n");
12622 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
12623 cli_rmdir(cli, dname);
12624 if (!torture_close_connection(cli)) {
12631 static bool run_streamerror(int dummy)
12633 struct cli_state *cli;
12634 const char *dname = "\\testdir_streamerror";
12635 const char *streamname =
12636 "testdir_streamerror:{4c8cc155-6c1e-11d1-8e41-00c04fb9386d}:$DATA";
12638 time_t change_time, access_time, write_time;
12644 if (!torture_open_connection(&cli, 0)) {
12648 torture_deltree(cli, dname);
12650 status = cli_mkdir(cli, dname);
12651 if (!NT_STATUS_IS_OK(status)) {
12652 printf("mkdir failed: %s\n", nt_errstr(status));
12656 status = cli_qpathinfo1(cli, streamname, &change_time, &access_time,
12657 &write_time, &size, &attr);
12658 if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
12659 printf("pathinfo returned %s, expected "
12660 "NT_STATUS_OBJECT_NAME_NOT_FOUND\n",
12661 nt_errstr(status));
12665 status = cli_ntcreate(cli, streamname, 0x16,
12666 FILE_READ_DATA|FILE_READ_EA|
12667 FILE_READ_ATTRIBUTES|READ_CONTROL_ACCESS,
12668 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ,
12669 FILE_OPEN, 0, 0, &fnum, NULL);
12671 if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
12672 printf("ntcreate returned %s, expected "
12673 "NT_STATUS_OBJECT_NAME_NOT_FOUND\n",
12674 nt_errstr(status));
12679 cli_rmdir(cli, dname);
12683 struct pidtest_state {
12689 static void pid_echo_done(struct tevent_req *subreq);
12691 static struct tevent_req *pid_echo_send(TALLOC_CTX *mem_ctx,
12692 struct tevent_context *ev,
12693 struct cli_state *cli)
12695 struct tevent_req *req, *subreq;
12696 struct pidtest_state *state;
12698 req = tevent_req_create(mem_ctx, &state, struct pidtest_state);
12703 SSVAL(state->vwv, 0, 1);
12704 state->data = data_blob_const("hello", 5);
12706 subreq = smb1cli_req_send(state,
12710 0, 0, /* *_flags */
12711 0, 0, /* *_flags2 */
12713 0xDEADBEEF, /* pid */
12715 NULL, /* session */
12716 ARRAY_SIZE(state->vwv), state->vwv,
12717 state->data.length, state->data.data);
12719 if (tevent_req_nomem(subreq, req)) {
12720 return tevent_req_post(req, ev);
12722 tevent_req_set_callback(subreq, pid_echo_done, req);
12726 static void pid_echo_done(struct tevent_req *subreq)
12728 struct tevent_req *req = tevent_req_callback_data(
12729 subreq, struct tevent_req);
12730 struct pidtest_state *state = tevent_req_data(
12731 req, struct pidtest_state);
12733 uint32_t num_bytes;
12734 uint8_t *bytes = NULL;
12735 struct iovec *recv_iov = NULL;
12736 uint8_t *phdr = NULL;
12737 uint16_t pidlow = 0;
12738 uint16_t pidhigh = 0;
12739 struct smb1cli_req_expected_response expected[] = {
12741 .status = NT_STATUS_OK,
12746 status = smb1cli_req_recv(subreq, state,
12751 NULL, /* pvwv_offset */
12754 NULL, /* pbytes_offset */
12756 expected, ARRAY_SIZE(expected));
12758 TALLOC_FREE(subreq);
12760 if (!NT_STATUS_IS_OK(status)) {
12761 tevent_req_nterror(req, status);
12765 if (num_bytes != state->data.length) {
12766 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
12770 if (memcmp(bytes, state->data.data, num_bytes) != 0) {
12771 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
12775 /* Check pid low/high == DEADBEEF */
12776 pidlow = SVAL(phdr, HDR_PID);
12777 if (pidlow != 0xBEEF){
12778 printf("Incorrect pidlow 0x%x, should be 0xBEEF\n",
12779 (unsigned int)pidlow);
12780 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
12783 pidhigh = SVAL(phdr, HDR_PIDHIGH);
12784 if (pidhigh != 0xDEAD){
12785 printf("Incorrect pidhigh 0x%x, should be 0xDEAD\n",
12786 (unsigned int)pidhigh);
12787 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
12791 tevent_req_done(req);
12794 static NTSTATUS pid_echo_recv(struct tevent_req *req)
12796 return tevent_req_simple_recv_ntstatus(req);
12799 static bool run_pidhigh(int dummy)
12801 bool success = false;
12802 struct cli_state *cli = NULL;
12804 struct tevent_context *ev = NULL;
12805 struct tevent_req *req = NULL;
12806 TALLOC_CTX *frame = talloc_stackframe();
12808 printf("starting pid high test\n");
12809 if (!torture_open_connection(&cli, 0)) {
12812 smbXcli_conn_set_sockopt(cli->conn, sockops);
12814 ev = samba_tevent_context_init(frame);
12819 req = pid_echo_send(frame, ev, cli);
12824 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
12828 status = pid_echo_recv(req);
12829 if (NT_STATUS_IS_OK(status)) {
12830 printf("pid high test ok\n");
12836 TALLOC_FREE(frame);
12837 torture_close_connection(cli);
12842 Test Windows open on a bad POSIX symlink.
12844 static bool run_symlink_open_test(int dummy)
12846 static struct cli_state *cli;
12847 const char *fname = "non_existant_file";
12848 const char *sname = "dangling_symlink";
12849 uint16_t fnum = (uint16_t)-1;
12850 bool correct = false;
12852 TALLOC_CTX *frame = NULL;
12854 frame = talloc_stackframe();
12856 printf("Starting Windows bad symlink open test\n");
12858 if (!torture_open_connection(&cli, 0)) {
12859 TALLOC_FREE(frame);
12863 smbXcli_conn_set_sockopt(cli->conn, sockops);
12865 status = torture_setup_unix_extensions(cli);
12866 if (!NT_STATUS_IS_OK(status)) {
12867 TALLOC_FREE(frame);
12871 /* Ensure nothing exists. */
12872 cli_setatr(cli, fname, 0, 0);
12873 cli_posix_unlink(cli, fname);
12874 cli_setatr(cli, sname, 0, 0);
12875 cli_posix_unlink(cli, sname);
12877 /* Create a symlink pointing nowhere. */
12878 status = cli_posix_symlink(cli, fname, sname);
12879 if (!NT_STATUS_IS_OK(status)) {
12880 printf("cli_posix_symlink of %s -> %s failed (%s)\n",
12883 nt_errstr(status));
12887 /* Now ensure that a Windows open doesn't hang. */
12888 status = cli_ntcreate(cli,
12891 FILE_READ_DATA|FILE_WRITE_DATA,
12893 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
12901 * We get either NT_STATUS_OBJECT_NAME_NOT_FOUND or
12902 * NT_STATUS_OBJECT_PATH_NOT_FOUND depending on if
12903 * we use O_NOFOLLOW on the server or not.
12905 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND) ||
12906 NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_PATH_NOT_FOUND))
12910 printf("cli_ntcreate of %s returned %s - should return"
12911 " either (%s) or (%s)\n",
12914 nt_errstr(NT_STATUS_OBJECT_NAME_NOT_FOUND),
12915 nt_errstr(NT_STATUS_OBJECT_PATH_NOT_FOUND));
12923 if (fnum != (uint16_t)-1) {
12924 cli_close(cli, fnum);
12925 fnum = (uint16_t)-1;
12928 cli_setatr(cli, sname, 0, 0);
12929 cli_posix_unlink(cli, sname);
12930 cli_setatr(cli, fname, 0, 0);
12931 cli_posix_unlink(cli, fname);
12933 if (!torture_close_connection(cli)) {
12937 TALLOC_FREE(frame);
12941 static NTSTATUS smb1_wild_mangle_list_fn(struct file_info *finfo,
12945 char **mangled_name_return = (char **)state;
12946 bool is_mangled = strchr(finfo->name, '~');
12949 *mangled_name_return = talloc_strdup(NULL, finfo->name);
12950 if (*mangled_name_return == NULL) {
12951 return NT_STATUS_NO_MEMORY;
12954 return NT_STATUS_OK;
12957 static bool run_smb1_wild_mangle_unlink_test(int dummy)
12959 static struct cli_state *cli_posix = NULL;
12960 static struct cli_state *cli = NULL;
12961 uint16_t fnum = (uint16_t)-1;
12962 bool correct = false;
12963 const char *dname = "smb1_wild_mangle_unlink";
12964 const char *aname = "smb1_wild_mangle_unlink/a";
12965 const char *star_name = "smb1_wild_mangle_unlink/*";
12966 char *windows_unlink_name = NULL;
12967 char *mangled_name = NULL;
12970 printf("Starting SMB1 wild mangle unlink test\n");
12972 /* Open a Windows connection. */
12973 if (!torture_open_connection(&cli, 0)) {
12977 smbXcli_conn_set_sockopt(cli->conn, sockops);
12979 /* Open a POSIX connection. */
12980 if (!torture_open_connection(&cli_posix, 0)) {
12984 smbXcli_conn_set_sockopt(cli_posix->conn, sockops);
12986 status = torture_setup_unix_extensions(cli_posix);
12987 if (!NT_STATUS_IS_OK(status)) {
12988 printf("server doesn't support POSIX\n");
12993 torture_deltree(cli, dname);
12996 * Create two files - 'a' and '*'.
12997 * We need POSIX extensions for this as '*'
12998 * is not a valid Windows name.
13001 status = cli_mkdir(cli, dname);
13002 if (!NT_STATUS_IS_OK(status)) {
13003 printf("cli_mkdir of %s returned %s\n",
13005 nt_errstr(status));
13009 status = cli_posix_open(cli_posix,
13011 O_RDWR|O_CREAT|O_EXCL,
13014 if (!NT_STATUS_IS_OK(status)) {
13015 printf("cli_posix_open (create) of %s returned %s\n",
13017 nt_errstr(status));
13020 status = cli_close(cli_posix, fnum);
13021 if (!NT_STATUS_IS_OK(status)) {
13024 status = cli_posix_open(cli_posix,
13026 O_RDWR|O_CREAT|O_EXCL,
13029 if (!NT_STATUS_IS_OK(status)) {
13030 printf("cli_posix_open (create) of %s returned %s\n",
13032 nt_errstr(status));
13035 status = cli_close(cli_posix, fnum);
13036 if (!NT_STATUS_IS_OK(status)) {
13040 status = cli_list(cli,
13043 smb1_wild_mangle_list_fn,
13045 if (!NT_STATUS_IS_OK(status)) {
13046 printf("cli_list of %s returned %s\n",
13048 nt_errstr(status));
13052 if (mangled_name == NULL) {
13056 printf("mangled_name = %s\n",
13060 * Try a Windows unlink with the mangled name.
13061 * This should *NOT* unlink the 'a' name.
13064 windows_unlink_name = talloc_asprintf(cli_posix,
13069 status = cli_unlink(cli, windows_unlink_name, 0);
13070 if (!NT_STATUS_IS_OK(status)) {
13071 printf("cli_unlink of %s returned %s\n",
13072 windows_unlink_name,
13073 nt_errstr(status));
13077 /* Does 'a' still exist ? */
13078 status = cli_posix_open(cli_posix,
13083 if (!NT_STATUS_IS_OK(status)) {
13084 printf("cli_posix_open O_RNONLY of %s returned %s\n",
13086 nt_errstr(status));
13090 status = cli_close(cli_posix, fnum);
13091 if (!NT_STATUS_IS_OK(status)) {
13099 TALLOC_FREE(windows_unlink_name);
13100 TALLOC_FREE(mangled_name);
13103 torture_deltree(cli, dname);
13104 torture_close_connection(cli);
13107 if (cli_posix != NULL) {
13108 torture_close_connection(cli_posix);
13114 static bool run_smb1_wild_mangle_rename_test(int dummy)
13116 static struct cli_state *cli_posix = NULL;
13117 static struct cli_state *cli = NULL;
13118 uint16_t fnum = (uint16_t)-1;
13119 bool correct = false;
13120 const char *dname = "smb1_wild_mangle_rename";
13121 const char *fooname = "smb1_wild_mangle_rename/foo";
13122 const char *foostar_name = "smb1_wild_mangle_rename/fo*";
13123 const char *wild_name = "smb1_wild_mangle_rename/*";
13124 char *windows_rename_src = NULL;
13125 const char *windows_rename_dst = "smb1_wild_mangle_rename\\bar";
13126 char *mangled_name = NULL;
13129 printf("Starting SMB1 wild mangle rename test\n");
13131 if (!torture_open_connection(&cli_posix, 0)) {
13135 smbXcli_conn_set_sockopt(cli_posix->conn, sockops);
13137 status = torture_setup_unix_extensions(cli_posix);
13138 if (!NT_STATUS_IS_OK(status)) {
13139 printf("server doesn't support POSIX\n");
13143 /* Open a Windows connection. */
13144 if (!torture_open_connection(&cli, 0)) {
13148 smbXcli_conn_set_sockopt(cli->conn, sockops);
13150 /* Ensure we start from fresh. */
13151 torture_deltree(cli, dname);
13154 * Create two files - 'foo' and 'fo*'.
13155 * We need POSIX extensions for this as 'fo*'
13156 * is not a valid Windows name.
13159 status = cli_posix_mkdir(cli_posix, dname, 0770);
13160 if (!NT_STATUS_IS_OK(status)) {
13161 printf("cli_posix_mkdir of %s returned %s\n",
13163 nt_errstr(status));
13167 status = cli_posix_open(cli_posix,
13169 O_RDWR|O_CREAT|O_EXCL,
13172 if (!NT_STATUS_IS_OK(status)) {
13173 printf("cli_posix_open (create) of %s returned %s\n",
13175 nt_errstr(status));
13178 status = cli_close(cli_posix, fnum);
13179 if (!NT_STATUS_IS_OK(status)) {
13182 status = cli_posix_open(cli_posix,
13184 O_RDWR|O_CREAT|O_EXCL,
13187 if (!NT_STATUS_IS_OK(status)) {
13188 printf("cli_posix_open (create) of %s returned %s\n",
13190 nt_errstr(status));
13193 status = cli_close(cli_posix, fnum);
13194 if (!NT_STATUS_IS_OK(status)) {
13199 * Get the mangled name. We can re-use the
13200 * previous smb1_wild_mangle_list_fn for this.
13203 status = cli_list(cli,
13206 smb1_wild_mangle_list_fn,
13208 if (!NT_STATUS_IS_OK(status)) {
13209 printf("cli_list of %s returned %s\n",
13211 nt_errstr(status));
13215 if (mangled_name == NULL) {
13219 printf("mangled_name = %s\n",
13223 * Try a Windows rename with the mangled name.
13224 * This should *NOT* rename the 'foo' name.
13227 windows_rename_src = talloc_asprintf(cli_posix,
13232 status = cli_rename(cli,
13233 windows_rename_src,
13234 windows_rename_dst,
13236 if (!NT_STATUS_IS_OK(status)) {
13237 printf("cli_rename of %s -> %s returned %s\n",
13238 windows_rename_src,
13239 windows_rename_dst,
13240 nt_errstr(status));
13244 /* Does 'foo' still exist ? */
13245 status = cli_posix_open(cli_posix,
13250 if (!NT_STATUS_IS_OK(status)) {
13251 printf("cli_posix_open O_RNONLY of %s returned %s\n",
13253 nt_errstr(status));
13257 status = cli_close(cli_posix, fnum);
13258 if (!NT_STATUS_IS_OK(status)) {
13266 TALLOC_FREE(mangled_name);
13267 TALLOC_FREE(windows_rename_src);
13270 torture_deltree(cli, dname);
13271 torture_close_connection(cli);
13274 torture_close_connection(cli_posix);
13280 * Only testing minimal time strings, as the others
13281 * need (locale-dependent) guessing at what strftime does and
13282 * even may differ in builds.
13284 static bool timesubst_test(void)
13286 TALLOC_CTX *ctx = NULL;
13287 /* Sa 23. Dez 04:33:20 CET 2017 */
13288 const struct timeval tv = { 1514000000, 123 };
13289 const char* expect_minimal = "20171223_033320";
13290 const char* expect_minus = "20171223_033320_000123";
13292 char *env_tz, *orig_tz = NULL;
13293 bool result = true;
13295 ctx = talloc_new(NULL);
13297 env_tz = getenv("TZ");
13299 orig_tz = talloc_strdup(ctx, env_tz);
13301 setenv("TZ", "UTC", 1);
13303 s = minimal_timeval_string(ctx, &tv, false);
13305 if(!s || strcmp(s, expect_minimal)) {
13306 printf("minimal_timeval_string(ctx, tv, false) returned [%s], expected "
13307 "[%s]\n", s ? s : "<nil>", expect_minimal);
13311 s = minimal_timeval_string(ctx, &tv, true);
13312 if(!s || strcmp(s, expect_minus)) {
13313 printf("minimal_timeval_string(ctx, tv, true) returned [%s], expected "
13314 "[%s]\n", s ? s : "<nil>", expect_minus);
13320 setenv("TZ", orig_tz, 1);
13327 static bool run_local_substitute(int dummy)
13331 ok &= subst_test("%U", "bla", "", -1, -1, "bla");
13332 ok &= subst_test("%u%U", "bla", "", -1, -1, "blabla");
13333 ok &= subst_test("%g", "", "", -1, -1, "NO_GROUP");
13334 ok &= subst_test("%G", "", "", -1, -1, "NO_GROUP");
13335 ok &= subst_test("%g", "", "", -1, 0, gidtoname(0));
13336 ok &= subst_test("%G", "", "", -1, 0, gidtoname(0));
13337 ok &= subst_test("%D%u", "u", "dom", -1, 0, "domu");
13338 ok &= subst_test("%i %I", "", "", -1, -1, "0.0.0.0 0.0.0.0");
13339 ok &= subst_test("%j %J", "", "", -1, -1, "0_0_0_0 0_0_0_0");
13340 /* Substitution depends on current time, so better test the underlying
13341 formatting function. At least covers %t. */
13342 ok &= timesubst_test();
13344 /* Different captialization rules in sub_basic... */
13346 ok &= (strcmp(talloc_sub_basic(talloc_tos(), "BLA", "dom", "%U%D"),
13352 static bool run_local_base64(int dummy)
13357 for (i=1; i<2000; i++) {
13358 DATA_BLOB blob1, blob2;
13361 blob1.data = talloc_array(talloc_tos(), uint8_t, i);
13363 generate_random_buffer(blob1.data, blob1.length);
13365 b64 = base64_encode_data_blob(talloc_tos(), blob1);
13367 d_fprintf(stderr, "base64_encode_data_blob failed "
13368 "for %d bytes\n", i);
13371 blob2 = base64_decode_data_blob(b64);
13374 if (data_blob_cmp(&blob1, &blob2)) {
13375 d_fprintf(stderr, "data_blob_cmp failed for %d "
13379 TALLOC_FREE(blob1.data);
13380 data_blob_free(&blob2);
13385 static void parse_fn(const struct gencache_timeout *t,
13387 void *private_data)
13392 static bool run_local_gencache(int dummy)
13398 struct memcache *mem;
13401 mem = memcache_init(NULL, 0);
13403 d_printf("%s: memcache_init failed\n", __location__);
13406 memcache_set_global(mem);
13408 if (!gencache_set("foo", "bar", time(NULL) + 1000)) {
13409 d_printf("%s: gencache_set() failed\n", __location__);
13413 if (!gencache_get("foo", NULL, NULL, NULL)) {
13414 d_printf("%s: gencache_get() failed\n", __location__);
13418 for (i=0; i<1000000; i++) {
13419 gencache_parse("foo", parse_fn, NULL);
13422 if (!gencache_get("foo", talloc_tos(), &val, &tm)) {
13423 d_printf("%s: gencache_get() failed\n", __location__);
13428 if (!gencache_get("foo", talloc_tos(), &val, &tm)) {
13429 d_printf("%s: gencache_get() failed\n", __location__);
13433 if (strcmp(val, "bar") != 0) {
13434 d_printf("%s: gencache_get() returned %s, expected %s\n",
13435 __location__, val, "bar");
13442 if (!gencache_del("foo")) {
13443 d_printf("%s: gencache_del() failed\n", __location__);
13446 if (gencache_del("foo")) {
13447 d_printf("%s: second gencache_del() succeeded\n",
13452 if (gencache_get("foo", talloc_tos(), &val, &tm)) {
13453 d_printf("%s: gencache_get() on deleted entry "
13454 "succeeded\n", __location__);
13458 blob = data_blob_string_const_null("bar");
13459 tm = time(NULL) + 60;
13461 if (!gencache_set_data_blob("foo", blob, tm)) {
13462 d_printf("%s: gencache_set_data_blob() failed\n", __location__);
13466 if (!gencache_get_data_blob("foo", talloc_tos(), &blob, NULL, NULL)) {
13467 d_printf("%s: gencache_get_data_blob() failed\n", __location__);
13471 if (strcmp((const char *)blob.data, "bar") != 0) {
13472 d_printf("%s: gencache_get_data_blob() returned %s, expected %s\n",
13473 __location__, (const char *)blob.data, "bar");
13474 data_blob_free(&blob);
13478 data_blob_free(&blob);
13480 if (!gencache_del("foo")) {
13481 d_printf("%s: gencache_del() failed\n", __location__);
13484 if (gencache_del("foo")) {
13485 d_printf("%s: second gencache_del() succeeded\n",
13490 if (gencache_get_data_blob("foo", talloc_tos(), &blob, NULL, NULL)) {
13491 d_printf("%s: gencache_get_data_blob() on deleted entry "
13492 "succeeded\n", __location__);
13497 blob.data = (uint8_t *)&v;
13498 blob.length = sizeof(v);
13500 if (!gencache_set_data_blob("blob", blob, tm)) {
13501 d_printf("%s: gencache_set_data_blob() failed\n",
13505 if (gencache_get("blob", talloc_tos(), &val, &tm)) {
13506 d_printf("%s: gencache_get succeeded\n", __location__);
13513 static bool rbt_testflags(struct db_context *db, const char *key,
13518 struct db_record *rec;
13520 rec = dbwrap_fetch_locked(db, db, string_tdb_data(key));
13522 d_fprintf(stderr, "fetch_locked failed\n");
13526 status = dbwrap_record_store(rec, string_tdb_data(value), TDB_MODIFY);
13527 if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
13528 d_fprintf(stderr, "store TDB_MODIFY unexpected status: %s\n",
13529 nt_errstr(status));
13533 status = dbwrap_record_store(rec, string_tdb_data("overwriteme"),
13535 if (!NT_STATUS_IS_OK(status)) {
13536 d_fprintf(stderr, "store TDB_INSERT failed: %s\n",
13537 nt_errstr(status));
13541 status = dbwrap_record_store(rec, string_tdb_data(value), TDB_INSERT);
13542 if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_COLLISION)) {
13543 d_fprintf(stderr, "store TDB_INSERT unexpected status: %s\n",
13544 nt_errstr(status));
13548 status = dbwrap_record_store(rec, string_tdb_data(value), TDB_MODIFY);
13549 if (!NT_STATUS_IS_OK(status)) {
13550 d_fprintf(stderr, "store TDB_MODIFY failed: %s\n",
13551 nt_errstr(status));
13561 static bool rbt_testval(struct db_context *db, const char *key,
13564 struct db_record *rec;
13565 TDB_DATA data = string_tdb_data(value);
13570 rec = dbwrap_fetch_locked(db, db, string_tdb_data(key));
13572 d_fprintf(stderr, "fetch_locked failed\n");
13575 status = dbwrap_record_store(rec, data, 0);
13576 if (!NT_STATUS_IS_OK(status)) {
13577 d_fprintf(stderr, "store failed: %s\n", nt_errstr(status));
13582 rec = dbwrap_fetch_locked(db, db, string_tdb_data(key));
13584 d_fprintf(stderr, "second fetch_locked failed\n");
13588 dbvalue = dbwrap_record_get_value(rec);
13589 if ((dbvalue.dsize != data.dsize)
13590 || (memcmp(dbvalue.dptr, data.dptr, data.dsize) != 0)) {
13591 d_fprintf(stderr, "Got wrong data back\n");
13601 static int local_rbtree_traverse_read(struct db_record *rec, void *private_data)
13603 int *count2 = (int *)private_data;
13608 static int local_rbtree_traverse_delete(struct db_record *rec, void *private_data)
13610 int *count2 = (int *)private_data;
13612 dbwrap_record_delete(rec);
13616 static bool run_local_rbtree(int dummy)
13618 struct db_context *db;
13625 db = db_open_rbt(NULL);
13628 d_fprintf(stderr, "db_open_rbt failed\n");
13632 if (!rbt_testflags(db, "firstkey", "firstval")) {
13636 for (i = 0; i < 999; i++) {
13637 char key[sizeof("key-9223372036854775807")];
13638 char value[sizeof("value-9223372036854775807")];
13640 snprintf(key, sizeof(key), "key%ld", random());
13641 snprintf(value, sizeof(value) ,"value%ld", random());
13643 if (!rbt_testval(db, key, value)) {
13647 snprintf(value, sizeof(value) ,"value%ld", random());
13649 if (!rbt_testval(db, key, value)) {
13655 count = 0; count2 = 0;
13656 status = dbwrap_traverse_read(db, local_rbtree_traverse_read,
13658 printf("%s: read1: %d %d, %s\n", __func__, count, count2, nt_errstr(status));
13659 if ((count != count2) || (count != 1000)) {
13662 count = 0; count2 = 0;
13663 status = dbwrap_traverse(db, local_rbtree_traverse_delete,
13665 printf("%s: delete: %d %d, %s\n", __func__, count, count2, nt_errstr(status));
13666 if ((count != count2) || (count != 1000)) {
13669 count = 0; count2 = 0;
13670 status = dbwrap_traverse_read(db, local_rbtree_traverse_read,
13672 printf("%s: read2: %d %d, %s\n", __func__, count, count2, nt_errstr(status));
13673 if ((count != count2) || (count != 0)) {
13684 local test for character set functions
13686 This is a very simple test for the functionality in convert_string_error()
13688 static bool run_local_convert_string(int dummy)
13690 TALLOC_CTX *tmp_ctx = talloc_new(NULL);
13691 const char *test_strings[2] = { "March", "M\303\244rz" };
13695 for (i=0; i<2; i++) {
13696 const char *str = test_strings[i];
13697 int len = strlen(str);
13698 size_t converted_size;
13701 memset(dst, 'X', sizeof(dst));
13703 /* first try with real source length */
13704 ret = convert_string_error(CH_UNIX, CH_UTF8,
13709 d_fprintf(stderr, "Failed to convert '%s' to CH_DISPLAY\n", str);
13713 if (converted_size != len) {
13714 d_fprintf(stderr, "Converted size of '%s' should be %d - got %d\n",
13715 str, len, (int)converted_size);
13719 if (strncmp(str, dst, converted_size) != 0) {
13720 d_fprintf(stderr, "Expected '%s' to match '%s'\n", str, dst);
13724 if (strlen(str) != converted_size) {
13725 d_fprintf(stderr, "Expected '%s' length %d - got %d\n", str,
13726 (int)strlen(str), (int)converted_size);
13730 if (dst[converted_size] != 'X') {
13731 d_fprintf(stderr, "Expected no termination of '%s'\n", dst);
13735 /* now with srclen==-1, this causes the nul to be
13737 ret = convert_string_error(CH_UNIX, CH_UTF8,
13742 d_fprintf(stderr, "Failed to convert '%s' to CH_DISPLAY\n", str);
13746 if (converted_size != len+1) {
13747 d_fprintf(stderr, "Converted size of '%s' should be %d - got %d\n",
13748 str, len, (int)converted_size);
13752 if (strncmp(str, dst, converted_size) != 0) {
13753 d_fprintf(stderr, "Expected '%s' to match '%s'\n", str, dst);
13757 if (len+1 != converted_size) {
13758 d_fprintf(stderr, "Expected '%s' length %d - got %d\n", str,
13759 len+1, (int)converted_size);
13763 if (dst[converted_size] != 'X') {
13764 d_fprintf(stderr, "Expected no termination of '%s'\n", dst);
13771 TALLOC_FREE(tmp_ctx);
13774 TALLOC_FREE(tmp_ctx);
13778 static bool run_local_string_to_sid(int dummy) {
13779 struct dom_sid sid;
13781 if (string_to_sid(&sid, "S--1-5-32-545")) {
13782 printf("allowing S--1-5-32-545\n");
13785 if (string_to_sid(&sid, "S-1-5-32-+545")) {
13786 printf("allowing S-1-5-32-+545\n");
13789 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")) {
13790 printf("allowing S-1-2-3-4-5-6-7-8-9-0-1-2-3-4-5-6-7-8-9-0\n");
13793 if (string_to_sid(&sid, "S-1-5-32-545-abc")) {
13794 printf("allowing S-1-5-32-545-abc\n");
13797 if (string_to_sid(&sid, "S-300-5-32-545")) {
13798 printf("allowing S-300-5-32-545\n");
13801 if (string_to_sid(&sid, "S-1-0xfffffffffffffe-32-545")) {
13802 printf("allowing S-1-0xfffffffffffffe-32-545\n");
13805 if (string_to_sid(&sid, "S-1-0xffffffffffff-5294967297-545")) {
13806 printf("allowing S-1-0xffffffffffff-5294967297-545\n");
13809 if (!string_to_sid(&sid, "S-1-0xfffffffffffe-32-545")) {
13810 printf("could not parse S-1-0xfffffffffffe-32-545\n");
13813 if (!string_to_sid(&sid, "S-1-5-32-545")) {
13814 printf("could not parse S-1-5-32-545\n");
13817 if (!dom_sid_equal(&sid, &global_sid_Builtin_Users)) {
13818 struct dom_sid_buf buf;
13819 printf("mis-parsed S-1-5-32-545 as %s\n",
13820 dom_sid_str_buf(&sid, &buf));
13826 static bool sid_to_string_test(const char *expected) {
13829 struct dom_sid sid;
13831 if (!string_to_sid(&sid, expected)) {
13832 printf("could not parse %s\n", expected);
13836 str = dom_sid_string(NULL, &sid);
13837 if (strcmp(str, expected)) {
13838 printf("Comparison failed (%s != %s)\n", str, expected);
13845 static bool run_local_sid_to_string(int dummy) {
13846 if (!sid_to_string_test("S-1-0xffffffffffff-1-1-1-1-1-1-1-1-1-1-1-1"))
13848 if (!sid_to_string_test("S-1-545"))
13850 if (!sid_to_string_test("S-255-3840-1-1-1-1"))
13855 static bool run_local_binary_to_sid(int dummy) {
13857 struct dom_sid *sid = talloc(NULL, struct dom_sid);
13858 static const uint8_t good_binary_sid[] = {
13859 0x1, /* revision number */
13860 15, /* num auths */
13861 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, /* id_auth */
13862 0x1, 0x1, 0x1, 0x1, /* auth[0] */
13863 0x1, 0x1, 0x1, 0x1, /* auth[1] */
13864 0x1, 0x1, 0x1, 0x1, /* auth[2] */
13865 0x1, 0x1, 0x1, 0x1, /* auth[3] */
13866 0x1, 0x1, 0x1, 0x1, /* auth[4] */
13867 0x1, 0x1, 0x1, 0x1, /* auth[5] */
13868 0x1, 0x1, 0x1, 0x1, /* auth[6] */
13869 0x1, 0x1, 0x1, 0x1, /* auth[7] */
13870 0x1, 0x1, 0x1, 0x1, /* auth[8] */
13871 0x1, 0x1, 0x1, 0x1, /* auth[9] */
13872 0x1, 0x1, 0x1, 0x1, /* auth[10] */
13873 0x1, 0x1, 0x1, 0x1, /* auth[11] */
13874 0x1, 0x1, 0x1, 0x1, /* auth[12] */
13875 0x1, 0x1, 0x1, 0x1, /* auth[13] */
13876 0x1, 0x1, 0x1, 0x1, /* auth[14] */
13879 static const uint8_t long_binary_sid[] = {
13880 0x1, /* revision number */
13881 15, /* num auths */
13882 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, /* id_auth */
13883 0x1, 0x1, 0x1, 0x1, /* auth[0] */
13884 0x1, 0x1, 0x1, 0x1, /* auth[1] */
13885 0x1, 0x1, 0x1, 0x1, /* auth[2] */
13886 0x1, 0x1, 0x1, 0x1, /* auth[3] */
13887 0x1, 0x1, 0x1, 0x1, /* auth[4] */
13888 0x1, 0x1, 0x1, 0x1, /* auth[5] */
13889 0x1, 0x1, 0x1, 0x1, /* auth[6] */
13890 0x1, 0x1, 0x1, 0x1, /* auth[7] */
13891 0x1, 0x1, 0x1, 0x1, /* auth[8] */
13892 0x1, 0x1, 0x1, 0x1, /* auth[9] */
13893 0x1, 0x1, 0x1, 0x1, /* auth[10] */
13894 0x1, 0x1, 0x1, 0x1, /* auth[11] */
13895 0x1, 0x1, 0x1, 0x1, /* auth[12] */
13896 0x1, 0x1, 0x1, 0x1, /* auth[13] */
13897 0x1, 0x1, 0x1, 0x1, /* auth[14] */
13898 0x1, 0x1, 0x1, 0x1, /* auth[15] */
13899 0x1, 0x1, 0x1, 0x1, /* auth[16] */
13900 0x1, 0x1, 0x1, 0x1, /* auth[17] */
13903 static const uint8_t long_binary_sid2[] = {
13904 0x1, /* revision number */
13905 32, /* num auths */
13906 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, /* id_auth */
13907 0x1, 0x1, 0x1, 0x1, /* auth[0] */
13908 0x1, 0x1, 0x1, 0x1, /* auth[1] */
13909 0x1, 0x1, 0x1, 0x1, /* auth[2] */
13910 0x1, 0x1, 0x1, 0x1, /* auth[3] */
13911 0x1, 0x1, 0x1, 0x1, /* auth[4] */
13912 0x1, 0x1, 0x1, 0x1, /* auth[5] */
13913 0x1, 0x1, 0x1, 0x1, /* auth[6] */
13914 0x1, 0x1, 0x1, 0x1, /* auth[7] */
13915 0x1, 0x1, 0x1, 0x1, /* auth[8] */
13916 0x1, 0x1, 0x1, 0x1, /* auth[9] */
13917 0x1, 0x1, 0x1, 0x1, /* auth[10] */
13918 0x1, 0x1, 0x1, 0x1, /* auth[11] */
13919 0x1, 0x1, 0x1, 0x1, /* auth[12] */
13920 0x1, 0x1, 0x1, 0x1, /* auth[13] */
13921 0x1, 0x1, 0x1, 0x1, /* auth[14] */
13922 0x1, 0x1, 0x1, 0x1, /* auth[15] */
13923 0x1, 0x1, 0x1, 0x1, /* auth[16] */
13924 0x1, 0x1, 0x1, 0x1, /* auth[17] */
13925 0x1, 0x1, 0x1, 0x1, /* auth[18] */
13926 0x1, 0x1, 0x1, 0x1, /* auth[19] */
13927 0x1, 0x1, 0x1, 0x1, /* auth[20] */
13928 0x1, 0x1, 0x1, 0x1, /* auth[21] */
13929 0x1, 0x1, 0x1, 0x1, /* auth[22] */
13930 0x1, 0x1, 0x1, 0x1, /* auth[23] */
13931 0x1, 0x1, 0x1, 0x1, /* auth[24] */
13932 0x1, 0x1, 0x1, 0x1, /* auth[25] */
13933 0x1, 0x1, 0x1, 0x1, /* auth[26] */
13934 0x1, 0x1, 0x1, 0x1, /* auth[27] */
13935 0x1, 0x1, 0x1, 0x1, /* auth[28] */
13936 0x1, 0x1, 0x1, 0x1, /* auth[29] */
13937 0x1, 0x1, 0x1, 0x1, /* auth[30] */
13938 0x1, 0x1, 0x1, 0x1, /* auth[31] */
13941 ret = sid_parse(good_binary_sid, sizeof(good_binary_sid), sid);
13945 ret = sid_parse(long_binary_sid2, sizeof(long_binary_sid2), sid);
13949 ret = sid_parse(long_binary_sid, sizeof(long_binary_sid), sid);
13956 /* Split a path name into filename and stream name components. Canonicalise
13957 * such that an implicit $DATA token is always explicit.
13959 * The "specification" of this function can be found in the
13960 * run_local_stream_name() function in torture.c, I've tried those
13961 * combinations against a W2k3 server.
13964 static NTSTATUS split_ntfs_stream_name(TALLOC_CTX *mem_ctx, const char *fname,
13965 char **pbase, char **pstream)
13968 char *stream = NULL;
13969 char *sname; /* stream name */
13970 const char *stype; /* stream type */
13972 DEBUG(10, ("split_ntfs_stream_name called for [%s]\n", fname));
13974 sname = strchr_m(fname, ':');
13976 if (sname == NULL) {
13977 if (pbase != NULL) {
13978 base = talloc_strdup(mem_ctx, fname);
13979 NT_STATUS_HAVE_NO_MEMORY(base);
13984 if (pbase != NULL) {
13985 base = talloc_strndup(mem_ctx, fname, PTR_DIFF(sname, fname));
13986 NT_STATUS_HAVE_NO_MEMORY(base);
13991 stype = strchr_m(sname, ':');
13993 if (stype == NULL) {
13994 sname = talloc_strdup(mem_ctx, sname);
13998 if (strcasecmp_m(stype, ":$DATA") != 0) {
14000 * If there is an explicit stream type, so far we only
14001 * allow $DATA. Is there anything else allowed? -- vl
14003 DEBUG(10, ("[%s] is an invalid stream type\n", stype));
14005 return NT_STATUS_OBJECT_NAME_INVALID;
14007 sname = talloc_strndup(mem_ctx, sname, PTR_DIFF(stype, sname));
14011 if (sname == NULL) {
14013 return NT_STATUS_NO_MEMORY;
14016 if (sname[0] == '\0') {
14018 * no stream name, so no stream
14023 if (pstream != NULL) {
14024 stream = talloc_asprintf(mem_ctx, "%s:%s", sname, stype);
14025 if (stream == NULL) {
14026 TALLOC_FREE(sname);
14028 return NT_STATUS_NO_MEMORY;
14031 * upper-case the type field
14033 (void)strupper_m(strchr_m(stream, ':')+1);
14037 if (pbase != NULL) {
14040 if (pstream != NULL) {
14043 return NT_STATUS_OK;
14046 static bool test_stream_name(const char *fname, const char *expected_base,
14047 const char *expected_stream,
14048 NTSTATUS expected_status)
14052 char *stream = NULL;
14054 status = split_ntfs_stream_name(talloc_tos(), fname, &base, &stream);
14055 if (!NT_STATUS_EQUAL(status, expected_status)) {
14059 if (!NT_STATUS_IS_OK(status)) {
14063 if (base == NULL) goto error;
14065 if (strcmp(expected_base, base) != 0) goto error;
14067 if ((expected_stream != NULL) && (stream == NULL)) goto error;
14068 if ((expected_stream == NULL) && (stream != NULL)) goto error;
14070 if ((stream != NULL) && (strcmp(expected_stream, stream) != 0))
14074 TALLOC_FREE(stream);
14078 d_fprintf(stderr, "Do test_stream(%s, %s, %s, %s)\n",
14079 fname, expected_base ? expected_base : "<NULL>",
14080 expected_stream ? expected_stream : "<NULL>",
14081 nt_errstr(expected_status));
14082 d_fprintf(stderr, "-> base=%s, stream=%s, status=%s\n",
14083 base ? base : "<NULL>", stream ? stream : "<NULL>",
14084 nt_errstr(status));
14086 TALLOC_FREE(stream);
14090 static bool run_local_stream_name(int dummy)
14094 ret &= test_stream_name(
14095 "bla", "bla", NULL, NT_STATUS_OK);
14096 ret &= test_stream_name(
14097 "bla::$DATA", "bla", NULL, NT_STATUS_OK);
14098 ret &= test_stream_name(
14099 "bla:blub:", "bla", NULL, NT_STATUS_OBJECT_NAME_INVALID);
14100 ret &= test_stream_name(
14101 "bla::", NULL, NULL, NT_STATUS_OBJECT_NAME_INVALID);
14102 ret &= test_stream_name(
14103 "bla::123", "bla", NULL, NT_STATUS_OBJECT_NAME_INVALID);
14104 ret &= test_stream_name(
14105 "bla:$DATA", "bla", "$DATA:$DATA", NT_STATUS_OK);
14106 ret &= test_stream_name(
14107 "bla:x:$DATA", "bla", "x:$DATA", NT_STATUS_OK);
14108 ret &= test_stream_name(
14109 "bla:x", "bla", "x:$DATA", NT_STATUS_OK);
14114 static bool data_blob_equal(DATA_BLOB a, DATA_BLOB b)
14116 if (a.length != b.length) {
14117 printf("a.length=%d != b.length=%d\n",
14118 (int)a.length, (int)b.length);
14121 if (memcmp(a.data, b.data, a.length) != 0) {
14122 printf("a.data and b.data differ\n");
14128 static bool run_local_memcache(int dummy)
14130 struct memcache *cache;
14131 DATA_BLOB k1, k2, k3, k4, k5;
14135 TALLOC_CTX *mem_ctx;
14141 size_t size1, size2;
14144 mem_ctx = talloc_init("foo");
14145 if (mem_ctx == NULL) {
14149 /* STAT_CACHE TESTS */
14151 cache = memcache_init(NULL, sizeof(void *) == 8 ? 200 : 100);
14153 if (cache == NULL) {
14154 printf("memcache_init failed\n");
14158 d1 = data_blob_const("d1", 2);
14159 d3 = data_blob_const("d3", 2);
14161 k1 = data_blob_const("d1", 2);
14162 k2 = data_blob_const("d2", 2);
14163 k3 = data_blob_const("d3", 2);
14164 k4 = data_blob_const("d4", 2);
14165 k5 = data_blob_const("d5", 2);
14167 memcache_add(cache, STAT_CACHE, k1, d1);
14169 if (!memcache_lookup(cache, STAT_CACHE, k1, &v1)) {
14170 printf("could not find k1\n");
14173 if (!data_blob_equal(d1, v1)) {
14177 memcache_add(cache, STAT_CACHE, k1, d3);
14179 if (!memcache_lookup(cache, STAT_CACHE, k1, &v3)) {
14180 printf("could not find replaced k1\n");
14183 if (!data_blob_equal(d3, v3)) {
14187 TALLOC_FREE(cache);
14189 /* GETWD_CACHE TESTS */
14190 str1 = talloc_strdup(mem_ctx, "string1");
14191 if (str1 == NULL) {
14194 ptr2 = str1; /* Keep an alias for comparison. */
14196 str2 = talloc_strdup(mem_ctx, "string2");
14197 if (str2 == NULL) {
14201 cache = memcache_init(NULL, sizeof(void *) == 8 ? 200 : 100);
14202 if (cache == NULL) {
14203 printf("memcache_init failed\n");
14207 memcache_add_talloc(cache, GETWD_CACHE, k2, &str1);
14208 /* str1 == NULL now. */
14209 ptr1 = memcache_lookup_talloc(cache, GETWD_CACHE, k2);
14210 if (ptr1 == NULL) {
14211 printf("could not find k2\n");
14214 if (ptr1 != ptr2) {
14215 printf("fetch of k2 got wrong string\n");
14219 /* Add a blob to ensure k2 gets purged. */
14220 d3 = data_blob_talloc_zero(mem_ctx, 180);
14221 memcache_add(cache, STAT_CACHE, k3, d3);
14223 ptr2 = memcache_lookup_talloc(cache, GETWD_CACHE, k2);
14224 if (ptr2 != NULL) {
14225 printf("Did find k2, should have been purged\n");
14230 * Test that talloc size also is accounted in memcache and
14231 * causes purge of other object.
14234 str1 = talloc_zero_size(mem_ctx, 100);
14235 str2 = talloc_zero_size(mem_ctx, 100);
14237 memcache_add_talloc(cache, GETWD_CACHE, k4, &str1);
14238 memcache_add_talloc(cache, GETWD_CACHE, k5, &str1);
14240 ptr3 = memcache_lookup_talloc(cache, GETWD_CACHE, k4);
14241 if (ptr3 != NULL) {
14242 printf("Did find k4, should have been purged\n");
14247 * Test that adding a duplicate non-talloced
14248 * key/value on top of a talloced key/value takes account
14249 * of the talloc_freed value size.
14251 TALLOC_FREE(cache);
14252 TALLOC_FREE(mem_ctx);
14254 mem_ctx = talloc_init("key_replace");
14255 if (mem_ctx == NULL) {
14259 cache = memcache_init(NULL, sizeof(void *) == 8 ? 200 : 100);
14260 if (cache == NULL) {
14265 * Add a 100 byte talloced string. This will
14266 * store a (4 or 8 byte) pointer and record the
14267 * total talloced size.
14269 str1 = talloc_zero_size(mem_ctx, 100);
14270 memcache_add_talloc(cache, GETWD_CACHE, k4, &str1);
14272 * Now overwrite with a small talloced
14273 * value. This should fit in the existing size
14274 * and the total talloced size should be removed
14275 * from the cache size.
14277 str1 = talloc_zero_size(mem_ctx, 2);
14278 memcache_add_talloc(cache, GETWD_CACHE, k4, &str1);
14280 * Now store a 20 byte string. If the
14281 * total talloced size wasn't accounted for
14282 * and removed in the overwrite, then this
14285 str2 = talloc_zero_size(mem_ctx, 20);
14286 memcache_add_talloc(cache, GETWD_CACHE, k5, &str2);
14288 ptr3 = memcache_lookup_talloc(cache, GETWD_CACHE, k4);
14289 if (ptr3 == NULL) {
14290 printf("Did not find k4, should not have been purged\n");
14294 TALLOC_FREE(cache);
14295 TALLOC_FREE(mem_ctx);
14297 mem_ctx = talloc_init("foo");
14298 if (mem_ctx == NULL) {
14302 cache = memcache_init(NULL, 0);
14303 if (cache == NULL) {
14307 str1 = talloc_strdup(mem_ctx, "string1");
14308 if (str1 == NULL) {
14311 str2 = talloc_strdup(mem_ctx, "string2");
14312 if (str2 == NULL) {
14315 memcache_add_talloc(cache, SINGLETON_CACHE_TALLOC,
14316 data_blob_string_const("torture"), &str1);
14317 size1 = talloc_total_size(cache);
14319 memcache_add_talloc(cache, SINGLETON_CACHE_TALLOC,
14320 data_blob_string_const("torture"), &str2);
14321 size2 = talloc_total_size(cache);
14323 printf("size1=%d, size2=%d\n", (int)size1, (int)size2);
14325 if (size2 > size1) {
14326 printf("memcache leaks memory!\n");
14332 TALLOC_FREE(cache);
14336 static void wbclient_done(struct tevent_req *req)
14339 struct winbindd_response *wb_resp;
14340 int *i = (int *)tevent_req_callback_data_void(req);
14342 wbc_err = wb_trans_recv(req, req, &wb_resp);
14345 d_printf("wb_trans_recv %d returned %s\n", *i, wbcErrorString(wbc_err));
14348 static bool run_wbclient_multi_ping(int dummy)
14350 struct tevent_context *ev;
14351 struct wb_context **wb_ctx;
14352 struct winbindd_request wb_req;
14353 bool result = false;
14356 BlockSignals(True, SIGPIPE);
14358 ev = tevent_context_init(talloc_tos());
14363 wb_ctx = talloc_array(ev, struct wb_context *, torture_nprocs);
14364 if (wb_ctx == NULL) {
14368 ZERO_STRUCT(wb_req);
14369 wb_req.cmd = WINBINDD_PING;
14371 d_printf("torture_nprocs=%d, numops=%d\n", (int)torture_nprocs, (int)torture_numops);
14373 for (i=0; i<torture_nprocs; i++) {
14374 wb_ctx[i] = wb_context_init(ev, NULL);
14375 if (wb_ctx[i] == NULL) {
14378 for (j=0; j<torture_numops; j++) {
14379 struct tevent_req *req;
14380 req = wb_trans_send(ev, ev, wb_ctx[i],
14381 (j % 2) == 0, &wb_req);
14385 tevent_req_set_callback(req, wbclient_done, &i);
14391 while (i < torture_nprocs * torture_numops) {
14392 tevent_loop_once(ev);
14401 static bool dbtrans_inc(struct db_context *db)
14403 struct db_record *rec;
14409 rec = dbwrap_fetch_locked(db, db, string_term_tdb_data("transtest"));
14411 printf(__location__ "fetch_lock failed\n");
14415 value = dbwrap_record_get_value(rec);
14417 if (value.dsize != sizeof(uint32_t)) {
14418 printf(__location__ "value.dsize = %d\n",
14423 memcpy(&val, value.dptr, sizeof(val));
14426 status = dbwrap_record_store(
14427 rec, make_tdb_data((uint8_t *)&val, sizeof(val)), 0);
14428 if (!NT_STATUS_IS_OK(status)) {
14429 printf(__location__ "store failed: %s\n",
14430 nt_errstr(status));
14440 static bool run_local_dbtrans(int dummy)
14442 struct db_context *db;
14443 struct db_record *rec;
14449 db = db_open(talloc_tos(), "transtest.tdb", 0, TDB_DEFAULT,
14450 O_RDWR|O_CREAT, 0600, DBWRAP_LOCK_ORDER_1,
14453 printf("Could not open transtest.db\n");
14457 res = dbwrap_transaction_start(db);
14459 printf(__location__ "transaction_start failed\n");
14463 rec = dbwrap_fetch_locked(db, db, string_term_tdb_data("transtest"));
14465 printf(__location__ "fetch_lock failed\n");
14469 value = dbwrap_record_get_value(rec);
14471 if (value.dptr == NULL) {
14473 status = dbwrap_record_store(
14474 rec, make_tdb_data((uint8_t *)&initial,
14477 if (!NT_STATUS_IS_OK(status)) {
14478 printf(__location__ "store returned %s\n",
14479 nt_errstr(status));
14486 res = dbwrap_transaction_commit(db);
14488 printf(__location__ "transaction_commit failed\n");
14493 uint32_t val, val2;
14496 res = dbwrap_transaction_start(db);
14498 printf(__location__ "transaction_start failed\n");
14502 status = dbwrap_fetch_uint32_bystring(db, "transtest", &val);
14503 if (!NT_STATUS_IS_OK(status)) {
14504 printf(__location__ "dbwrap_fetch_uint32 failed: %s\n",
14505 nt_errstr(status));
14509 for (i=0; i<10; i++) {
14510 if (!dbtrans_inc(db)) {
14515 status = dbwrap_fetch_uint32_bystring(db, "transtest", &val2);
14516 if (!NT_STATUS_IS_OK(status)) {
14517 printf(__location__ "dbwrap_fetch_uint32 failed: %s\n",
14518 nt_errstr(status));
14522 if (val2 != val + 10) {
14523 printf(__location__ "val=%d, val2=%d\n",
14524 (int)val, (int)val2);
14528 printf("val2=%d\r", val2);
14530 res = dbwrap_transaction_commit(db);
14532 printf(__location__ "transaction_commit failed\n");
14542 * Just a dummy test to be run under a debugger. There's no real way
14543 * to inspect the tevent_poll specific function from outside of
14547 static bool run_local_tevent_poll(int dummy)
14549 struct tevent_context *ev;
14550 struct tevent_fd *fd1, *fd2;
14551 bool result = false;
14553 ev = tevent_context_init_byname(NULL, "poll");
14555 d_fprintf(stderr, "tevent_context_init_byname failed\n");
14559 fd1 = tevent_add_fd(ev, ev, 2, 0, NULL, NULL);
14561 d_fprintf(stderr, "tevent_add_fd failed\n");
14564 fd2 = tevent_add_fd(ev, ev, 3, 0, NULL, NULL);
14566 d_fprintf(stderr, "tevent_add_fd failed\n");
14571 fd2 = tevent_add_fd(ev, ev, 1, 0, NULL, NULL);
14573 d_fprintf(stderr, "tevent_add_fd failed\n");
14583 static bool run_local_hex_encode_buf(int dummy)
14589 for (i=0; i<sizeof(src); i++) {
14592 hex_encode_buf(buf, src, sizeof(src));
14593 if (strcmp(buf, "0001020304050607") != 0) {
14596 hex_encode_buf(buf, NULL, 0);
14597 if (buf[0] != '\0') {
14603 static const char *remove_duplicate_addrs2_test_strings_vector[] = {
14625 "1001:1111:1111:1000:0:1111:1111:1111",
14634 static const char *remove_duplicate_addrs2_test_strings_result[] = {
14648 "1001:1111:1111:1000:0:1111:1111:1111"
14651 static bool run_local_remove_duplicate_addrs2(int dummy)
14653 struct samba_sockaddr test_vector[28];
14656 /* Construct the sockaddr_storage test vector. */
14657 for (i = 0; i < 28; i++) {
14658 struct addrinfo hints;
14659 struct addrinfo *res = NULL;
14662 memset(&hints, '\0', sizeof(hints));
14663 hints.ai_flags = AI_NUMERICHOST;
14664 ret = getaddrinfo(remove_duplicate_addrs2_test_strings_vector[i],
14669 fprintf(stderr, "getaddrinfo failed on [%s]\n",
14670 remove_duplicate_addrs2_test_strings_vector[i]);
14673 memset(&test_vector[i], '\0', sizeof(test_vector[i]));
14674 memcpy(&test_vector[i].u.ss,
14680 count = remove_duplicate_addrs2(test_vector, i);
14683 fprintf(stderr, "count wrong (%zu) should be 14\n",
14688 for (i = 0; i < count; i++) {
14689 char addr[INET6_ADDRSTRLEN];
14691 print_sockaddr(addr, sizeof(addr), &test_vector[i].u.ss);
14693 if (strcmp(addr, remove_duplicate_addrs2_test_strings_result[i]) != 0) {
14694 fprintf(stderr, "mismatch on [%zu] [%s] [%s]\n",
14697 remove_duplicate_addrs2_test_strings_result[i]);
14702 printf("run_local_remove_duplicate_addrs2: success\n");
14706 static bool run_local_tdb_opener(int dummy)
14712 t = tdb_open("test.tdb", 1000, TDB_CLEAR_IF_FIRST,
14713 O_RDWR|O_CREAT, 0755);
14715 perror("tdb_open failed");
14726 static bool run_local_tdb_writer(int dummy)
14732 t = tdb_open("test.tdb", 1000, 0, O_RDWR|O_CREAT, 0755);
14734 perror("tdb_open failed");
14738 val.dptr = (uint8_t *)&v;
14739 val.dsize = sizeof(v);
14745 ret = tdb_store(t, val, val, 0);
14747 printf("%s\n", tdb_errorstr(t));
14752 data = tdb_fetch(t, val);
14753 if (data.dptr != NULL) {
14754 SAFE_FREE(data.dptr);
14760 static bool run_local_canonicalize_path(int dummy)
14762 const char *src[] = {
14769 ".././././../../../boo",
14781 "/foo/bar/../baz/",
14782 "////////////////",
14783 "/////////./././././.",
14784 "/./.././../.boo/../baz",
14785 "/a/component/path",
14786 "/a/component/path/",
14787 "/a/component/path/..",
14788 "/a/component/../path/",
14789 "///a/./././///component/../////path/",
14792 const char *dst[] = {
14815 "/a/component/path",
14816 "/a/component/path",
14824 for (i = 0; src[i] != NULL; i++) {
14825 char *d = canonicalize_absolute_path(talloc_tos(), src[i]);
14827 perror("talloc fail\n");
14830 if (strcmp(d, dst[i]) != 0) {
14832 "canonicalize mismatch %s -> %s != %s",
14833 src[i], d, dst[i]);
14840 struct session_setup_nt1_truncated_state {
14845 static void smb1_session_setup_nt1_truncated_done(struct tevent_req *subreq);
14847 static struct tevent_req *smb1_session_setup_nt1_truncated_send(
14848 TALLOC_CTX *mem_ctx,
14849 struct tevent_context *ev,
14850 struct smbXcli_conn *conn)
14852 uint16_t *vwv = NULL;
14853 uint8_t *bytes = NULL;
14854 const char *pass = "12345678";
14855 const char *uname = "z";
14856 struct session_setup_nt1_truncated_state *state = NULL;
14857 struct tevent_req *req = NULL;
14858 struct tevent_req *subreq = NULL;
14860 req = tevent_req_create(mem_ctx,
14862 struct session_setup_nt1_truncated_state);
14866 vwv = &state->vwv[0];
14867 bytes = &state->bytes[0];
14869 SCVAL(vwv+0, 0, 0xff);
14870 SCVAL(vwv+0, 1, 0);
14871 SSVAL(vwv+1, 0, 0);
14872 SSVAL(vwv+2, 0, 8192);
14873 SSVAL(vwv+3, 0, 2);
14874 SSVAL(vwv+4, 0, 1);
14875 SIVAL(vwv+5, 0, 0);
14876 SSVAL(vwv+7, 0, strlen(pass)); /* OEMPasswordLen */
14877 SSVAL(vwv+8, 0, 0); /* UnicodePasswordLen */
14878 SSVAL(vwv+9, 0, 0); /* reserved */
14879 SSVAL(vwv+10, 0, 0); /* reserved */
14880 SIVAL(vwv+11, 0, CAP_STATUS32);
14882 memcpy(bytes, pass, strlen(pass));
14883 bytes += strlen(pass);
14884 memcpy(bytes, uname, strlen(uname)+1);
14886 subreq = smb1cli_req_send(state, ev, conn,
14888 0, /* additional_flags */
14889 0, /* clear_flags */
14890 0, /* additional_flags2 */
14891 0, /* clear_flags2 */
14892 10000, /* timeout_msec */
14895 NULL, /* session */
14898 strlen(pass), /* Truncate length at password. */
14900 if (tevent_req_nomem(subreq, req)) {
14901 return tevent_req_post(req, ev);
14903 tevent_req_set_callback(subreq,
14904 smb1_session_setup_nt1_truncated_done,
14909 static void smb1_session_setup_nt1_truncated_done(struct tevent_req *subreq)
14911 struct tevent_req *req =
14912 tevent_req_callback_data(subreq,
14913 struct tevent_req);
14914 struct session_setup_nt1_truncated_state *state =
14915 tevent_req_data(req,
14916 struct session_setup_nt1_truncated_state);
14918 struct smb1cli_req_expected_response expected[] = {
14920 .status = NT_STATUS_OK,
14925 status = smb1cli_req_recv(subreq, state,
14930 NULL, /* pvwv_offset */
14933 NULL, /* pbytes_offset */
14935 expected, ARRAY_SIZE(expected));
14936 TALLOC_FREE(subreq);
14937 if (tevent_req_nterror(req, status)) {
14940 tevent_req_done(req);
14943 static NTSTATUS smb1_session_setup_nt1_truncated_recv(struct tevent_req *req)
14945 return tevent_req_simple_recv_ntstatus(req);
14948 static bool run_smb1_truncated_sesssetup(int dummy)
14950 struct tevent_context *ev;
14951 struct tevent_req *req;
14952 struct smbXcli_conn *conn;
14953 struct sockaddr_storage ss;
14958 printf("Starting send truncated SMB1 sesssetup.\n");
14960 ok = resolve_name(host, &ss, 0x20, true);
14962 d_fprintf(stderr, "Could not resolve name %s\n", host);
14966 status = open_socket_out(&ss, 445, 10000, &fd);
14967 if (!NT_STATUS_IS_OK(status)) {
14968 d_fprintf(stderr, "open_socket_out failed: %s\n",
14969 nt_errstr(status));
14973 conn = smbXcli_conn_create(talloc_tos(), fd, host, SMB_SIGNING_OFF, 0,
14975 if (conn == NULL) {
14976 d_fprintf(stderr, "smbXcli_conn_create failed\n");
14980 status = smbXcli_negprot(conn,
14987 if (!NT_STATUS_IS_OK(status)) {
14988 d_fprintf(stderr, "smbXcli_negprot failed!\n");
14992 ev = samba_tevent_context_init(talloc_tos());
14994 d_fprintf(stderr, "samba_tevent_context_init failed\n");
14998 req = smb1_session_setup_nt1_truncated_send(ev, ev, conn);
15000 d_fprintf(stderr, "smb1_session_setup_nt1_truncated_send failed\n");
15004 ok = tevent_req_poll_ntstatus(req, ev, &status);
15006 d_fprintf(stderr, "tevent_req_poll failed with status %s\n",
15007 nt_errstr(status));
15011 status = smb1_session_setup_nt1_truncated_recv(req);
15012 if (!NT_STATUS_IS_OK(status)) {
15013 d_fprintf(stderr, "smb1_session_setup_nt1_truncated_recv returned "
15014 "%s, expected NT_STATUS_OK\n",
15015 nt_errstr(status));
15023 struct smb1_negotiate_exit_state {
15027 static void smb1_negotiate_exit_done(struct tevent_req *subreq);
15029 static struct tevent_req *smb1_negotiate_exit_send(
15030 TALLOC_CTX *mem_ctx,
15031 struct tevent_context *ev,
15032 struct smbXcli_conn *conn)
15034 struct smb1_negotiate_exit_state *state = NULL;
15035 struct tevent_req *req = NULL;
15036 struct tevent_req *subreq = NULL;
15038 req = tevent_req_create(mem_ctx,
15040 struct smb1_negotiate_exit_state);
15044 subreq = smb1cli_req_send(state, ev, conn,
15046 0, /* additional_flags */
15047 0, /* clear_flags */
15048 0, /* additional_flags2 */
15049 0, /* clear_flags2 */
15050 10000, /* timeout_msec */
15053 NULL, /* session */
15058 if (tevent_req_nomem(subreq, req)) {
15059 return tevent_req_post(req, ev);
15061 tevent_req_set_callback(subreq,
15062 smb1_negotiate_exit_done,
15067 static void smb1_negotiate_exit_done(struct tevent_req *subreq)
15069 struct tevent_req *req =
15070 tevent_req_callback_data(subreq,
15071 struct tevent_req);
15072 struct smb1_negotiate_exit_state *state =
15073 tevent_req_data(req,
15074 struct smb1_negotiate_exit_state);
15076 struct smb1cli_req_expected_response expected[] = {
15078 .status = NT_STATUS_OK,
15083 status = smb1cli_req_recv(subreq, state,
15088 NULL, /* pvwv_offset */
15091 NULL, /* pbytes_offset */
15093 expected, ARRAY_SIZE(expected));
15094 TALLOC_FREE(subreq);
15095 if (tevent_req_nterror(req, status)) {
15098 tevent_req_done(req);
15101 static NTSTATUS smb1_negotiate_exit_recv(struct tevent_req *req)
15103 return tevent_req_simple_recv_ntstatus(req);
15106 static bool do_smb1_exit(TALLOC_CTX *mem_ctx,
15107 struct tevent_context *ev,
15108 struct smbXcli_conn *conn)
15110 struct tevent_req *req;
15113 NTSTATUS expected_status = NT_STATUS_DOS(ERRSRV, ERRinvnid);;
15115 req = smb1_negotiate_exit_send(ev, ev, conn);
15117 d_fprintf(stderr, "smb1_negotiate_exit_send failed\n");
15121 ok = tevent_req_poll_ntstatus(req, ev, &status);
15123 d_fprintf(stderr, "tevent_req_poll failed with status %s\n",
15124 nt_errstr(status));
15128 status = smb1_negotiate_exit_recv(req);
15129 if (!NT_STATUS_EQUAL(status, expected_status)) {
15130 d_fprintf(stderr, "smb1_negotiate_exit_recv returned "
15131 "%s, expected ERRSRV, ERRinvnid\n",
15132 nt_errstr(status));
15138 static bool run_smb1_negotiate_exit(int dummy)
15140 struct tevent_context *ev;
15141 struct smbXcli_conn *conn;
15142 struct sockaddr_storage ss;
15147 printf("Starting send SMB1 negotiate+exit.\n");
15149 ok = resolve_name(host, &ss, 0x20, true);
15151 d_fprintf(stderr, "Could not resolve name %s\n", host);
15155 status = open_socket_out(&ss, 445, 10000, &fd);
15156 if (!NT_STATUS_IS_OK(status)) {
15157 d_fprintf(stderr, "open_socket_out failed: %s\n",
15158 nt_errstr(status));
15162 conn = smbXcli_conn_create(talloc_tos(), fd, host, SMB_SIGNING_OFF, 0,
15164 if (conn == NULL) {
15165 d_fprintf(stderr, "smbXcli_conn_create failed\n");
15169 status = smbXcli_negprot(conn,
15176 if (!NT_STATUS_IS_OK(status)) {
15177 d_fprintf(stderr, "smbXcli_negprot failed!\n");
15181 ev = samba_tevent_context_init(talloc_tos());
15183 d_fprintf(stderr, "samba_tevent_context_init failed\n");
15188 * Call do_smb1_exit twice to catch a server crash, the
15189 * server sends the first return code then crashes.
15191 ok = do_smb1_exit(ev, ev, conn);
15193 d_fprintf(stderr, "do_smb1_exit (1) failed\n");
15196 ok = do_smb1_exit(ev, ev, conn);
15198 d_fprintf(stderr, "do_smb1_exit (2) failed\n");
15206 static bool run_smb1_negotiate_tcon(int dummy)
15208 struct cli_state *cli = NULL;
15210 uint16_t max_xmit = 0;
15213 printf("Starting send SMB1 negotiate+tcon.\n");
15214 cli = open_nbt_connection();
15216 d_fprintf(stderr, "open_nbt_connection failed!\n");
15219 smbXcli_conn_set_sockopt(cli->conn, sockops);
15221 status = smbXcli_negprot(cli->conn,
15228 if (!NT_STATUS_IS_OK(status)) {
15229 d_fprintf(stderr, "smbXcli_negprot failed %s!\n",
15230 nt_errstr(status));
15233 status = cli_raw_tcon(cli,
15239 if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
15240 d_fprintf(stderr, "cli_raw_tcon failed - got %s "
15241 "(should get NT_STATUS_ACCESS_DENIED)!\n",
15242 nt_errstr(status));
15248 static bool run_ign_bad_negprot(int dummy)
15250 struct tevent_context *ev;
15251 struct tevent_req *req;
15252 struct smbXcli_conn *conn;
15253 struct sockaddr_storage ss;
15258 printf("starting ignore bad negprot\n");
15260 ok = resolve_name(host, &ss, 0x20, true);
15262 d_fprintf(stderr, "Could not resolve name %s\n", host);
15266 status = open_socket_out(&ss, 445, 10000, &fd);
15267 if (!NT_STATUS_IS_OK(status)) {
15268 d_fprintf(stderr, "open_socket_out failed: %s\n",
15269 nt_errstr(status));
15273 conn = smbXcli_conn_create(talloc_tos(), fd, host, SMB_SIGNING_OFF, 0,
15275 if (conn == NULL) {
15276 d_fprintf(stderr, "smbXcli_conn_create failed\n");
15280 status = smbXcli_negprot(conn,
15287 if (NT_STATUS_IS_OK(status)) {
15288 d_fprintf(stderr, "smbXcli_negprot succeeded!\n");
15292 ev = samba_tevent_context_init(talloc_tos());
15294 d_fprintf(stderr, "samba_tevent_context_init failed\n");
15298 req = smb1cli_session_setup_nt1_send(
15299 ev, ev, conn, 0, getpid(), NULL, 65503, 2, 1, 0, "", "",
15300 data_blob_null, data_blob_null, 0x40,
15301 "Windows 2000 2195", "Windows 2000 5.0");
15303 d_fprintf(stderr, "smb1cli_session_setup_nt1_send failed\n");
15307 ok = tevent_req_poll_ntstatus(req, ev, &status);
15309 d_fprintf(stderr, "tevent_req_poll failed\n");
15313 status = smb1cli_session_setup_nt1_recv(req, NULL, NULL, NULL, NULL,
15315 if (!NT_STATUS_EQUAL(status, NT_STATUS_CONNECTION_RESET)) {
15316 d_fprintf(stderr, "smb1cli_session_setup_nt1_recv returned "
15317 "%s, expected NT_STATUS_CONNECTION_RESET\n",
15318 nt_errstr(status));
15324 printf("starting ignore bad negprot\n");
15330 static double create_procs(bool (*fn)(int), bool *result)
15333 volatile pid_t *child_status;
15334 volatile bool *child_status_out;
15337 struct timeval start;
15341 child_status = (volatile pid_t *)anonymous_shared_allocate(sizeof(pid_t)*torture_nprocs);
15342 if (!child_status) {
15343 printf("Failed to setup shared memory\n");
15347 child_status_out = (volatile bool *)anonymous_shared_allocate(sizeof(bool)*torture_nprocs);
15348 if (!child_status_out) {
15349 printf("Failed to setup result status shared memory\n");
15353 for (i = 0; i < torture_nprocs; i++) {
15354 child_status[i] = 0;
15355 child_status_out[i] = True;
15358 start = timeval_current();
15360 for (i=0;i<torture_nprocs;i++) {
15363 pid_t mypid = getpid();
15364 sys_srandom(((int)mypid) ^ ((int)time(NULL)));
15366 slprintf(myname,sizeof(myname),"CLIENT%d", i);
15369 if (torture_open_connection(¤t_cli, i)) break;
15370 if (tries-- == 0) {
15371 printf("pid %d failed to start\n", (int)getpid());
15377 child_status[i] = getpid();
15379 while (child_status[i] && timeval_elapsed(&start) < 5) smb_msleep(2);
15381 child_status_out[i] = fn(i);
15388 for (i=0;i<torture_nprocs;i++) {
15389 if (child_status[i]) synccount++;
15391 if (synccount == torture_nprocs) break;
15393 } while (timeval_elapsed(&start) < 30);
15395 if (synccount != torture_nprocs) {
15396 printf("FAILED TO START %d CLIENTS (started %d)\n", torture_nprocs, synccount);
15398 return timeval_elapsed(&start);
15401 /* start the client load */
15402 start = timeval_current();
15404 for (i=0;i<torture_nprocs;i++) {
15405 child_status[i] = 0;
15408 printf("%d clients started\n", torture_nprocs);
15410 for (i=0;i<torture_nprocs;i++) {
15411 while (waitpid(0, &status, 0) == -1 && errno == EINTR) /* noop */ ;
15416 for (i=0;i<torture_nprocs;i++) {
15417 if (!child_status_out[i]) {
15421 return timeval_elapsed(&start);
15424 #define FLAG_MULTIPROC 1
15430 } torture_ops[] = {
15433 .fn = run_fdpasstest,
15437 .fn = run_locktest1,
15441 .fn = run_locktest2,
15445 .fn = run_locktest3,
15449 .fn = run_locktest4,
15453 .fn = run_locktest5,
15457 .fn = run_locktest6,
15461 .fn = run_locktest7,
15465 .fn = run_locktest8,
15469 .fn = run_locktest9a,
15473 .fn = run_locktest9b,
15477 .fn = run_locktest10,
15481 .fn = run_locktest11,
15485 .fn = run_locktest12,
15489 .fn = run_locktest13,
15493 .fn = run_unlinktest,
15497 .fn = run_browsetest,
15501 .fn = run_attrtest,
15505 .fn = run_trans2test,
15509 .fn = run_maxfidtest,
15510 .flags = FLAG_MULTIPROC,
15515 .flags = FLAG_MULTIPROC,
15518 .name = "RANDOMIPC",
15519 .fn = run_randomipc,
15522 .name = "NEGNOWAIT",
15523 .fn = run_negprot_nowait,
15545 #ifdef HAVE_KERNEL_OPLOCKS_LINUX
15557 .fn = run_dirtest1,
15560 .name = "DIR-CREATETIME",
15561 .fn = run_dir_createtime,
15565 .fn = torture_denytest1,
15569 .fn = torture_denytest2,
15573 .fn = run_tcon_test,
15577 .fn = run_tcon_devtype_test,
15581 .fn = run_readwritetest,
15585 .fn = run_readwritemulti,
15586 .flags = FLAG_MULTIPROC
15590 .fn = run_readwritelarge,
15593 .name = "RW-SIGNING",
15594 .fn = run_readwritelarge_signtest,
15598 .fn = run_opentest,
15602 .fn = run_simple_posix_open_test,
15605 .name = "POSIX-APPEND",
15606 .fn = run_posix_append,
15609 .name = "POSIX-SYMLINK-ACL",
15610 .fn = run_acl_symlink_test,
15613 .name = "POSIX-SYMLINK-EA",
15614 .fn = run_ea_symlink_test,
15617 .name = "POSIX-STREAM-DELETE",
15618 .fn = run_posix_stream_delete,
15621 .name = "POSIX-OFD-LOCK",
15622 .fn = run_posix_ofd_lock_test,
15625 .name = "POSIX-BLOCKING-LOCK",
15626 .fn = run_posix_blocking_lock,
15629 .name = "POSIX-MKDIR",
15630 .fn = run_posix_mkdir_test,
15633 .name = "POSIX-ACL-OPLOCK",
15634 .fn = run_posix_acl_oplock_test,
15637 .name = "POSIX-ACL-SHAREROOT",
15638 .fn = run_posix_acl_shareroot_test,
15641 .name = "POSIX-LS-WILDCARD",
15642 .fn = run_posix_ls_wildcard_test,
15645 .name = "POSIX-LS-SINGLE",
15646 .fn = run_posix_ls_single_test,
15649 .name = "POSIX-READLINK",
15650 .fn = run_posix_readlink_test,
15653 .name = "POSIX-STAT",
15654 .fn = run_posix_stat_test,
15657 .name = "POSIX-SYMLINK-PARENT",
15658 .fn = run_posix_symlink_parent_test,
15661 .name = "POSIX-SYMLINK-CHMOD",
15662 .fn = run_posix_symlink_chmod_test,
15665 .name = "POSIX-SYMLINK-RENAME",
15666 .fn = run_posix_symlink_rename_test,
15669 .name = "POSIX-DIR-DEFAULT-ACL",
15670 .fn = run_posix_dir_default_acl_test,
15673 .name = "POSIX-SYMLINK-GETPATHINFO",
15674 .fn = run_posix_symlink_getpathinfo_test,
15677 .name = "POSIX-SYMLINK-SETPATHINFO",
15678 .fn = run_posix_symlink_setpathinfo_test,
15681 .name = "WINDOWS-BAD-SYMLINK",
15682 .fn = run_symlink_open_test,
15685 .name = "SMB1-WILD-MANGLE-UNLINK",
15686 .fn = run_smb1_wild_mangle_unlink_test,
15689 .name = "SMB1-WILD-MANGLE-RENAME",
15690 .fn = run_smb1_wild_mangle_rename_test,
15693 .name = "CASE-INSENSITIVE-CREATE",
15694 .fn = run_case_insensitive_create,
15697 .name = "ASYNC-ECHO",
15698 .fn = run_async_echo,
15701 .name = "UID-REGRESSION-TEST",
15702 .fn = run_uid_regression_test,
15705 .name = "SHORTNAME-TEST",
15706 .fn = run_shortname_test,
15709 .name = "ADDRCHANGE",
15710 .fn = run_addrchange,
15714 .name = "OPENATTR",
15715 .fn = run_openattrtest,
15727 .name = "RENAME-ACCESS",
15728 .fn = run_rename_access,
15731 .name = "OWNER-RIGHTS",
15732 .fn = run_owner_rights,
15736 .fn = run_deletetest,
15739 .name = "DELETE-STREAM",
15740 .fn = run_delete_stream,
15743 .name = "DELETE-PRINT",
15744 .fn = run_delete_print_test,
15747 .name = "DELETE-LN",
15748 .fn = run_deletetest_ln,
15751 .name = "PROPERTIES",
15752 .fn = run_properties,
15756 .fn = torture_mangle,
15763 .name = "MANGLE-ILLEGAL",
15764 .fn = run_mangle_illegal,
15771 .name = "TRANS2SCAN",
15772 .fn = torture_trans2_scan,
15775 .name = "NTTRANSSCAN",
15776 .fn = torture_nttrans_scan,
15780 .fn = torture_utable,
15783 .name = "CASETABLE",
15784 .fn = torture_casetable,
15787 .name = "ERRMAPEXTRACT",
15788 .fn = run_error_map_extract,
15791 .name = "PIPE_NUMBER",
15792 .fn = run_pipe_number,
15796 .fn = run_tcon2_test,
15800 .fn = torture_ioctl_test,
15804 .fn = torture_chkpath_test,
15808 .fn = run_fdsesstest,
15815 .name = "SESSSETUP_BENCH",
15816 .fn = run_sesssetup_bench,
15831 .name = "WINDOWS-WRITE",
15832 .fn = run_windows_write,
15835 .name = "LARGE_READX",
15836 .fn = run_large_readx,
15839 .name = "MSDFS-ATTRIBUTE",
15840 .fn = run_msdfs_attribute,
15843 .name = "NTTRANS-CREATE",
15844 .fn = run_nttrans_create,
15847 .name = "NTTRANS-FSCTL",
15848 .fn = run_nttrans_fsctl,
15851 .name = "CLI_ECHO",
15852 .fn = run_cli_echo,
15855 .name = "CLI_SPLICE",
15856 .fn = run_cli_splice,
15863 .name = "STREAMERROR",
15864 .fn = run_streamerror,
15867 .name = "NOTIFY-BENCH",
15868 .fn = run_notify_bench,
15871 .name = "NOTIFY-BENCH2",
15872 .fn = run_notify_bench2,
15875 .name = "NOTIFY-BENCH3",
15876 .fn = run_notify_bench3,
15879 .name = "BAD-NBT-SESSION",
15880 .fn = run_bad_nbt_session,
15883 .name = "IGN-BAD-NEGPROT",
15884 .fn = run_ign_bad_negprot,
15887 .name = "SMB-ANY-CONNECT",
15888 .fn = run_smb_any_connect,
15891 .name = "NOTIFY-ONLINE",
15892 .fn = run_notify_online,
15895 .name = "SMB2-BASIC",
15896 .fn = run_smb2_basic,
15899 .name = "SMB2-NEGPROT",
15900 .fn = run_smb2_negprot,
15903 .name = "SMB2-ANONYMOUS",
15904 .fn = run_smb2_anonymous,
15907 .name = "SMB2-SESSION-RECONNECT",
15908 .fn = run_smb2_session_reconnect,
15911 .name = "SMB2-TCON-DEPENDENCE",
15912 .fn = run_smb2_tcon_dependence,
15915 .name = "SMB2-MULTI-CHANNEL",
15916 .fn = run_smb2_multi_channel,
15919 .name = "SMB2-SESSION-REAUTH",
15920 .fn = run_smb2_session_reauth,
15923 .name = "SMB2-FTRUNCATE",
15924 .fn = run_smb2_ftruncate,
15927 .name = "SMB2-DIR-FSYNC",
15928 .fn = run_smb2_dir_fsync,
15931 .name = "SMB2-PATH-SLASH",
15932 .fn = run_smb2_path_slash,
15935 .name = "SMB1-SYSTEM-SECURITY",
15936 .fn = run_smb1_system_security,
15939 .name = "SMB2-SACL",
15940 .fn = run_smb2_sacl,
15943 .name = "SMB2-QUOTA1",
15944 .fn = run_smb2_quota1,
15947 .name = "SMB2-INVALID-PIPENAME",
15948 .fn = run_smb2_invalid_pipename,
15951 .name = "SMB2-STREAM-ACL",
15952 .fn = run_smb2_stream_acl,
15955 .name = "SMB2-LIST-DIR-ASYNC",
15956 .fn = run_list_dir_async_test,
15959 .name = "SMB2-DEL-ON-CLOSE-NONEMPTY",
15960 .fn = run_delete_on_close_non_empty,
15963 .name = "SMB2-DEL-ON-CLOSE-NONWRITE-DELETE-YES",
15964 .fn = run_delete_on_close_nonwrite_delete_yes_test,
15967 .name = "SMB2-DEL-ON-CLOSE-NONWRITE-DELETE-NO",
15968 .fn = run_delete_on_close_nonwrite_delete_no_test,
15971 .name = "SMB2-DFS-PATHS",
15972 .fn = run_smb2_dfs_paths,
15975 .name = "SMB2-NON-DFS-SHARE",
15976 .fn = run_smb2_non_dfs_share,
15979 .name = "SMB2-DFS-SHARE-NON-DFS-PATH",
15980 .fn = run_smb2_dfs_share_non_dfs_path,
15983 .name = "SMB2-DFS-FILENAME-LEADING-BACKSLASH",
15984 .fn = run_smb2_dfs_filename_leading_backslash,
15987 .name = "SMB2-PIPE-READ-ASYNC-DISCONNECT",
15988 .fn = run_smb2_pipe_read_async_disconnect,
15991 .name = "SMB1-TRUNCATED-SESSSETUP",
15992 .fn = run_smb1_truncated_sesssetup,
15995 .name = "SMB1-NEGOTIATE-EXIT",
15996 .fn = run_smb1_negotiate_exit,
15999 .name = "SMB1-NEGOTIATE-TCON",
16000 .fn = run_smb1_negotiate_tcon,
16003 .name = "SMB1-DFS-PATHS",
16004 .fn = run_smb1_dfs_paths,
16007 .name = "SMB1-DFS-SEARCH-PATHS",
16008 .fn = run_smb1_dfs_search_paths,
16011 .name = "SMB1-DFS-OPERATIONS",
16012 .fn = run_smb1_dfs_operations,
16015 .name = "SMB1-DFS-BADPATH",
16016 .fn = run_smb1_dfs_check_badpath,
16019 .name = "CLEANUP1",
16020 .fn = run_cleanup1,
16023 .name = "CLEANUP2",
16024 .fn = run_cleanup2,
16027 .name = "CLEANUP4",
16028 .fn = run_cleanup4,
16031 .name = "OPLOCK-CANCEL",
16032 .fn = run_oplock_cancel,
16039 .name = "LOCAL-SUBSTITUTE",
16040 .fn = run_local_substitute,
16043 .name = "LOCAL-GENCACHE",
16044 .fn = run_local_gencache,
16047 .name = "LOCAL-DBWRAP-WATCH1",
16048 .fn = run_dbwrap_watch1,
16051 .name = "LOCAL-DBWRAP-WATCH2",
16052 .fn = run_dbwrap_watch2,
16055 .name = "LOCAL-DBWRAP-WATCH3",
16056 .fn = run_dbwrap_watch3,
16059 .name = "LOCAL-DBWRAP-WATCH4",
16060 .fn = run_dbwrap_watch4,
16063 .name = "LOCAL-DBWRAP-DO-LOCKED1",
16064 .fn = run_dbwrap_do_locked1,
16067 .name = "LOCAL-MESSAGING-READ1",
16068 .fn = run_messaging_read1,
16071 .name = "LOCAL-MESSAGING-READ2",
16072 .fn = run_messaging_read2,
16075 .name = "LOCAL-MESSAGING-READ3",
16076 .fn = run_messaging_read3,
16079 .name = "LOCAL-MESSAGING-READ4",
16080 .fn = run_messaging_read4,
16083 .name = "LOCAL-MESSAGING-FDPASS1",
16084 .fn = run_messaging_fdpass1,
16087 .name = "LOCAL-MESSAGING-FDPASS2",
16088 .fn = run_messaging_fdpass2,
16091 .name = "LOCAL-MESSAGING-FDPASS2a",
16092 .fn = run_messaging_fdpass2a,
16095 .name = "LOCAL-MESSAGING-FDPASS2b",
16096 .fn = run_messaging_fdpass2b,
16099 .name = "LOCAL-MESSAGING-SEND-ALL",
16100 .fn = run_messaging_send_all,
16103 .name = "LOCAL-BASE64",
16104 .fn = run_local_base64,
16107 .name = "LOCAL-RBTREE",
16108 .fn = run_local_rbtree,
16111 .name = "LOCAL-MEMCACHE",
16112 .fn = run_local_memcache,
16115 .name = "LOCAL-STREAM-NAME",
16116 .fn = run_local_stream_name,
16119 .name = "LOCAL-STR-MATCH-MSWILD",
16120 .fn = run_str_match_mswild,
16123 .name = "LOCAL-STR-MATCH-REGEX-SUB1",
16124 .fn = run_str_match_regex_sub1,
16127 .name = "WBCLIENT-MULTI-PING",
16128 .fn = run_wbclient_multi_ping,
16131 .name = "LOCAL-string_to_sid",
16132 .fn = run_local_string_to_sid,
16135 .name = "LOCAL-sid_to_string",
16136 .fn = run_local_sid_to_string,
16139 .name = "LOCAL-binary_to_sid",
16140 .fn = run_local_binary_to_sid,
16143 .name = "LOCAL-DBTRANS",
16144 .fn = run_local_dbtrans,
16147 .name = "LOCAL-TEVENT-POLL",
16148 .fn = run_local_tevent_poll,
16151 .name = "LOCAL-CONVERT-STRING",
16152 .fn = run_local_convert_string,
16155 .name = "LOCAL-CONV-AUTH-INFO",
16156 .fn = run_local_conv_auth_info,
16159 .name = "LOCAL-hex_encode_buf",
16160 .fn = run_local_hex_encode_buf,
16163 .name = "LOCAL-IDMAP-TDB-COMMON",
16164 .fn = run_idmap_tdb_common_test,
16167 .name = "LOCAL-remove_duplicate_addrs2",
16168 .fn = run_local_remove_duplicate_addrs2,
16171 .name = "local-tdb-opener",
16172 .fn = run_local_tdb_opener,
16175 .name = "local-tdb-writer",
16176 .fn = run_local_tdb_writer,
16179 .name = "LOCAL-DBWRAP-CTDB1",
16180 .fn = run_local_dbwrap_ctdb1,
16183 .name = "LOCAL-BENCH-PTHREADPOOL",
16184 .fn = run_bench_pthreadpool,
16187 .name = "LOCAL-PTHREADPOOL-TEVENT",
16188 .fn = run_pthreadpool_tevent,
16191 .name = "LOCAL-G-LOCK1",
16195 .name = "LOCAL-G-LOCK2",
16199 .name = "LOCAL-G-LOCK3",
16203 .name = "LOCAL-G-LOCK4",
16207 .name = "LOCAL-G-LOCK4A",
16208 .fn = run_g_lock4a,
16211 .name = "LOCAL-G-LOCK5",
16215 .name = "LOCAL-G-LOCK6",
16219 .name = "LOCAL-G-LOCK7",
16223 .name = "LOCAL-G-LOCK8",
16227 .name = "LOCAL-G-LOCK-PING-PONG",
16228 .fn = run_g_lock_ping_pong,
16231 .name = "LOCAL-CANONICALIZE-PATH",
16232 .fn = run_local_canonicalize_path,
16235 .name = "LOCAL-NAMEMAP-CACHE1",
16236 .fn = run_local_namemap_cache1,
16239 .name = "LOCAL-IDMAP-CACHE1",
16240 .fn = run_local_idmap_cache1,
16243 .name = "qpathinfo-bufsize",
16244 .fn = run_qpathinfo_bufsize,
16247 .name = "hide-new-files-timeout",
16248 .fn = run_hidenewfiles,
16251 .name = "hide-new-files-timeout-showdirs",
16252 .fn = run_hidenewfiles_showdirs,
16254 #ifdef CLUSTER_SUPPORT
16256 .name = "ctdbd-conn1",
16257 .fn = run_ctdbd_conn1,
16261 .name = "readdir-timestamp",
16262 .fn = run_readdir_timestamp,
16265 .name = "rpc-scale",
16266 .fn = run_rpc_scale,
16269 .name = "LOCAL-TDB-VALIDATE",
16270 .fn = run_tdb_validate,
16277 /****************************************************************************
16278 run a specified test or "ALL"
16279 ****************************************************************************/
16280 static bool run_test(const char *name)
16283 bool result = True;
16284 bool found = False;
16287 if (strequal(name,"ALL")) {
16288 for (i=0;torture_ops[i].name;i++) {
16289 run_test(torture_ops[i].name);
16294 for (i=0;torture_ops[i].name;i++) {
16295 fstr_sprintf(randomfname, "\\XX%x",
16296 (unsigned)random());
16298 if (strequal(name, torture_ops[i].name)) {
16300 printf("Running %s\n", name);
16301 if (torture_ops[i].flags & FLAG_MULTIPROC) {
16302 t = create_procs(torture_ops[i].fn, &result);
16305 printf("TEST %s FAILED!\n", name);
16308 struct timeval start;
16309 start = timeval_current();
16310 if (!torture_ops[i].fn(0)) {
16312 printf("TEST %s FAILED!\n", name);
16314 t = timeval_elapsed(&start);
16316 printf("%s took %g secs\n\n", name, t);
16321 printf("Did not find a test named %s\n", name);
16329 static void usage(void)
16333 printf("WARNING samba4 test suite is much more complete nowadays.\n");
16334 printf("Please use samba4 torture.\n\n");
16336 printf("Usage: smbtorture //server/share <options> TEST1 TEST2 ...\n");
16338 printf("\t-d debuglevel\n");
16339 printf("\t-U user%%pass\n");
16340 printf("\t-k use kerberos\n");
16341 printf("\t-N numprocs\n");
16342 printf("\t-n my_netbios_name\n");
16343 printf("\t-W workgroup\n");
16344 printf("\t-o num_operations\n");
16345 printf("\t-O socket_options\n");
16346 printf("\t-m maximum protocol\n");
16347 printf("\t-L use oplocks\n");
16348 printf("\t-c CLIENT.TXT specify client load file for NBENCH\n");
16349 printf("\t-A showall\n");
16350 printf("\t-p port\n");
16351 printf("\t-s seed\n");
16352 printf("\t-b unclist_filename specify multiple shares for multiple connections\n");
16353 printf("\t-f filename filename to test\n");
16354 printf("\t-e encrypt\n");
16355 printf("\t-T 'OPTION=VALUE' smb.conf option line\n");
16358 printf("tests are:");
16359 for (i=0;torture_ops[i].name;i++) {
16360 printf(" %s", torture_ops[i].name);
16364 printf("default test is ALL\n");
16369 /****************************************************************************
16371 ****************************************************************************/
16372 int main(int argc,char *argv[])
16378 bool correct = True;
16379 TALLOC_CTX *frame = talloc_stackframe();
16380 int seed = time(NULL);
16381 struct loadparm_context *lp_ctx = NULL;
16383 #ifdef HAVE_SETBUFFER
16384 setbuffer(stdout, NULL, 0);
16387 setup_logging("smbtorture", DEBUG_STDOUT);
16392 lp_ctx = loadparm_init_s3(frame, loadparm_s3_helpers());
16393 if (lp_ctx == NULL) {
16395 "Failed to initialise the global parameter structure.\n");
16399 if (is_default_dyn_CONFIGFILE()) {
16400 if(getenv("SMB_CONF_PATH")) {
16401 set_dyn_CONFIGFILE(getenv("SMB_CONF_PATH"));
16404 lp_load_global(get_dyn_CONFIGFILE());
16411 for(p = argv[1]; *p; p++)
16415 if (strncmp(argv[1], "//", 2)) {
16419 fstrcpy(host, &argv[1][2]);
16420 p = strchr_m(&host[2],'/');
16425 fstrcpy(share, p+1);
16427 fstrcpy(myname, get_myname(talloc_tos()));
16429 fprintf(stderr, "Failed to get my hostname.\n");
16433 if (*username == 0 && getenv("LOGNAME")) {
16434 fstrcpy(username,getenv("LOGNAME"));
16440 fstrcpy(workgroup, lp_workgroup());
16442 while ((opt = getopt(argc, argv, "p:hW:U:n:N:O:o:m:Ll:d:Aec:ks:b:B:f:T:"))
16446 port_to_use = atoi(optarg);
16449 seed = atoi(optarg);
16452 fstrcpy(workgroup,optarg);
16455 lpcfg_set_cmdline(lp_ctx, "client max protocol", optarg);
16458 torture_nprocs = atoi(optarg);
16461 torture_numops = atoi(optarg);
16464 lpcfg_set_cmdline(lp_ctx, "log level", optarg);
16470 use_oplocks = True;
16473 local_path = optarg;
16476 torture_showall = True;
16479 fstrcpy(myname, optarg);
16482 client_txt = optarg;
16489 use_kerberos = True;
16491 d_printf("No kerberos support compiled in\n");
16497 fstrcpy(username,optarg);
16498 p = strchr_m(username,'%');
16501 fstrcpy(password, p+1);
16506 fstrcpy(multishare_conn_fname, optarg);
16507 use_multishare_conn = True;
16510 torture_blocksize = atoi(optarg);
16513 test_filename = SMB_STRDUP(optarg);
16516 lpcfg_set_option(lp_ctx, optarg);
16519 printf("Unknown option %c (%d)\n", (char)opt, opt);
16524 d_printf("using seed %d\n", seed);
16528 if(use_kerberos && !gotuser) gotpass = True;
16531 char pwd[256] = {0};
16534 rc = samba_getpass("Password:", pwd, sizeof(pwd), false, false);
16536 fstrcpy(password, pwd);
16541 printf("host=%s share=%s user=%s myname=%s\n",
16542 host, share, username, myname);
16544 torture_creds = cli_session_creds_init(frame,
16550 false, /* fallback_after_kerberos */
16551 false, /* use_ccache */
16552 false); /* password_is_nt_hash */
16553 if (torture_creds == NULL) {
16554 d_printf("cli_session_creds_init() failed.\n");
16558 if (argc == optind) {
16559 correct = run_test("ALL");
16561 for (i=optind;i<argc;i++) {
16562 if (!run_test(argv[i])) {
16568 TALLOC_FREE(frame);