2 Unix SMB/CIFS implementation.
4 Copyright (C) Andrew Tridgell 1997-1998
5 Copyright (C) Jeremy Allison 2009
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program. If not, see <http://www.gnu.org/licenses/>.
22 #include "system/shmem.h"
23 #include "libsmb/namequery.h"
24 #include "wbc_async.h"
25 #include "torture/proto.h"
26 #include "libcli/security/security.h"
28 #include "tldap_util.h"
29 #include "tldap_gensec_bind.h"
30 #include "../librpc/gen_ndr/svcctl.h"
31 #include "../lib/util/memcache.h"
32 #include "nsswitch/winbind_client.h"
33 #include "dbwrap/dbwrap.h"
34 #include "dbwrap/dbwrap_open.h"
35 #include "dbwrap/dbwrap_rbt.h"
36 #include "async_smb.h"
37 #include "libsmb/libsmb.h"
38 #include "libsmb/clirap.h"
40 #include "libsmb/nmblib.h"
41 #include "../lib/util/tevent_ntstatus.h"
43 #include "../libcli/smb/read_smb.h"
44 #include "../libcli/smb/smbXcli_base.h"
45 #include "lib/util/sys_rw_data.h"
46 #include "lib/util/base64.h"
47 #include "lib/util/time.h"
48 #include "lib/gencache.h"
49 #include "lib/util/sys_rw.h"
50 #include "lib/util/asn1.h"
51 #include "lib/param/param.h"
52 #include "auth/gensec/gensec.h"
53 #include "lib/util/string_wrappers.h"
55 #include <gnutls/gnutls.h>
56 #include <gnutls/crypto.h>
61 fstring host, workgroup, share, password, username, myname;
62 struct cli_credentials *torture_creds;
63 static const char *sockops="TCP_NODELAY";
65 static int port_to_use=0;
66 int torture_numops=100;
67 int torture_blocksize=1024*1024;
68 static int procnum; /* records process count number when forking */
69 static struct cli_state *current_cli;
70 static fstring randomfname;
71 static bool use_oplocks;
72 static bool use_level_II_oplocks;
73 static const char *client_txt = "client_oplocks.txt";
74 static bool disable_spnego;
75 static bool use_kerberos;
76 static bool force_dos_errors;
77 static fstring multishare_conn_fname;
78 static bool use_multishare_conn = False;
79 static bool do_encrypt;
80 static const char *local_path = NULL;
81 static enum smb_signing_setting signing_state = SMB_SIGNING_DEFAULT;
84 bool torture_showall = False;
86 static double create_procs(bool (*fn)(int), bool *result);
88 /********************************************************************
89 Ensure a connection is encrypted.
90 ********************************************************************/
92 static bool force_cli_encryption(struct cli_state *c,
93 const char *sharename)
95 uint16_t major, minor;
96 uint32_t caplow, caphigh;
99 if (!SERVER_HAS_UNIX_CIFS(c)) {
100 d_printf("Encryption required and "
101 "server that doesn't support "
102 "UNIX extensions - failing connect\n");
106 status = cli_unix_extensions_version(c, &major, &minor, &caplow,
108 if (!NT_STATUS_IS_OK(status)) {
109 d_printf("Encryption required and "
110 "can't get UNIX CIFS extensions "
111 "version from server: %s\n", nt_errstr(status));
115 if (!(caplow & CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP)) {
116 d_printf("Encryption required and "
117 "share %s doesn't support "
118 "encryption.\n", sharename);
122 status = cli_smb1_setup_encryption(c, torture_creds);
123 if (!NT_STATUS_IS_OK(status)) {
124 d_printf("Encryption required and "
125 "setup failed with error %s.\n",
134 static struct cli_state *open_nbt_connection(void)
140 if (disable_spnego) {
141 flags |= CLI_FULL_CONNECTION_DONT_SPNEGO;
145 flags |= CLI_FULL_CONNECTION_OPLOCKS;
148 if (use_level_II_oplocks) {
149 flags |= CLI_FULL_CONNECTION_LEVEL_II_OPLOCKS;
152 if (force_dos_errors) {
153 flags |= CLI_FULL_CONNECTION_FORCE_DOS_ERRORS;
156 status = cli_connect_nb(host, NULL, port_to_use, 0x20, myname,
157 signing_state, flags, &c);
158 if (!NT_STATUS_IS_OK(status)) {
159 printf("Failed to connect with %s. Error %s\n", host, nt_errstr(status) );
163 cli_set_timeout(c, 120000); /* set a really long timeout (2 minutes) */
168 /****************************************************************************
169 Send a corrupt session request. See rfc1002.txt 4.3 and 4.3.2.
170 ****************************************************************************/
172 static bool cli_bad_session_request(int fd,
173 struct nmb_name *calling, struct nmb_name *called)
182 uint8_t message_type;
184 struct tevent_context *ev;
185 struct tevent_req *req;
187 frame = talloc_stackframe();
189 iov[0].iov_base = len_buf;
190 iov[0].iov_len = sizeof(len_buf);
192 /* put in the destination name */
194 iov[1].iov_base = name_mangle(talloc_tos(), called->name,
196 if (iov[1].iov_base == NULL) {
199 iov[1].iov_len = name_len((unsigned char *)iov[1].iov_base,
200 talloc_get_size(iov[1].iov_base));
204 iov[2].iov_base = name_mangle(talloc_tos(), calling->name,
206 if (iov[2].iov_base == NULL) {
209 iov[2].iov_len = name_len((unsigned char *)iov[2].iov_base,
210 talloc_get_size(iov[2].iov_base));
212 /* Deliberately corrupt the name len (first byte) */
213 *((uint8_t *)iov[2].iov_base) = 100;
215 /* send a session request (RFC 1002) */
216 /* setup the packet length
217 * Remove four bytes from the length count, since the length
218 * field in the NBT Session Service header counts the number
219 * of bytes which follow. The cli_send_smb() function knows
220 * about this and accounts for those four bytes.
224 _smb_setlen(len_buf, iov[1].iov_len + iov[2].iov_len);
225 SCVAL(len_buf,0,0x81);
227 len = write_data_iov(fd, iov, 3);
232 ev = samba_tevent_context_init(frame);
236 req = read_smb_send(frame, ev, fd);
240 if (!tevent_req_poll(req, ev)) {
243 len = read_smb_recv(req, talloc_tos(), &inbuf, &err);
250 message_type = CVAL(inbuf, 0);
251 if (message_type != 0x83) {
252 d_fprintf(stderr, "Expected msg type 0x83, got 0x%2.2x\n",
257 if (smb_len(inbuf) != 1) {
258 d_fprintf(stderr, "Expected smb_len 1, got %d\n",
259 (int)smb_len(inbuf));
263 error = CVAL(inbuf, 4);
265 d_fprintf(stderr, "Expected error 0x82, got %d\n",
276 /* Insert a NULL at the first separator of the given path and return a pointer
277 * to the remainder of the string.
280 terminate_path_at_separator(char * path)
288 if ((p = strchr_m(path, '/'))) {
293 if ((p = strchr_m(path, '\\'))) {
303 parse a //server/share type UNC name
305 bool smbcli_parse_unc(const char *unc_name, TALLOC_CTX *mem_ctx,
306 char **hostname, char **sharename)
310 *hostname = *sharename = NULL;
312 if (strncmp(unc_name, "\\\\", 2) &&
313 strncmp(unc_name, "//", 2)) {
317 *hostname = talloc_strdup(mem_ctx, &unc_name[2]);
318 p = terminate_path_at_separator(*hostname);
321 *sharename = talloc_strdup(mem_ctx, p);
322 terminate_path_at_separator(*sharename);
325 if (*hostname && *sharename) {
329 TALLOC_FREE(*hostname);
330 TALLOC_FREE(*sharename);
334 static bool torture_open_connection_share(struct cli_state **c,
335 const char *hostname,
336 const char *sharename,
341 status = cli_full_connection_creds(c,
350 if (!NT_STATUS_IS_OK(status)) {
351 printf("failed to open share connection: //%s/%s port:%d - %s\n",
352 hostname, sharename, port_to_use, nt_errstr(status));
356 cli_set_timeout(*c, 120000); /* set a really long timeout (2 minutes) */
359 return force_cli_encryption(*c,
365 bool torture_open_connection_flags(struct cli_state **c, int conn_index, int flags)
367 char **unc_list = NULL;
368 int num_unc_names = 0;
371 if (use_multishare_conn==True) {
373 unc_list = file_lines_load(multishare_conn_fname, &num_unc_names, 0, NULL);
374 if (!unc_list || num_unc_names <= 0) {
375 printf("Failed to load unc names list from '%s'\n", multishare_conn_fname);
379 if (!smbcli_parse_unc(unc_list[conn_index % num_unc_names],
381 printf("Failed to parse UNC name %s\n",
382 unc_list[conn_index % num_unc_names]);
383 TALLOC_FREE(unc_list);
387 result = torture_open_connection_share(c, h, s, flags);
389 /* h, s were copied earlier */
390 TALLOC_FREE(unc_list);
394 return torture_open_connection_share(c, host, share, flags);
397 bool torture_open_connection(struct cli_state **c, int conn_index)
399 int flags = CLI_FULL_CONNECTION_FORCE_SMB1;
402 flags |= CLI_FULL_CONNECTION_OPLOCKS;
404 if (use_level_II_oplocks) {
405 flags |= CLI_FULL_CONNECTION_LEVEL_II_OPLOCKS;
408 return torture_open_connection_flags(c, conn_index, flags);
411 bool torture_init_connection(struct cli_state **pcli)
413 struct cli_state *cli;
415 cli = open_nbt_connection();
424 bool torture_cli_session_setup2(struct cli_state *cli, uint16_t *new_vuid)
426 uint16_t old_vuid = cli_state_get_uid(cli);
430 cli_state_set_uid(cli, 0);
431 status = cli_session_setup_creds(cli, torture_creds);
432 ret = NT_STATUS_IS_OK(status);
433 *new_vuid = cli_state_get_uid(cli);
434 cli_state_set_uid(cli, old_vuid);
439 bool torture_close_connection(struct cli_state *c)
444 status = cli_tdis(c);
445 if (!NT_STATUS_IS_OK(status)) {
446 printf("tdis failed (%s)\n", nt_errstr(status));
455 void torture_conn_set_sockopt(struct cli_state *cli)
457 smbXcli_conn_set_sockopt(cli->conn, sockops);
460 /* check if the server produced the expected dos or nt error code */
461 static bool check_both_error(int line, NTSTATUS status,
462 uint8_t eclass, uint32_t ecode, NTSTATUS nterr)
464 if (NT_STATUS_IS_DOS(status)) {
468 /* Check DOS error */
469 cclass = NT_STATUS_DOS_CLASS(status);
470 num = NT_STATUS_DOS_CODE(status);
472 if (eclass != cclass || ecode != num) {
473 printf("unexpected error code class=%d code=%d\n",
474 (int)cclass, (int)num);
475 printf(" expected %d/%d %s (line=%d)\n",
476 (int)eclass, (int)ecode, nt_errstr(nterr), line);
481 if (!NT_STATUS_EQUAL(nterr, status)) {
482 printf("unexpected error code %s\n",
484 printf(" expected %s (line=%d)\n",
485 nt_errstr(nterr), line);
494 /* check if the server produced the expected error code */
495 static bool check_error(int line, NTSTATUS status,
496 uint8_t eclass, uint32_t ecode, NTSTATUS nterr)
498 if (NT_STATUS_IS_DOS(status)) {
502 /* Check DOS error */
504 cclass = NT_STATUS_DOS_CLASS(status);
505 num = NT_STATUS_DOS_CODE(status);
507 if (eclass != cclass || ecode != num) {
508 printf("unexpected error code class=%d code=%d\n",
509 (int)cclass, (int)num);
510 printf(" expected %d/%d %s (line=%d)\n",
511 (int)eclass, (int)ecode, nt_errstr(nterr),
519 if (NT_STATUS_V(nterr) != NT_STATUS_V(status)) {
520 printf("unexpected error code %s\n",
522 printf(" expected %s (line=%d)\n", nt_errstr(nterr),
532 static bool wait_lock(struct cli_state *c, int fnum, uint32_t offset, uint32_t len)
536 status = cli_lock32(c, fnum, offset, len, -1, WRITE_LOCK);
538 while (!NT_STATUS_IS_OK(status)) {
539 if (!check_both_error(__LINE__, status, ERRDOS,
540 ERRlock, NT_STATUS_LOCK_NOT_GRANTED)) {
544 status = cli_lock32(c, fnum, offset, len, -1, WRITE_LOCK);
551 static bool rw_torture(struct cli_state *c)
553 const char *lockfname = "\\torture.lck";
557 pid_t pid2, pid = getpid();
564 memset(buf, '\0', sizeof(buf));
566 status = cli_openx(c, lockfname, O_RDWR | O_CREAT | O_EXCL,
568 if (!NT_STATUS_IS_OK(status)) {
569 status = cli_openx(c, lockfname, O_RDWR, DENY_NONE, &fnum2);
571 if (!NT_STATUS_IS_OK(status)) {
572 printf("open of %s failed (%s)\n",
573 lockfname, nt_errstr(status));
577 for (i=0;i<torture_numops;i++) {
578 unsigned n = (unsigned)sys_random()%10;
581 printf("%d\r", i); fflush(stdout);
583 slprintf(fname, sizeof(fstring) - 1, "\\torture.%u", n);
585 if (!wait_lock(c, fnum2, n*sizeof(int), sizeof(int))) {
589 status = cli_openx(c, fname, O_RDWR | O_CREAT | O_TRUNC,
591 if (!NT_STATUS_IS_OK(status)) {
592 printf("open failed (%s)\n", nt_errstr(status));
597 status = cli_writeall(c, fnum, 0, (uint8_t *)&pid, 0,
599 if (!NT_STATUS_IS_OK(status)) {
600 printf("write failed (%s)\n", nt_errstr(status));
605 status = cli_writeall(c, fnum, 0, (uint8_t *)buf,
606 sizeof(pid)+(j*sizeof(buf)),
608 if (!NT_STATUS_IS_OK(status)) {
609 printf("write failed (%s)\n",
617 status = cli_read(c, fnum, (char *)&pid2, 0, sizeof(pid),
619 if (!NT_STATUS_IS_OK(status)) {
620 printf("read failed (%s)\n", nt_errstr(status));
622 } else if (nread != sizeof(pid)) {
623 printf("read/write compare failed: "
624 "recv %ld req %ld\n", (unsigned long)nread,
625 (unsigned long)sizeof(pid));
630 printf("data corruption!\n");
634 status = cli_close(c, fnum);
635 if (!NT_STATUS_IS_OK(status)) {
636 printf("close failed (%s)\n", nt_errstr(status));
640 status = cli_unlink(c, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
641 if (!NT_STATUS_IS_OK(status)) {
642 printf("unlink failed (%s)\n", nt_errstr(status));
646 status = cli_unlock(c, fnum2, n*sizeof(int), sizeof(int));
647 if (!NT_STATUS_IS_OK(status)) {
648 printf("unlock failed (%s)\n", nt_errstr(status));
654 cli_unlink(c, lockfname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
661 static bool run_torture(int dummy)
663 struct cli_state *cli;
668 smbXcli_conn_set_sockopt(cli->conn, sockops);
670 ret = rw_torture(cli);
672 if (!torture_close_connection(cli)) {
679 static bool rw_torture3(struct cli_state *c, char *lockfname)
681 uint16_t fnum = (uint16_t)-1;
686 unsigned countprev = 0;
689 NTSTATUS status = NT_STATUS_OK;
692 for (i = 0; i < sizeof(buf); i += sizeof(uint32_t))
694 SIVAL(buf, i, sys_random());
701 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
702 if (!NT_STATUS_IS_OK(status)) {
703 printf("unlink failed (%s) (normal, this file should "
704 "not exist)\n", nt_errstr(status));
707 status = cli_openx(c, lockfname, O_RDWR | O_CREAT | O_EXCL,
709 if (!NT_STATUS_IS_OK(status)) {
710 printf("first open read/write of %s failed (%s)\n",
711 lockfname, nt_errstr(status));
717 for (i = 0; i < 500 && fnum == (uint16_t)-1; i++)
719 status = cli_openx(c, lockfname, O_RDONLY,
721 if (NT_STATUS_IS_OK(status)) {
726 if (!NT_STATUS_IS_OK(status)) {
727 printf("second open read-only of %s failed (%s)\n",
728 lockfname, nt_errstr(status));
734 for (count = 0; count < sizeof(buf); count += sent)
736 if (count >= countprev) {
737 printf("%d %8d\r", i, count);
740 countprev += (sizeof(buf) / 20);
745 sent = ((unsigned)sys_random()%(20))+ 1;
746 if (sent > sizeof(buf) - count)
748 sent = sizeof(buf) - count;
751 status = cli_writeall(c, fnum, 0, (uint8_t *)buf+count,
753 if (!NT_STATUS_IS_OK(status)) {
754 printf("write failed (%s)\n",
761 status = cli_read(c, fnum, buf_rd+count, count,
762 sizeof(buf)-count, &sent);
763 if(!NT_STATUS_IS_OK(status)) {
764 printf("read failed offset:%d size:%ld (%s)\n",
765 count, (unsigned long)sizeof(buf)-count,
769 } else if (sent > 0) {
770 if (memcmp(buf_rd+count, buf+count, sent) != 0)
772 printf("read/write compare failed\n");
773 printf("offset: %d req %ld recvd %ld\n", count, (unsigned long)sizeof(buf)-count, (unsigned long)sent);
782 status = cli_close(c, fnum);
783 if (!NT_STATUS_IS_OK(status)) {
784 printf("close failed (%s)\n", nt_errstr(status));
791 static bool rw_torture2(struct cli_state *c1, struct cli_state *c2)
793 const char *lockfname = "\\torture2.lck";
803 status = cli_unlink(c1, lockfname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
804 if (!NT_STATUS_IS_OK(status)) {
805 printf("unlink failed (%s) (normal, this file should not exist)\n", nt_errstr(status));
808 status = cli_openx(c1, lockfname, O_RDWR | O_CREAT | O_EXCL,
810 if (!NT_STATUS_IS_OK(status)) {
811 printf("first open read/write of %s failed (%s)\n",
812 lockfname, nt_errstr(status));
816 status = cli_openx(c2, lockfname, O_RDONLY, DENY_NONE, &fnum2);
817 if (!NT_STATUS_IS_OK(status)) {
818 printf("second open read-only of %s failed (%s)\n",
819 lockfname, nt_errstr(status));
820 cli_close(c1, fnum1);
824 for (i = 0; i < torture_numops; i++)
826 size_t buf_size = ((unsigned)sys_random()%(sizeof(buf)-1))+ 1;
828 printf("%d\r", i); fflush(stdout);
831 generate_random_buffer((unsigned char *)buf, buf_size);
833 status = cli_writeall(c1, fnum1, 0, (uint8_t *)buf, 0,
835 if (!NT_STATUS_IS_OK(status)) {
836 printf("write failed (%s)\n", nt_errstr(status));
841 status = cli_read(c2, fnum2, buf_rd, 0, buf_size, &bytes_read);
842 if(!NT_STATUS_IS_OK(status)) {
843 printf("read failed (%s)\n", nt_errstr(status));
846 } else if (bytes_read != buf_size) {
847 printf("read failed\n");
848 printf("read %ld, expected %ld\n",
849 (unsigned long)bytes_read,
850 (unsigned long)buf_size);
855 if (memcmp(buf_rd, buf, buf_size) != 0)
857 printf("read/write compare failed\n");
863 status = cli_close(c2, fnum2);
864 if (!NT_STATUS_IS_OK(status)) {
865 printf("close failed (%s)\n", nt_errstr(status));
869 status = cli_close(c1, fnum1);
870 if (!NT_STATUS_IS_OK(status)) {
871 printf("close failed (%s)\n", nt_errstr(status));
875 status = cli_unlink(c1, lockfname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
876 if (!NT_STATUS_IS_OK(status)) {
877 printf("unlink failed (%s)\n", nt_errstr(status));
884 static bool run_readwritetest(int dummy)
886 struct cli_state *cli1, *cli2;
887 bool test1, test2 = False;
889 if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
892 smbXcli_conn_set_sockopt(cli1->conn, sockops);
893 smbXcli_conn_set_sockopt(cli2->conn, sockops);
895 printf("starting readwritetest\n");
897 test1 = rw_torture2(cli1, cli2);
898 printf("Passed readwritetest v1: %s\n", BOOLSTR(test1));
901 test2 = rw_torture2(cli1, cli1);
902 printf("Passed readwritetest v2: %s\n", BOOLSTR(test2));
905 if (!torture_close_connection(cli1)) {
909 if (!torture_close_connection(cli2)) {
913 return (test1 && test2);
916 static bool run_readwritemulti(int dummy)
918 struct cli_state *cli;
923 smbXcli_conn_set_sockopt(cli->conn, sockops);
925 printf("run_readwritemulti: fname %s\n", randomfname);
926 test = rw_torture3(cli, randomfname);
928 if (!torture_close_connection(cli)) {
935 static bool run_readwritelarge_internal(void)
937 static struct cli_state *cli1;
939 const char *lockfname = "\\large.dat";
945 if (!torture_open_connection(&cli1, 0)) {
948 smbXcli_conn_set_sockopt(cli1->conn, sockops);
949 memset(buf,'\0',sizeof(buf));
951 printf("starting readwritelarge_internal\n");
953 cli_unlink(cli1, lockfname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
955 status = cli_openx(cli1, lockfname, O_RDWR | O_CREAT | O_EXCL,
957 if (!NT_STATUS_IS_OK(status)) {
958 printf("open read/write of %s failed (%s)\n", lockfname, nt_errstr(status));
962 cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 0, sizeof(buf), NULL);
964 status = cli_qfileinfo_basic(cli1, fnum1, NULL, &fsize, NULL, NULL,
966 if (!NT_STATUS_IS_OK(status)) {
967 printf("qfileinfo failed (%s)\n", nt_errstr(status));
971 if (fsize == sizeof(buf))
972 printf("readwritelarge_internal test 1 succeeded (size = %lx)\n",
973 (unsigned long)fsize);
975 printf("readwritelarge_internal test 1 failed (size = %lx)\n",
976 (unsigned long)fsize);
980 status = cli_close(cli1, fnum1);
981 if (!NT_STATUS_IS_OK(status)) {
982 printf("close failed (%s)\n", nt_errstr(status));
986 status = cli_unlink(cli1, lockfname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
987 if (!NT_STATUS_IS_OK(status)) {
988 printf("unlink failed (%s)\n", nt_errstr(status));
992 status = cli_openx(cli1, lockfname, O_RDWR | O_CREAT | O_EXCL,
994 if (!NT_STATUS_IS_OK(status)) {
995 printf("open read/write of %s failed (%s)\n", lockfname, nt_errstr(status));
999 cli_smbwrite(cli1, fnum1, buf, 0, sizeof(buf), NULL);
1001 status = cli_qfileinfo_basic(cli1, fnum1, NULL, &fsize, NULL, NULL,
1003 if (!NT_STATUS_IS_OK(status)) {
1004 printf("qfileinfo failed (%s)\n", nt_errstr(status));
1008 if (fsize == sizeof(buf))
1009 printf("readwritelarge_internal test 2 succeeded (size = %lx)\n",
1010 (unsigned long)fsize);
1012 printf("readwritelarge_internal test 2 failed (size = %lx)\n",
1013 (unsigned long)fsize);
1017 status = cli_close(cli1, fnum1);
1018 if (!NT_STATUS_IS_OK(status)) {
1019 printf("close failed (%s)\n", nt_errstr(status));
1023 if (!torture_close_connection(cli1)) {
1029 static bool run_readwritelarge(int dummy)
1031 return run_readwritelarge_internal();
1034 static bool run_readwritelarge_signtest(int dummy)
1037 signing_state = SMB_SIGNING_REQUIRED;
1038 ret = run_readwritelarge_internal();
1039 signing_state = SMB_SIGNING_DEFAULT;
1046 #define ival(s) strtol(s, NULL, 0)
1048 /* run a test that simulates an approximate netbench client load */
1049 static bool run_netbench(int client)
1051 struct cli_state *cli;
1056 const char *params[20];
1057 bool correct = True;
1063 smbXcli_conn_set_sockopt(cli->conn, sockops);
1067 slprintf(cname,sizeof(cname)-1, "client%d", client);
1069 f = fopen(client_txt, "r");
1076 while (fgets(line, sizeof(line)-1, f)) {
1080 line[strlen(line)-1] = 0;
1082 /* printf("[%d] %s\n", line_count, line); */
1084 all_string_sub(line,"client1", cname, sizeof(line));
1086 /* parse the command parameters */
1087 params[0] = strtok_r(line, " ", &saveptr);
1089 while (params[i]) params[++i] = strtok_r(NULL, " ", &saveptr);
1093 if (i < 2) continue;
1095 if (!strncmp(params[0],"SMB", 3)) {
1096 printf("ERROR: You are using a dbench 1 load file\n");
1100 if (!strcmp(params[0],"NTCreateX")) {
1101 nb_createx(params[1], ival(params[2]), ival(params[3]),
1103 } else if (!strcmp(params[0],"Close")) {
1104 nb_close(ival(params[1]));
1105 } else if (!strcmp(params[0],"Rename")) {
1106 nb_rename(params[1], params[2]);
1107 } else if (!strcmp(params[0],"Unlink")) {
1108 nb_unlink(params[1]);
1109 } else if (!strcmp(params[0],"Deltree")) {
1110 nb_deltree(params[1]);
1111 } else if (!strcmp(params[0],"Rmdir")) {
1112 nb_rmdir(params[1]);
1113 } else if (!strcmp(params[0],"QUERY_PATH_INFORMATION")) {
1114 nb_qpathinfo(params[1]);
1115 } else if (!strcmp(params[0],"QUERY_FILE_INFORMATION")) {
1116 nb_qfileinfo(ival(params[1]));
1117 } else if (!strcmp(params[0],"QUERY_FS_INFORMATION")) {
1118 nb_qfsinfo(ival(params[1]));
1119 } else if (!strcmp(params[0],"FIND_FIRST")) {
1120 nb_findfirst(params[1]);
1121 } else if (!strcmp(params[0],"WriteX")) {
1122 nb_writex(ival(params[1]),
1123 ival(params[2]), ival(params[3]), ival(params[4]));
1124 } else if (!strcmp(params[0],"ReadX")) {
1125 nb_readx(ival(params[1]),
1126 ival(params[2]), ival(params[3]), ival(params[4]));
1127 } else if (!strcmp(params[0],"Flush")) {
1128 nb_flush(ival(params[1]));
1130 printf("Unknown operation %s\n", params[0]);
1138 if (!torture_close_connection(cli)) {
1146 /* run a test that simulates an approximate netbench client load */
1147 static bool run_nbench(int dummy)
1150 bool correct = True;
1152 nbio_shmem(torture_nprocs);
1156 signal(SIGALRM, nb_alarm);
1158 t = create_procs(run_netbench, &correct);
1161 printf("\nThroughput %g MB/sec\n",
1162 1.0e-6 * nbio_total() / t);
1168 This test checks for two things:
1170 1) correct support for retaining locks over a close (ie. the server
1171 must not use posix semantics)
1172 2) support for lock timeouts
1174 static bool run_locktest1(int dummy)
1176 struct cli_state *cli1, *cli2;
1177 const char *fname = "\\lockt1.lck";
1178 uint16_t fnum1, fnum2, fnum3;
1180 unsigned lock_timeout;
1183 if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
1186 smbXcli_conn_set_sockopt(cli1->conn, sockops);
1187 smbXcli_conn_set_sockopt(cli2->conn, sockops);
1189 printf("starting locktest1\n");
1191 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1193 status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
1195 if (!NT_STATUS_IS_OK(status)) {
1196 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
1200 status = cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum2);
1201 if (!NT_STATUS_IS_OK(status)) {
1202 printf("open2 of %s failed (%s)\n", fname, nt_errstr(status));
1206 status = cli_openx(cli2, fname, O_RDWR, DENY_NONE, &fnum3);
1207 if (!NT_STATUS_IS_OK(status)) {
1208 printf("open3 of %s failed (%s)\n", fname, nt_errstr(status));
1212 status = cli_lock32(cli1, fnum1, 0, 4, 0, WRITE_LOCK);
1213 if (!NT_STATUS_IS_OK(status)) {
1214 printf("lock1 failed (%s)\n", nt_errstr(status));
1218 status = cli_lock32(cli2, fnum3, 0, 4, 0, WRITE_LOCK);
1219 if (NT_STATUS_IS_OK(status)) {
1220 printf("lock2 succeeded! This is a locking bug\n");
1223 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1224 NT_STATUS_LOCK_NOT_GRANTED)) {
1229 lock_timeout = (1 + (random() % 20));
1230 printf("Testing lock timeout with timeout=%u\n", lock_timeout);
1232 status = cli_lock32(cli2, fnum3, 0, 4, lock_timeout * 1000, WRITE_LOCK);
1233 if (NT_STATUS_IS_OK(status)) {
1234 printf("lock3 succeeded! This is a locking bug\n");
1237 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1238 NT_STATUS_FILE_LOCK_CONFLICT)) {
1244 if (ABS(t2 - t1) < lock_timeout-1) {
1245 printf("error: This server appears not to support timed lock requests\n");
1248 printf("server slept for %u seconds for a %u second timeout\n",
1249 (unsigned int)(t2-t1), lock_timeout);
1251 status = cli_close(cli1, fnum2);
1252 if (!NT_STATUS_IS_OK(status)) {
1253 printf("close1 failed (%s)\n", nt_errstr(status));
1257 status = cli_lock32(cli2, fnum3, 0, 4, 0, WRITE_LOCK);
1258 if (NT_STATUS_IS_OK(status)) {
1259 printf("lock4 succeeded! This is a locking bug\n");
1262 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1263 NT_STATUS_FILE_LOCK_CONFLICT)) {
1268 status = cli_close(cli1, fnum1);
1269 if (!NT_STATUS_IS_OK(status)) {
1270 printf("close2 failed (%s)\n", nt_errstr(status));
1274 status = cli_close(cli2, fnum3);
1275 if (!NT_STATUS_IS_OK(status)) {
1276 printf("close3 failed (%s)\n", nt_errstr(status));
1280 status = cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1281 if (!NT_STATUS_IS_OK(status)) {
1282 printf("unlink failed (%s)\n", nt_errstr(status));
1287 if (!torture_close_connection(cli1)) {
1291 if (!torture_close_connection(cli2)) {
1295 printf("Passed locktest1\n");
1300 this checks to see if a secondary tconx can use open files from an
1303 static bool run_tcon_test(int dummy)
1305 static struct cli_state *cli;
1306 const char *fname = "\\tcontest.tmp";
1308 uint32_t cnum1, cnum2, cnum3;
1309 struct smbXcli_tcon *orig_tcon = NULL;
1310 uint16_t vuid1, vuid2;
1315 memset(buf, '\0', sizeof(buf));
1317 if (!torture_open_connection(&cli, 0)) {
1320 smbXcli_conn_set_sockopt(cli->conn, sockops);
1322 printf("starting tcontest\n");
1324 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1326 status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
1327 if (!NT_STATUS_IS_OK(status)) {
1328 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
1332 cnum1 = cli_state_get_tid(cli);
1333 vuid1 = cli_state_get_uid(cli);
1335 status = cli_writeall(cli, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
1336 if (!NT_STATUS_IS_OK(status)) {
1337 printf("initial write failed (%s)", nt_errstr(status));
1341 orig_tcon = cli_state_save_tcon(cli);
1342 if (orig_tcon == NULL) {
1346 status = cli_tree_connect_creds(cli, share, "?????", torture_creds);
1347 if (!NT_STATUS_IS_OK(status)) {
1348 printf("%s refused 2nd tree connect (%s)\n", host,
1350 cli_state_restore_tcon(cli, orig_tcon);
1355 cnum2 = cli_state_get_tid(cli);
1356 cnum3 = MAX(cnum1, cnum2) + 1; /* any invalid number */
1357 vuid2 = cli_state_get_uid(cli) + 1;
1359 /* try a write with the wrong tid */
1360 cli_state_set_tid(cli, cnum2);
1362 status = cli_writeall(cli, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
1363 if (NT_STATUS_IS_OK(status)) {
1364 printf("* server allows write with wrong TID\n");
1367 printf("server fails write with wrong TID : %s\n",
1372 /* try a write with an invalid tid */
1373 cli_state_set_tid(cli, cnum3);
1375 status = cli_writeall(cli, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
1376 if (NT_STATUS_IS_OK(status)) {
1377 printf("* server allows write with invalid TID\n");
1380 printf("server fails write with invalid TID : %s\n",
1384 /* try a write with an invalid vuid */
1385 cli_state_set_uid(cli, vuid2);
1386 cli_state_set_tid(cli, cnum1);
1388 status = cli_writeall(cli, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
1389 if (NT_STATUS_IS_OK(status)) {
1390 printf("* server allows write with invalid VUID\n");
1393 printf("server fails write with invalid VUID : %s\n",
1397 cli_state_set_tid(cli, cnum1);
1398 cli_state_set_uid(cli, vuid1);
1400 status = cli_close(cli, fnum1);
1401 if (!NT_STATUS_IS_OK(status)) {
1402 printf("close failed (%s)\n", nt_errstr(status));
1403 cli_state_restore_tcon(cli, orig_tcon);
1408 cli_state_set_tid(cli, cnum2);
1410 status = cli_tdis(cli);
1411 if (!NT_STATUS_IS_OK(status)) {
1412 printf("secondary tdis failed (%s)\n", nt_errstr(status));
1413 cli_state_restore_tcon(cli, orig_tcon);
1418 cli_state_restore_tcon(cli, orig_tcon);
1420 cli_state_set_tid(cli, cnum1);
1422 if (!torture_close_connection(cli)) {
1431 checks for old style tcon support
1433 static bool run_tcon2_test(int dummy)
1435 static struct cli_state *cli;
1436 uint16_t cnum, max_xmit;
1440 if (!torture_open_connection(&cli, 0)) {
1443 smbXcli_conn_set_sockopt(cli->conn, sockops);
1445 printf("starting tcon2 test\n");
1447 if (asprintf(&service, "\\\\%s\\%s", host, share) == -1) {
1451 status = cli_raw_tcon(cli, service, password, "?????", &max_xmit, &cnum);
1455 if (!NT_STATUS_IS_OK(status)) {
1456 printf("tcon2 failed : %s\n", nt_errstr(status));
1458 printf("tcon OK : max_xmit=%d cnum=%d\n",
1459 (int)max_xmit, (int)cnum);
1462 if (!torture_close_connection(cli)) {
1466 printf("Passed tcon2 test\n");
1470 static bool tcon_devtest(struct cli_state *cli,
1471 const char *myshare, const char *devtype,
1472 const char *return_devtype,
1473 NTSTATUS expected_error)
1478 status = cli_tree_connect_creds(cli, myshare, devtype, torture_creds);
1480 if (NT_STATUS_IS_OK(expected_error)) {
1481 if (NT_STATUS_IS_OK(status)) {
1482 if (return_devtype != NULL &&
1483 strequal(cli->dev, return_devtype)) {
1486 printf("tconX to share %s with type %s "
1487 "succeeded but returned the wrong "
1488 "device type (got [%s] but should have got [%s])\n",
1489 myshare, devtype, cli->dev, return_devtype);
1493 printf("tconX to share %s with type %s "
1494 "should have succeeded but failed\n",
1500 if (NT_STATUS_IS_OK(status)) {
1501 printf("tconx to share %s with type %s "
1502 "should have failed but succeeded\n",
1506 if (NT_STATUS_EQUAL(status, expected_error)) {
1509 printf("Returned unexpected error\n");
1518 checks for correct tconX support
1520 static bool run_tcon_devtype_test(int dummy)
1522 static struct cli_state *cli1 = NULL;
1523 int flags = CLI_FULL_CONNECTION_FORCE_SMB1;
1527 status = cli_full_connection_creds(&cli1,
1533 NULL, /* service_type */
1537 if (!NT_STATUS_IS_OK(status)) {
1538 printf("could not open connection\n");
1542 if (!tcon_devtest(cli1, "IPC$", "A:", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1545 if (!tcon_devtest(cli1, "IPC$", "?????", "IPC", NT_STATUS_OK))
1548 if (!tcon_devtest(cli1, "IPC$", "LPT:", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1551 if (!tcon_devtest(cli1, "IPC$", "IPC", "IPC", NT_STATUS_OK))
1554 if (!tcon_devtest(cli1, "IPC$", "FOOBA", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1557 if (!tcon_devtest(cli1, share, "A:", "A:", NT_STATUS_OK))
1560 if (!tcon_devtest(cli1, share, "?????", "A:", NT_STATUS_OK))
1563 if (!tcon_devtest(cli1, share, "LPT:", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1566 if (!tcon_devtest(cli1, share, "IPC", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1569 if (!tcon_devtest(cli1, share, "FOOBA", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1575 printf("Passed tcondevtest\n");
1582 This test checks that
1584 1) the server supports multiple locking contexts on the one SMB
1585 connection, distinguished by PID.
1587 2) the server correctly fails overlapping locks made by the same PID (this
1588 goes against POSIX behaviour, which is why it is tricky to implement)
1590 3) the server denies unlock requests by an incorrect client PID
1592 static bool run_locktest2(int dummy)
1594 static struct cli_state *cli;
1595 const char *fname = "\\lockt2.lck";
1596 uint16_t fnum1, fnum2, fnum3;
1597 bool correct = True;
1600 if (!torture_open_connection(&cli, 0)) {
1604 smbXcli_conn_set_sockopt(cli->conn, sockops);
1606 printf("starting locktest2\n");
1608 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1612 status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
1613 if (!NT_STATUS_IS_OK(status)) {
1614 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
1618 status = cli_openx(cli, fname, O_RDWR, DENY_NONE, &fnum2);
1619 if (!NT_STATUS_IS_OK(status)) {
1620 printf("open2 of %s failed (%s)\n", fname, nt_errstr(status));
1626 status = cli_openx(cli, fname, O_RDWR, DENY_NONE, &fnum3);
1627 if (!NT_STATUS_IS_OK(status)) {
1628 printf("open3 of %s failed (%s)\n", fname, nt_errstr(status));
1634 status = cli_lock32(cli, fnum1, 0, 4, 0, WRITE_LOCK);
1635 if (!NT_STATUS_IS_OK(status)) {
1636 printf("lock1 failed (%s)\n", nt_errstr(status));
1640 status = cli_lock32(cli, fnum1, 0, 4, 0, WRITE_LOCK);
1641 if (NT_STATUS_IS_OK(status)) {
1642 printf("WRITE lock1 succeeded! This is a locking bug\n");
1645 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1646 NT_STATUS_LOCK_NOT_GRANTED)) {
1651 status = cli_lock32(cli, fnum2, 0, 4, 0, WRITE_LOCK);
1652 if (NT_STATUS_IS_OK(status)) {
1653 printf("WRITE lock2 succeeded! This is a locking bug\n");
1656 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1657 NT_STATUS_LOCK_NOT_GRANTED)) {
1662 status = cli_lock32(cli, fnum2, 0, 4, 0, READ_LOCK);
1663 if (NT_STATUS_IS_OK(status)) {
1664 printf("READ lock2 succeeded! This is a locking bug\n");
1667 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1668 NT_STATUS_FILE_LOCK_CONFLICT)) {
1673 status = cli_lock32(cli, fnum1, 100, 4, 0, WRITE_LOCK);
1674 if (!NT_STATUS_IS_OK(status)) {
1675 printf("lock at 100 failed (%s)\n", nt_errstr(status));
1678 if (NT_STATUS_IS_OK(cli_unlock(cli, fnum1, 100, 4))) {
1679 printf("unlock at 100 succeeded! This is a locking bug\n");
1683 status = cli_unlock(cli, fnum1, 0, 4);
1684 if (NT_STATUS_IS_OK(status)) {
1685 printf("unlock1 succeeded! This is a locking bug\n");
1688 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1689 NT_STATUS_RANGE_NOT_LOCKED)) {
1694 status = cli_unlock(cli, fnum1, 0, 8);
1695 if (NT_STATUS_IS_OK(status)) {
1696 printf("unlock2 succeeded! This is a locking bug\n");
1699 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1700 NT_STATUS_RANGE_NOT_LOCKED)) {
1705 status = cli_lock32(cli, fnum3, 0, 4, 0, WRITE_LOCK);
1706 if (NT_STATUS_IS_OK(status)) {
1707 printf("lock3 succeeded! This is a locking bug\n");
1710 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1711 NT_STATUS_LOCK_NOT_GRANTED)) {
1718 status = cli_close(cli, fnum1);
1719 if (!NT_STATUS_IS_OK(status)) {
1720 printf("close1 failed (%s)\n", nt_errstr(status));
1724 status = cli_close(cli, fnum2);
1725 if (!NT_STATUS_IS_OK(status)) {
1726 printf("close2 failed (%s)\n", nt_errstr(status));
1730 status = cli_close(cli, fnum3);
1731 if (!NT_STATUS_IS_OK(status)) {
1732 printf("close3 failed (%s)\n", nt_errstr(status));
1736 if (!torture_close_connection(cli)) {
1740 printf("locktest2 finished\n");
1747 This test checks that
1749 1) the server supports the full offset range in lock requests
1751 static bool run_locktest3(int dummy)
1753 static struct cli_state *cli1, *cli2;
1754 const char *fname = "\\lockt3.lck";
1755 uint16_t fnum1, fnum2;
1758 bool correct = True;
1761 #define NEXT_OFFSET offset += (~(uint32_t)0) / torture_numops
1763 if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
1766 smbXcli_conn_set_sockopt(cli1->conn, sockops);
1767 smbXcli_conn_set_sockopt(cli2->conn, sockops);
1769 printf("starting locktest3\n");
1771 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1773 status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
1775 if (!NT_STATUS_IS_OK(status)) {
1776 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
1780 status = cli_openx(cli2, fname, O_RDWR, DENY_NONE, &fnum2);
1781 if (!NT_STATUS_IS_OK(status)) {
1782 printf("open2 of %s failed (%s)\n", fname, nt_errstr(status));
1786 for (offset=i=0;i<torture_numops;i++) {
1789 status = cli_lock32(cli1, fnum1, offset-1, 1, 0, WRITE_LOCK);
1790 if (!NT_STATUS_IS_OK(status)) {
1791 printf("lock1 %d failed (%s)\n",
1797 status = cli_lock32(cli2, fnum2, offset-2, 1, 0, WRITE_LOCK);
1798 if (!NT_STATUS_IS_OK(status)) {
1799 printf("lock2 %d failed (%s)\n",
1806 for (offset=i=0;i<torture_numops;i++) {
1809 status = cli_lock32(cli1, fnum1, offset-2, 1, 0, WRITE_LOCK);
1810 if (NT_STATUS_IS_OK(status)) {
1811 printf("error: lock1 %d succeeded!\n", i);
1815 status = cli_lock32(cli2, fnum2, offset-1, 1, 0, WRITE_LOCK);
1816 if (NT_STATUS_IS_OK(status)) {
1817 printf("error: lock2 %d succeeded!\n", i);
1821 status = cli_lock32(cli1, fnum1, offset-1, 1, 0, WRITE_LOCK);
1822 if (NT_STATUS_IS_OK(status)) {
1823 printf("error: lock3 %d succeeded!\n", i);
1827 status = cli_lock32(cli2, fnum2, offset-2, 1, 0, WRITE_LOCK);
1828 if (NT_STATUS_IS_OK(status)) {
1829 printf("error: lock4 %d succeeded!\n", i);
1834 for (offset=i=0;i<torture_numops;i++) {
1837 status = cli_unlock(cli1, fnum1, offset-1, 1);
1838 if (!NT_STATUS_IS_OK(status)) {
1839 printf("unlock1 %d failed (%s)\n",
1845 status = cli_unlock(cli2, fnum2, offset-2, 1);
1846 if (!NT_STATUS_IS_OK(status)) {
1847 printf("unlock2 %d failed (%s)\n",
1854 status = cli_close(cli1, fnum1);
1855 if (!NT_STATUS_IS_OK(status)) {
1856 printf("close1 failed (%s)\n", nt_errstr(status));
1860 status = cli_close(cli2, fnum2);
1861 if (!NT_STATUS_IS_OK(status)) {
1862 printf("close2 failed (%s)\n", nt_errstr(status));
1866 status = cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1867 if (!NT_STATUS_IS_OK(status)) {
1868 printf("unlink failed (%s)\n", nt_errstr(status));
1872 if (!torture_close_connection(cli1)) {
1876 if (!torture_close_connection(cli2)) {
1880 printf("finished locktest3\n");
1885 static bool test_cli_read(struct cli_state *cli, uint16_t fnum,
1886 char *buf, off_t offset, size_t size,
1887 size_t *nread, size_t expect)
1892 status = cli_read(cli, fnum, buf, offset, size, &l_nread);
1894 if(!NT_STATUS_IS_OK(status)) {
1896 } else if (l_nread != expect) {
1907 #define EXPECTED(ret, v) if ((ret) != (v)) { \
1908 printf("** "); correct = False; \
1912 looks at overlapping locks
1914 static bool run_locktest4(int dummy)
1916 static struct cli_state *cli1, *cli2;
1917 const char *fname = "\\lockt4.lck";
1918 uint16_t fnum1, fnum2, f;
1921 bool correct = True;
1924 if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
1928 smbXcli_conn_set_sockopt(cli1->conn, sockops);
1929 smbXcli_conn_set_sockopt(cli2->conn, sockops);
1931 printf("starting locktest4\n");
1933 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1935 cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
1936 cli_openx(cli2, fname, O_RDWR, DENY_NONE, &fnum2);
1938 memset(buf, 0, sizeof(buf));
1940 status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 0, sizeof(buf),
1942 if (!NT_STATUS_IS_OK(status)) {
1943 printf("Failed to create file: %s\n", nt_errstr(status));
1948 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 4, 0, WRITE_LOCK)) &&
1949 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 2, 4, 0, WRITE_LOCK));
1950 EXPECTED(ret, False);
1951 printf("the same process %s set overlapping write locks\n", ret?"can":"cannot");
1953 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 10, 4, 0, READ_LOCK)) &&
1954 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 12, 4, 0, READ_LOCK));
1955 EXPECTED(ret, True);
1956 printf("the same process %s set overlapping read locks\n", ret?"can":"cannot");
1958 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 20, 4, 0, WRITE_LOCK)) &&
1959 NT_STATUS_IS_OK(cli_lock32(cli2, fnum2, 22, 4, 0, WRITE_LOCK));
1960 EXPECTED(ret, False);
1961 printf("a different connection %s set overlapping write locks\n", ret?"can":"cannot");
1963 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 30, 4, 0, READ_LOCK)) &&
1964 NT_STATUS_IS_OK(cli_lock32(cli2, fnum2, 32, 4, 0, READ_LOCK));
1965 EXPECTED(ret, True);
1966 printf("a different connection %s set overlapping read locks\n", ret?"can":"cannot");
1968 ret = (cli_setpid(cli1, 1),
1969 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 40, 4, 0, WRITE_LOCK))) &&
1970 (cli_setpid(cli1, 2),
1971 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 42, 4, 0, WRITE_LOCK)));
1972 EXPECTED(ret, False);
1973 printf("a different pid %s set overlapping write locks\n", ret?"can":"cannot");
1975 ret = (cli_setpid(cli1, 1),
1976 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 50, 4, 0, READ_LOCK))) &&
1977 (cli_setpid(cli1, 2),
1978 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 52, 4, 0, READ_LOCK)));
1979 EXPECTED(ret, True);
1980 printf("a different pid %s set overlapping read locks\n", ret?"can":"cannot");
1982 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 60, 4, 0, READ_LOCK)) &&
1983 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 60, 4, 0, READ_LOCK));
1984 EXPECTED(ret, True);
1985 printf("the same process %s set the same read lock twice\n", ret?"can":"cannot");
1987 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 70, 4, 0, WRITE_LOCK)) &&
1988 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 70, 4, 0, WRITE_LOCK));
1989 EXPECTED(ret, False);
1990 printf("the same process %s set the same write lock twice\n", ret?"can":"cannot");
1992 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 80, 4, 0, READ_LOCK)) &&
1993 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 80, 4, 0, WRITE_LOCK));
1994 EXPECTED(ret, False);
1995 printf("the same process %s overlay a read lock with a write lock\n", ret?"can":"cannot");
1997 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 90, 4, 0, WRITE_LOCK)) &&
1998 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 90, 4, 0, READ_LOCK));
1999 EXPECTED(ret, True);
2000 printf("the same process %s overlay a write lock with a read lock\n", ret?"can":"cannot");
2002 ret = (cli_setpid(cli1, 1),
2003 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 100, 4, 0, WRITE_LOCK))) &&
2004 (cli_setpid(cli1, 2),
2005 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 100, 4, 0, READ_LOCK)));
2006 EXPECTED(ret, False);
2007 printf("a different pid %s overlay a write lock with a read lock\n", ret?"can":"cannot");
2009 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 110, 4, 0, READ_LOCK)) &&
2010 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 112, 4, 0, READ_LOCK)) &&
2011 NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 110, 6));
2012 EXPECTED(ret, False);
2013 printf("the same process %s coalesce read locks\n", ret?"can":"cannot");
2016 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 120, 4, 0, WRITE_LOCK)) &&
2017 test_cli_read(cli2, fnum2, buf, 120, 4, NULL, 4);
2018 EXPECTED(ret, False);
2019 printf("this server %s strict write locking\n", ret?"doesn't do":"does");
2021 status = cli_lock32(cli1, fnum1, 130, 4, 0, READ_LOCK);
2022 ret = NT_STATUS_IS_OK(status);
2024 status = cli_writeall(cli2, fnum2, 0, (uint8_t *)buf, 130, 4,
2026 ret = NT_STATUS_IS_OK(status);
2028 EXPECTED(ret, False);
2029 printf("this server %s strict read locking\n", ret?"doesn't do":"does");
2032 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 140, 4, 0, READ_LOCK)) &&
2033 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 140, 4, 0, READ_LOCK)) &&
2034 NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 140, 4)) &&
2035 NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 140, 4));
2036 EXPECTED(ret, True);
2037 printf("this server %s do recursive read locking\n", ret?"does":"doesn't");
2040 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 150, 4, 0, WRITE_LOCK)) &&
2041 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 150, 4, 0, READ_LOCK)) &&
2042 NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 150, 4)) &&
2043 test_cli_read(cli2, fnum2, buf, 150, 4, NULL, 4) &&
2044 !(NT_STATUS_IS_OK(cli_writeall(cli2, fnum2, 0, (uint8_t *)buf,
2046 NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 150, 4));
2047 EXPECTED(ret, True);
2048 printf("this server %s do recursive lock overlays\n", ret?"does":"doesn't");
2050 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 160, 4, 0, READ_LOCK)) &&
2051 NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 160, 4)) &&
2052 NT_STATUS_IS_OK(cli_writeall(cli2, fnum2, 0, (uint8_t *)buf,
2054 test_cli_read(cli2, fnum2, buf, 160, 4, NULL, 4);
2055 EXPECTED(ret, True);
2056 printf("the same process %s remove a read lock using write locking\n", ret?"can":"cannot");
2058 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 170, 4, 0, WRITE_LOCK)) &&
2059 NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 170, 4)) &&
2060 NT_STATUS_IS_OK(cli_writeall(cli2, fnum2, 0, (uint8_t *)buf,
2062 test_cli_read(cli2, fnum2, buf, 170, 4, NULL, 4);
2063 EXPECTED(ret, True);
2064 printf("the same process %s remove a write lock using read locking\n", ret?"can":"cannot");
2066 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 190, 4, 0, WRITE_LOCK)) &&
2067 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 190, 4, 0, READ_LOCK)) &&
2068 NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 190, 4)) &&
2069 !NT_STATUS_IS_OK(cli_writeall(cli2, fnum2, 0, (uint8_t *)buf,
2071 test_cli_read(cli2, fnum2, buf, 190, 4, NULL, 4);
2072 EXPECTED(ret, True);
2073 printf("the same process %s remove the first lock first\n", ret?"does":"doesn't");
2075 cli_close(cli1, fnum1);
2076 cli_close(cli2, fnum2);
2077 cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
2078 cli_openx(cli1, fname, O_RDWR, DENY_NONE, &f);
2079 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 8, 0, READ_LOCK)) &&
2080 NT_STATUS_IS_OK(cli_lock32(cli1, f, 0, 1, 0, READ_LOCK)) &&
2081 NT_STATUS_IS_OK(cli_close(cli1, fnum1)) &&
2082 NT_STATUS_IS_OK(cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1)) &&
2083 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 7, 1, 0, WRITE_LOCK));
2085 cli_close(cli1, fnum1);
2086 EXPECTED(ret, True);
2087 printf("the server %s have the NT byte range lock bug\n", !ret?"does":"doesn't");
2090 cli_close(cli1, fnum1);
2091 cli_close(cli2, fnum2);
2092 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2093 torture_close_connection(cli1);
2094 torture_close_connection(cli2);
2096 printf("finished locktest4\n");
2101 looks at lock upgrade/downgrade.
2103 static bool run_locktest5(int dummy)
2105 static struct cli_state *cli1, *cli2;
2106 const char *fname = "\\lockt5.lck";
2107 uint16_t fnum1, fnum2, fnum3;
2110 bool correct = True;
2113 if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
2117 smbXcli_conn_set_sockopt(cli1->conn, sockops);
2118 smbXcli_conn_set_sockopt(cli2->conn, sockops);
2120 printf("starting locktest5\n");
2122 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2124 cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
2125 cli_openx(cli2, fname, O_RDWR, DENY_NONE, &fnum2);
2126 cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum3);
2128 memset(buf, 0, sizeof(buf));
2130 status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 0, sizeof(buf),
2132 if (!NT_STATUS_IS_OK(status)) {
2133 printf("Failed to create file: %s\n", nt_errstr(status));
2138 /* Check for NT bug... */
2139 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 8, 0, READ_LOCK)) &&
2140 NT_STATUS_IS_OK(cli_lock32(cli1, fnum3, 0, 1, 0, READ_LOCK));
2141 cli_close(cli1, fnum1);
2142 cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
2143 status = cli_lock32(cli1, fnum1, 7, 1, 0, WRITE_LOCK);
2144 ret = NT_STATUS_IS_OK(status);
2145 EXPECTED(ret, True);
2146 printf("this server %s the NT locking bug\n", ret ? "doesn't have" : "has");
2147 cli_close(cli1, fnum1);
2148 cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
2149 cli_unlock(cli1, fnum3, 0, 1);
2151 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 4, 0, WRITE_LOCK)) &&
2152 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 1, 1, 0, READ_LOCK));
2153 EXPECTED(ret, True);
2154 printf("the same process %s overlay a write with a read lock\n", ret?"can":"cannot");
2156 status = cli_lock32(cli2, fnum2, 0, 4, 0, READ_LOCK);
2157 ret = NT_STATUS_IS_OK(status);
2158 EXPECTED(ret, False);
2160 printf("a different process %s get a read lock on the first process lock stack\n", ret?"can":"cannot");
2162 /* Unlock the process 2 lock. */
2163 cli_unlock(cli2, fnum2, 0, 4);
2165 status = cli_lock32(cli1, fnum3, 0, 4, 0, READ_LOCK);
2166 ret = NT_STATUS_IS_OK(status);
2167 EXPECTED(ret, False);
2169 printf("the same process on a different fnum %s get a read lock\n", ret?"can":"cannot");
2171 /* Unlock the process 1 fnum3 lock. */
2172 cli_unlock(cli1, fnum3, 0, 4);
2174 /* Stack 2 more locks here. */
2175 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 4, 0, READ_LOCK)) &&
2176 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 4, 0, READ_LOCK));
2178 EXPECTED(ret, True);
2179 printf("the same process %s stack read locks\n", ret?"can":"cannot");
2181 /* Unlock the first process lock, then check this was the WRITE lock that was
2184 ret = NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 0, 4)) &&
2185 NT_STATUS_IS_OK(cli_lock32(cli2, fnum2, 0, 4, 0, READ_LOCK));
2187 EXPECTED(ret, True);
2188 printf("the first unlock removes the %s lock\n", ret?"WRITE":"READ");
2190 /* Unlock the process 2 lock. */
2191 cli_unlock(cli2, fnum2, 0, 4);
2193 /* We should have 3 stacked locks here. Ensure we need to do 3 unlocks. */
2195 ret = NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 1, 1)) &&
2196 NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 0, 4)) &&
2197 NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 0, 4));
2199 EXPECTED(ret, True);
2200 printf("the same process %s unlock the stack of 4 locks\n", ret?"can":"cannot");
2202 /* Ensure the next unlock fails. */
2203 ret = NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 0, 4));
2204 EXPECTED(ret, False);
2205 printf("the same process %s count the lock stack\n", !ret?"can":"cannot");
2207 /* Ensure connection 2 can get a write lock. */
2208 status = cli_lock32(cli2, fnum2, 0, 4, 0, WRITE_LOCK);
2209 ret = NT_STATUS_IS_OK(status);
2210 EXPECTED(ret, True);
2212 printf("a different process %s get a write lock on the unlocked stack\n", ret?"can":"cannot");
2216 cli_close(cli1, fnum1);
2217 cli_close(cli2, fnum2);
2218 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2219 if (!torture_close_connection(cli1)) {
2222 if (!torture_close_connection(cli2)) {
2226 printf("finished locktest5\n");
2232 tries the unusual lockingX locktype bits
2234 static bool run_locktest6(int dummy)
2236 static struct cli_state *cli;
2237 const char *fname[1] = { "\\lock6.txt" };
2242 if (!torture_open_connection(&cli, 0)) {
2246 smbXcli_conn_set_sockopt(cli->conn, sockops);
2248 printf("starting locktest6\n");
2251 printf("Testing %s\n", fname[i]);
2253 cli_unlink(cli, fname[i], FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2255 cli_openx(cli, fname[i], O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
2256 status = cli_locktype(cli, fnum, 0, 8, 0, LOCKING_ANDX_CHANGE_LOCKTYPE);
2257 cli_close(cli, fnum);
2258 printf("CHANGE_LOCKTYPE gave %s\n", nt_errstr(status));
2260 cli_openx(cli, fname[i], O_RDWR, DENY_NONE, &fnum);
2261 status = cli_locktype(cli, fnum, 0, 8, 0, LOCKING_ANDX_CANCEL_LOCK);
2262 cli_close(cli, fnum);
2263 printf("CANCEL_LOCK gave %s\n", nt_errstr(status));
2265 cli_unlink(cli, fname[i], FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2268 torture_close_connection(cli);
2270 printf("finished locktest6\n");
2274 static bool run_locktest7(int dummy)
2276 struct cli_state *cli1;
2277 const char *fname = "\\lockt7.lck";
2280 bool correct = False;
2284 if (!torture_open_connection(&cli1, 0)) {
2288 smbXcli_conn_set_sockopt(cli1->conn, sockops);
2290 printf("starting locktest7\n");
2292 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2294 cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
2296 memset(buf, 0, sizeof(buf));
2298 status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 0, sizeof(buf),
2300 if (!NT_STATUS_IS_OK(status)) {
2301 printf("Failed to create file: %s\n", nt_errstr(status));
2305 cli_setpid(cli1, 1);
2307 status = cli_lock32(cli1, fnum1, 130, 4, 0, READ_LOCK);
2308 if (!NT_STATUS_IS_OK(status)) {
2309 printf("Unable to apply read lock on range 130:4, "
2310 "error was %s\n", nt_errstr(status));
2313 printf("pid1 successfully locked range 130:4 for READ\n");
2316 status = cli_read(cli1, fnum1, buf, 130, 4, &nread);
2317 if (!NT_STATUS_IS_OK(status)) {
2318 printf("pid1 unable to read the range 130:4, error was %s\n",
2321 } else if (nread != 4) {
2322 printf("pid1 unable to read the range 130:4, "
2323 "recv %ld req %d\n", (unsigned long)nread, 4);
2326 printf("pid1 successfully read the range 130:4\n");
2329 status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
2330 if (!NT_STATUS_IS_OK(status)) {
2331 printf("pid1 unable to write to the range 130:4, error was "
2332 "%s\n", nt_errstr(status));
2333 if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
2334 printf("Incorrect error (should be NT_STATUS_FILE_LOCK_CONFLICT)\n");
2338 printf("pid1 successfully wrote to the range 130:4 (should be denied)\n");
2342 cli_setpid(cli1, 2);
2344 status = cli_read(cli1, fnum1, buf, 130, 4, &nread);
2345 if (!NT_STATUS_IS_OK(status)) {
2346 printf("pid2 unable to read the range 130:4, error was %s\n",
2349 } else if (nread != 4) {
2350 printf("pid2 unable to read the range 130:4, "
2351 "recv %ld req %d\n", (unsigned long)nread, 4);
2354 printf("pid2 successfully read the range 130:4\n");
2357 status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
2358 if (!NT_STATUS_IS_OK(status)) {
2359 printf("pid2 unable to write to the range 130:4, error was "
2360 "%s\n", nt_errstr(status));
2361 if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
2362 printf("Incorrect error (should be NT_STATUS_FILE_LOCK_CONFLICT)\n");
2366 printf("pid2 successfully wrote to the range 130:4 (should be denied)\n");
2370 cli_setpid(cli1, 1);
2371 cli_unlock(cli1, fnum1, 130, 4);
2373 status = cli_lock32(cli1, fnum1, 130, 4, 0, WRITE_LOCK);
2374 if (!NT_STATUS_IS_OK(status)) {
2375 printf("Unable to apply write lock on range 130:4, error was %s\n", nt_errstr(status));
2378 printf("pid1 successfully locked range 130:4 for WRITE\n");
2381 status = cli_read(cli1, fnum1, buf, 130, 4, &nread);
2382 if (!NT_STATUS_IS_OK(status)) {
2383 printf("pid1 unable to read the range 130:4, error was %s\n",
2386 } else if (nread != 4) {
2387 printf("pid1 unable to read the range 130:4, "
2388 "recv %ld req %d\n", (unsigned long)nread, 4);
2391 printf("pid1 successfully read the range 130:4\n");
2394 status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
2395 if (!NT_STATUS_IS_OK(status)) {
2396 printf("pid1 unable to write to the range 130:4, error was "
2397 "%s\n", nt_errstr(status));
2400 printf("pid1 successfully wrote to the range 130:4\n");
2403 cli_setpid(cli1, 2);
2405 status = cli_read(cli1, fnum1, buf, 130, 4, &nread);
2406 if (!NT_STATUS_IS_OK(status)) {
2407 printf("pid2 unable to read the range 130:4, error was "
2408 "%s\n", nt_errstr(status));
2409 if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
2410 printf("Incorrect error (should be NT_STATUS_FILE_LOCK_CONFLICT)\n");
2414 printf("pid2 successfully read the range 130:4 (should be denied) recv %ld\n",
2415 (unsigned long)nread);
2419 status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
2420 if (!NT_STATUS_IS_OK(status)) {
2421 printf("pid2 unable to write to the range 130:4, error was "
2422 "%s\n", nt_errstr(status));
2423 if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
2424 printf("Incorrect error (should be NT_STATUS_FILE_LOCK_CONFLICT)\n");
2428 printf("pid2 successfully wrote to the range 130:4 (should be denied)\n");
2432 cli_unlock(cli1, fnum1, 130, 0);
2436 cli_close(cli1, fnum1);
2437 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2438 torture_close_connection(cli1);
2440 printf("finished locktest7\n");
2445 * This demonstrates a problem with our use of GPFS share modes: A file
2446 * descriptor sitting in the pending close queue holding a GPFS share mode
2447 * blocks opening a file another time. Happens with Word 2007 temp files.
2448 * With "posix locking = yes" and "gpfs:sharemodes = yes" enabled, the third
2449 * open is denied with NT_STATUS_SHARING_VIOLATION.
2452 static bool run_locktest8(int dummy)
2454 struct cli_state *cli1;
2455 const char *fname = "\\lockt8.lck";
2456 uint16_t fnum1, fnum2;
2458 bool correct = False;
2461 if (!torture_open_connection(&cli1, 0)) {
2465 smbXcli_conn_set_sockopt(cli1->conn, sockops);
2467 printf("starting locktest8\n");
2469 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2471 status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_WRITE,
2473 if (!NT_STATUS_IS_OK(status)) {
2474 d_fprintf(stderr, "cli_openx returned %s\n", nt_errstr(status));
2478 memset(buf, 0, sizeof(buf));
2480 status = cli_openx(cli1, fname, O_RDONLY, DENY_NONE, &fnum2);
2481 if (!NT_STATUS_IS_OK(status)) {
2482 d_fprintf(stderr, "cli_openx second time returned %s\n",
2487 status = cli_lock32(cli1, fnum2, 1, 1, 0, READ_LOCK);
2488 if (!NT_STATUS_IS_OK(status)) {
2489 printf("Unable to apply read lock on range 1:1, error was "
2490 "%s\n", nt_errstr(status));
2494 status = cli_close(cli1, fnum1);
2495 if (!NT_STATUS_IS_OK(status)) {
2496 d_fprintf(stderr, "cli_close(fnum1) %s\n", nt_errstr(status));
2500 status = cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
2501 if (!NT_STATUS_IS_OK(status)) {
2502 d_fprintf(stderr, "cli_openx third time returned %s\n",
2510 cli_close(cli1, fnum1);
2511 cli_close(cli1, fnum2);
2512 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2513 torture_close_connection(cli1);
2515 printf("finished locktest8\n");
2520 * This test is designed to be run in conjunction with
2521 * external NFS or POSIX locks taken in the filesystem.
2522 * It checks that the smbd server will block until the
2523 * lock is released and then acquire it. JRA.
2526 static bool got_alarm;
2527 static struct cli_state *alarm_cli;
2529 static void alarm_handler(int dummy)
2534 static void alarm_handler_parent(int dummy)
2536 smbXcli_conn_disconnect(alarm_cli->conn, NT_STATUS_LOCAL_DISCONNECT);
2539 static void do_local_lock(const char *fname, int read_fd, int write_fd)
2544 const char *local_pathname = NULL;
2547 local_pathname = talloc_asprintf(talloc_tos(),
2548 "%s/%s", local_path, fname);
2549 if (!local_pathname) {
2550 printf("child: alloc fail\n");
2554 unlink(local_pathname);
2555 fd = open(local_pathname, O_RDWR|O_CREAT, 0666);
2557 printf("child: open of %s failed %s.\n",
2558 local_pathname, strerror(errno));
2562 /* Now take a fcntl lock. */
2563 lock.l_type = F_WRLCK;
2564 lock.l_whence = SEEK_SET;
2567 lock.l_pid = getpid();
2569 ret = fcntl(fd,F_SETLK,&lock);
2571 printf("child: failed to get lock 0:4 on file %s. Error %s\n",
2572 local_pathname, strerror(errno));
2575 printf("child: got lock 0:4 on file %s.\n",
2580 CatchSignal(SIGALRM, alarm_handler);
2582 /* Signal the parent. */
2583 if (write(write_fd, &c, 1) != 1) {
2584 printf("child: start signal fail %s.\n",
2591 /* Wait for the parent to be ready. */
2592 if (read(read_fd, &c, 1) != 1) {
2593 printf("child: reply signal fail %s.\n",
2601 printf("child: released lock 0:4 on file %s.\n",
2607 static bool _run_locktest9X(const char *fname, int timeout)
2609 struct cli_state *cli1;
2610 char *fpath = talloc_asprintf(talloc_tos(), "\\%s", fname);
2612 bool correct = False;
2613 int pipe_in[2], pipe_out[2];
2617 struct timeval start;
2621 printf("starting locktest9X: %s\n", fname);
2623 if (local_path == NULL) {
2624 d_fprintf(stderr, "locktest9X must be given a local path via -l <localpath>\n");
2628 if (pipe(pipe_in) == -1 || pipe(pipe_out) == -1) {
2633 if (child_pid == -1) {
2637 if (child_pid == 0) {
2639 do_local_lock(fname, pipe_out[0], pipe_in[1]);
2649 ret = read(pipe_in[0], &c, 1);
2651 d_fprintf(stderr, "failed to read start signal from child. %s\n",
2656 if (!torture_open_connection(&cli1, 0)) {
2660 smbXcli_conn_set_sockopt(cli1->conn, sockops);
2662 status = cli_openx(cli1, fpath, O_RDWR, DENY_NONE,
2664 if (!NT_STATUS_IS_OK(status)) {
2665 d_fprintf(stderr, "cli_openx returned %s\n", nt_errstr(status));
2669 /* Ensure the child has the lock. */
2670 status = cli_lock32(cli1, fnum, 0, 4, 0, WRITE_LOCK);
2671 if (NT_STATUS_IS_OK(status)) {
2672 d_fprintf(stderr, "Got the lock on range 0:4 - this should not happen !\n");
2675 d_printf("Child has the lock.\n");
2678 /* Tell the child to wait 5 seconds then exit. */
2679 ret = write(pipe_out[1], &c, 1);
2681 d_fprintf(stderr, "failed to send exit signal to child. %s\n",
2686 /* Wait 20 seconds for the lock. */
2688 CatchSignal(SIGALRM, alarm_handler_parent);
2691 start = timeval_current();
2693 status = cli_lock32(cli1, fnum, 0, 4, timeout, WRITE_LOCK);
2694 if (!NT_STATUS_IS_OK(status)) {
2695 d_fprintf(stderr, "Unable to apply write lock on range 0:4, error was "
2696 "%s\n", nt_errstr(status));
2701 seconds = timeval_elapsed(&start);
2703 printf("Parent got the lock after %.2f seconds.\n",
2706 status = cli_close(cli1, fnum);
2707 if (!NT_STATUS_IS_OK(status)) {
2708 d_fprintf(stderr, "cli_close(fnum1) %s\n", nt_errstr(status));
2715 cli_close(cli1, fnum);
2716 torture_close_connection(cli1);
2720 printf("finished locktest9X: %s\n", fname);
2724 static bool run_locktest9a(int dummy)
2726 return _run_locktest9X("lock9a.dat", -1);
2729 static bool run_locktest9b(int dummy)
2731 return _run_locktest9X("lock9b.dat", 10000);
2734 struct locktest10_state {
2739 static void locktest10_lockingx_done(struct tevent_req *subreq);
2740 static void locktest10_read_andx_done(struct tevent_req *subreq);
2742 static bool run_locktest10(int dummy)
2744 struct tevent_context *ev = NULL;
2745 struct cli_state *cli1 = NULL;
2746 struct cli_state *cli2 = NULL;
2747 struct smb1_lock_element lck = { 0 };
2748 struct tevent_req *reqs[2] = { NULL };
2749 struct tevent_req *smbreqs[2] = { NULL };
2750 const char fname[] = "\\lockt10.lck";
2751 uint16_t fnum1, fnum2;
2755 struct locktest10_state state = { .ok = true };
2758 printf("starting locktest10\n");
2760 ev = samba_tevent_context_init(NULL);
2762 d_fprintf(stderr, "samba_tevent_context_init failed\n");
2766 ok = torture_open_connection(&cli1, 0);
2770 smbXcli_conn_set_sockopt(cli1->conn, sockops);
2772 ok = torture_open_connection(&cli2, 1);
2776 smbXcli_conn_set_sockopt(cli2->conn, sockops);
2778 status = cli_openx(cli1, fname, O_CREAT|O_RDWR, DENY_NONE, &fnum1);
2779 if (!NT_STATUS_IS_OK(status)) {
2781 "cli_openx failed: %s\n",
2786 status = cli_writeall(cli1, fnum1, 0, &data, 0, sizeof(data), NULL);
2787 if (!NT_STATUS_IS_OK(status)) {
2789 "cli_writeall failed: %s\n",
2794 status = cli_openx(cli2, fname, O_CREAT|O_RDWR, DENY_NONE, &fnum2);
2795 if (!NT_STATUS_IS_OK(status)) {
2797 "cli_openx failed: %s\n",
2802 status = cli_locktype(
2803 cli2, fnum2, 0, 1, 0, LOCKING_ANDX_EXCLUSIVE_LOCK);
2804 if (!NT_STATUS_IS_OK(status)) {
2806 "cli_locktype failed: %s\n",
2811 lck = (struct smb1_lock_element) {
2812 .pid = cli_getpid(cli1), .offset = 0, .length = 1,
2815 reqs[0] = cli_lockingx_create(
2817 ev, /* tevent_context */
2820 LOCKING_ANDX_EXCLUSIVE_LOCK, /* typeoflock */
2821 0, /* newoplocklevel */
2823 0, /* num_unlocks */
2827 &smbreqs[0]); /* psmbreq */
2828 if (reqs[0] == NULL) {
2829 d_fprintf(stderr, "cli_lockingx_create failed\n");
2832 tevent_req_set_callback(reqs[0], locktest10_lockingx_done, &state);
2834 reqs[1] = cli_read_andx_create(
2841 &smbreqs[1]); /* psmbreq */
2842 if (reqs[1] == NULL) {
2843 d_fprintf(stderr, "cli_read_andx_create failed\n");
2846 tevent_req_set_callback(reqs[1], locktest10_read_andx_done, &state);
2848 status = smb1cli_req_chain_submit(smbreqs, ARRAY_SIZE(smbreqs));
2849 if (!NT_STATUS_IS_OK(status)) {
2851 "smb1cli_req_chain_submit failed: %s\n",
2856 while (!state.done) {
2857 tevent_loop_once(ev);
2860 torture_close_connection(cli1);
2869 static void locktest10_lockingx_done(struct tevent_req *subreq)
2871 struct locktest10_state *state = tevent_req_callback_data_void(subreq);
2874 status = cli_lockingx_recv(subreq);
2875 TALLOC_FREE(subreq);
2877 if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
2878 d_printf("cli_lockingx returned %s\n", nt_errstr(status));
2883 static void locktest10_read_andx_done(struct tevent_req *subreq)
2885 struct locktest10_state *state = tevent_req_callback_data_void(subreq);
2886 ssize_t received = -1;
2887 uint8_t *rcvbuf = NULL;
2890 status = cli_read_andx_recv(subreq, &received, &rcvbuf);
2892 if (!NT_STATUS_EQUAL(status, NT_STATUS_REQUEST_ABORTED)) {
2893 d_printf("cli_read_andx returned %s\n", nt_errstr(status));
2898 TALLOC_FREE(subreq);
2901 static bool run_locktest11(int dummy)
2903 struct cli_state *cli1;
2904 const char *fname = "\\lockt11.lck";
2909 if (!torture_open_connection(&cli1, 0)) {
2913 smbXcli_conn_set_sockopt(cli1->conn, sockops);
2915 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2917 status = cli_openx(cli1, fname, O_CREAT|O_RDWR, DENY_NONE, &fnum);
2918 if (!NT_STATUS_IS_OK(status)) {
2920 "cli_openx returned %s\n",
2926 * Test that LOCKING_ANDX_CANCEL_LOCK without any locks
2927 * returns NT_STATUS_OK
2930 status = cli_lockingx(
2933 LOCKING_ANDX_CANCEL_LOCK, /* typeoflock */
2934 0, /* newoplocklevel */
2936 0, /* num_unlocks */
2941 if (!NT_STATUS_IS_OK(status)) {
2942 d_printf("cli_lockingX returned %s\n", nt_errstr(status));
2948 cli_close(cli1, fnum);
2949 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2954 struct deferred_close_state {
2955 struct tevent_context *ev;
2956 struct cli_state *cli;
2960 static void deferred_close_waited(struct tevent_req *subreq);
2961 static void deferred_close_done(struct tevent_req *subreq);
2963 static struct tevent_req *deferred_close_send(
2964 TALLOC_CTX *mem_ctx,
2965 struct tevent_context *ev,
2967 struct cli_state *cli,
2970 struct tevent_req *req = NULL, *subreq = NULL;
2971 struct deferred_close_state *state = NULL;
2972 struct timeval wakeup_time = timeval_current_ofs(wait_secs, 0);
2974 req = tevent_req_create(
2975 mem_ctx, &state, struct deferred_close_state);
2983 subreq = tevent_wakeup_send(state, state->ev, wakeup_time);
2984 if (tevent_req_nomem(subreq, req)) {
2985 return tevent_req_post(req, ev);
2987 tevent_req_set_callback(subreq, deferred_close_waited, req);
2991 static void deferred_close_waited(struct tevent_req *subreq)
2993 struct tevent_req *req = tevent_req_callback_data(
2994 subreq, struct tevent_req);
2995 struct deferred_close_state *state = tevent_req_data(
2996 req, struct deferred_close_state);
2999 ok = tevent_wakeup_recv(subreq);
3000 TALLOC_FREE(subreq);
3002 tevent_req_oom(req);
3006 subreq = cli_close_send(state, state->ev, state->cli, state->fnum);
3007 if (tevent_req_nomem(subreq, req)) {
3010 tevent_req_set_callback(subreq, deferred_close_done, req);
3013 static void deferred_close_done(struct tevent_req *subreq)
3015 NTSTATUS status = cli_close_recv(subreq);
3016 tevent_req_simple_finish_ntstatus(subreq, status);
3019 static NTSTATUS deferred_close_recv(struct tevent_req *req)
3021 return tevent_req_simple_recv_ntstatus(req);
3024 struct lockread_state {
3025 struct smb1_lock_element lck;
3026 struct tevent_req *reqs[2];
3027 struct tevent_req *smbreqs[2];
3028 NTSTATUS lock_status;
3029 NTSTATUS read_status;
3033 static void lockread_lockingx_done(struct tevent_req *subreq);
3034 static void lockread_read_andx_done(struct tevent_req *subreq);
3036 static struct tevent_req *lockread_send(
3037 TALLOC_CTX *mem_ctx,
3038 struct tevent_context *ev,
3039 struct cli_state *cli,
3042 struct tevent_req *req = NULL;
3043 struct lockread_state *state = NULL;
3046 req = tevent_req_create(mem_ctx, &state, struct lockread_state);
3051 state->lck = (struct smb1_lock_element) {
3052 .pid = cli_getpid(cli), .offset = 0, .length = 1,
3055 state->reqs[0] = cli_lockingx_create(
3057 ev, /* tevent_context */
3060 LOCKING_ANDX_EXCLUSIVE_LOCK, /* typeoflock */
3061 0, /* newoplocklevel */
3062 10000, /* timeout */
3063 0, /* num_unlocks */
3066 &state->lck, /* locks */
3067 &state->smbreqs[0]); /* psmbreq */
3068 if (tevent_req_nomem(state->reqs[0], req)) {
3069 return tevent_req_post(req, ev);
3071 tevent_req_set_callback(
3072 state->reqs[0], lockread_lockingx_done, req);
3074 state->reqs[1] = cli_read_andx_create(
3081 &state->smbreqs[1]); /* psmbreq */
3082 if (tevent_req_nomem(state->reqs[1], req)) {
3083 return tevent_req_post(req, ev);
3085 tevent_req_set_callback(
3086 state->reqs[1], lockread_read_andx_done, req);
3088 status = smb1cli_req_chain_submit(state->smbreqs, 2);
3089 if (tevent_req_nterror(req, status)) {
3090 return tevent_req_post(req, ev);
3095 static void lockread_lockingx_done(struct tevent_req *subreq)
3097 struct tevent_req *req = tevent_req_callback_data(
3098 subreq, struct tevent_req);
3099 struct lockread_state *state = tevent_req_data(
3100 req, struct lockread_state);
3101 state->lock_status = cli_lockingx_recv(subreq);
3102 TALLOC_FREE(subreq);
3104 "lockingx returned %s\n",
3105 nt_errstr(state->lock_status));
3108 static void lockread_read_andx_done(struct tevent_req *subreq)
3110 struct tevent_req *req = tevent_req_callback_data(
3111 subreq, struct tevent_req);
3112 struct lockread_state *state = tevent_req_data(
3113 req, struct lockread_state);
3114 ssize_t received = -1;
3115 uint8_t *rcvbuf = NULL;
3117 state->read_status = cli_read_andx_recv(subreq, &received, &rcvbuf);
3120 "read returned %s\n",
3121 nt_errstr(state->read_status));
3123 if (!NT_STATUS_IS_OK(state->read_status)) {
3124 TALLOC_FREE(subreq);
3125 tevent_req_done(req);
3130 state->readbuf = talloc_memdup(state, rcvbuf, received);
3131 TALLOC_FREE(subreq);
3132 if (tevent_req_nomem(state->readbuf, req)) {
3136 TALLOC_FREE(subreq);
3137 tevent_req_done(req);
3140 static NTSTATUS lockread_recv(
3141 struct tevent_req *req,
3142 NTSTATUS *lock_status,
3143 NTSTATUS *read_status,
3144 TALLOC_CTX *mem_ctx,
3147 struct lockread_state *state = tevent_req_data(
3148 req, struct lockread_state);
3151 if (tevent_req_is_nterror(req, &status)) {
3155 *lock_status = state->lock_status;
3156 *read_status = state->read_status;
3157 if (state->readbuf != NULL) {
3158 *read_buf = talloc_move(mem_ctx, &state->readbuf);
3163 return NT_STATUS_OK;
3166 struct lock12_state {
3170 static void lock12_closed(struct tevent_req *subreq);
3171 static void lock12_read(struct tevent_req *subreq);
3173 static struct tevent_req *lock12_send(
3174 TALLOC_CTX *mem_ctx,
3175 struct tevent_context *ev,
3176 struct cli_state *cli,
3180 struct tevent_req *req = NULL, *subreq = NULL;
3181 struct lock12_state *state = NULL;
3183 req = tevent_req_create(mem_ctx, &state, struct lock12_state);
3188 subreq = deferred_close_send(state, ev, 1, cli, fnum1);
3189 if (tevent_req_nomem(subreq, req)) {
3190 return tevent_req_post(req, ev);
3192 tevent_req_set_callback(subreq, lock12_closed, req);
3194 subreq = lockread_send(state, ev, cli, fnum2);
3195 if (tevent_req_nomem(subreq, req)) {
3196 return tevent_req_post(req, ev);
3198 tevent_req_set_callback(subreq, lock12_read, req);
3203 static void lock12_closed(struct tevent_req *subreq)
3205 struct tevent_req *req = tevent_req_callback_data(
3206 subreq, struct tevent_req);
3209 status = deferred_close_recv(subreq);
3210 TALLOC_FREE(subreq);
3211 DBG_DEBUG("close returned %s\n", nt_errstr(status));
3212 if (tevent_req_nterror(req, status)) {
3217 static void lock12_read(struct tevent_req *subreq)
3219 struct tevent_req *req = tevent_req_callback_data(
3220 subreq, struct tevent_req);
3221 struct lock12_state *state = tevent_req_data(
3222 req, struct lock12_state);
3223 NTSTATUS status, lock_status, read_status;
3224 uint8_t *buf = NULL;
3226 status = lockread_recv(
3227 subreq, &lock_status, &read_status, state, &buf);
3228 TALLOC_FREE(subreq);
3229 if (tevent_req_nterror(req, status) ||
3230 tevent_req_nterror(req, lock_status) ||
3231 tevent_req_nterror(req, read_status)) {
3234 tevent_req_done(req);
3237 static NTSTATUS lock12_recv(struct tevent_req *req)
3242 if (tevent_req_is_nterror(req, &status)) {
3245 return NT_STATUS_OK;
3248 static bool run_locktest12(int dummy)
3250 struct tevent_context *ev = NULL;
3251 struct tevent_req *req = NULL;
3252 struct cli_state *cli = NULL;
3253 const char fname[] = "\\lockt12.lck";
3254 uint16_t fnum1, fnum2;
3260 printf("starting locktest12\n");
3262 ev = samba_tevent_context_init(NULL);
3264 d_fprintf(stderr, "samba_tevent_context_init failed\n");
3268 ok = torture_open_connection(&cli, 0);
3272 smbXcli_conn_set_sockopt(cli->conn, sockops);
3274 status = cli_openx(cli, fname, O_CREAT|O_RDWR, DENY_NONE, &fnum1);
3275 if (!NT_STATUS_IS_OK(status)) {
3277 "cli_openx failed: %s\n",
3282 status = cli_openx(cli, fname, O_CREAT|O_RDWR, DENY_NONE, &fnum2);
3283 if (!NT_STATUS_IS_OK(status)) {
3285 "cli_openx failed: %s\n",
3290 status = cli_writeall(cli, fnum1, 0, &data, 0, sizeof(data), NULL);
3291 if (!NT_STATUS_IS_OK(status)) {
3293 "cli_writeall failed: %s\n",
3298 status = cli_locktype(
3299 cli, fnum1, 0, 1, 0, LOCKING_ANDX_EXCLUSIVE_LOCK);
3300 if (!NT_STATUS_IS_OK(status)) {
3302 "cli_locktype failed: %s\n",
3307 req = lock12_send(ev, ev, cli, fnum1, fnum2);
3309 d_fprintf(stderr, "lock12_send failed\n");
3313 ok = tevent_req_poll_ntstatus(req, ev, &status);
3315 d_fprintf(stderr, "tevent_req_poll_ntstatus failed\n");
3319 if (!NT_STATUS_IS_OK(status)) {
3321 "tevent_req_poll_ntstatus returned %s\n",
3326 status = lock12_recv(req);
3327 if (!NT_STATUS_IS_OK(status)) {
3328 d_fprintf(stderr, "lock12 returned %s\n", nt_errstr(status));
3335 torture_close_connection(cli);
3340 struct lock_ntcancel_state {
3341 struct timeval start;
3342 struct smb1_lock_element lck;
3343 struct tevent_req *subreq;
3346 static void lock_ntcancel_waited(struct tevent_req *subreq);
3347 static void lock_ntcancel_done(struct tevent_req *subreq);
3349 static struct tevent_req *lock_ntcancel_send(
3350 TALLOC_CTX *mem_ctx,
3351 struct tevent_context *ev,
3352 struct cli_state *cli,
3355 struct tevent_req *req = NULL, *subreq = NULL;
3356 struct lock_ntcancel_state *state = NULL;
3358 req = tevent_req_create(mem_ctx, &state, struct lock_ntcancel_state);
3362 state->lck = (struct smb1_lock_element) {
3363 .pid = cli_getpid(cli), .offset = 0, .length = 1,
3365 state->start = timeval_current();
3367 state->subreq = cli_lockingx_send(
3368 state, /* mem_ctx */
3369 ev, /* tevent_context */
3372 LOCKING_ANDX_EXCLUSIVE_LOCK, /* typeoflock */
3373 0, /* newoplocklevel */
3374 10000, /* timeout */
3375 0, /* num_unlocks */
3378 &state->lck); /* locks */
3379 if (tevent_req_nomem(state->subreq, req)) {
3380 return tevent_req_post(req, ev);
3382 tevent_req_set_callback(state->subreq, lock_ntcancel_done, req);
3384 subreq = tevent_wakeup_send(state, ev, timeval_current_ofs(1, 0));
3385 if (tevent_req_nomem(subreq, req)) {
3386 return tevent_req_post(req, ev);
3388 tevent_req_set_callback(subreq, lock_ntcancel_waited, req);
3392 static void lock_ntcancel_waited(struct tevent_req *subreq)
3394 struct tevent_req *req = tevent_req_callback_data(
3395 subreq, struct tevent_req);
3396 struct lock_ntcancel_state *state = tevent_req_data(
3397 req, struct lock_ntcancel_state);
3400 ok = tevent_wakeup_recv(subreq);
3401 TALLOC_FREE(subreq);
3403 tevent_req_oom(req);
3407 ok = tevent_req_cancel(state->subreq);
3409 d_fprintf(stderr, "Could not cancel subreq\n");
3410 tevent_req_oom(req);
3415 static void lock_ntcancel_done(struct tevent_req *subreq)
3417 struct tevent_req *req = tevent_req_callback_data(
3418 subreq, struct tevent_req);
3419 struct lock_ntcancel_state *state = tevent_req_data(
3420 req, struct lock_ntcancel_state);
3424 status = cli_lockingx_recv(subreq);
3425 TALLOC_FREE(subreq);
3427 if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
3428 d_printf("cli_lockingx returned %s\n", nt_errstr(status));
3429 tevent_req_nterror(req, NT_STATUS_UNSUCCESSFUL);
3433 elapsed = timeval_elapsed(&state->start);
3436 d_printf("cli_lockingx was too slow, cancel did not work\n");
3437 tevent_req_nterror(req, NT_STATUS_UNSUCCESSFUL);
3441 tevent_req_done(req);
3444 static NTSTATUS lock_ntcancel_recv(struct tevent_req *req)
3446 return tevent_req_simple_recv_ntstatus(req);
3449 static bool run_locktest13(int dummy)
3451 struct tevent_context *ev = NULL;
3452 struct tevent_req *req = NULL;
3453 struct cli_state *cli = NULL;
3454 const char fname[] = "\\lockt13.lck";
3455 uint16_t fnum1, fnum2;
3461 printf("starting locktest13\n");
3463 ev = samba_tevent_context_init(NULL);
3465 d_fprintf(stderr, "samba_tevent_context_init failed\n");
3469 ok = torture_open_connection(&cli, 0);
3473 smbXcli_conn_set_sockopt(cli->conn, sockops);
3475 status = cli_openx(cli, fname, O_CREAT|O_RDWR, DENY_NONE, &fnum1);
3476 if (!NT_STATUS_IS_OK(status)) {
3478 "cli_openx failed: %s\n",
3483 status = cli_openx(cli, fname, O_CREAT|O_RDWR, DENY_NONE, &fnum2);
3484 if (!NT_STATUS_IS_OK(status)) {
3486 "cli_openx failed: %s\n",
3491 status = cli_writeall(cli, fnum1, 0, &data, 0, sizeof(data), NULL);
3492 if (!NT_STATUS_IS_OK(status)) {
3494 "cli_writeall failed: %s\n",
3499 status = cli_locktype(
3500 cli, fnum1, 0, 1, 0, LOCKING_ANDX_EXCLUSIVE_LOCK);
3501 if (!NT_STATUS_IS_OK(status)) {
3503 "cli_locktype failed: %s\n",
3508 req = lock_ntcancel_send(ev, ev, cli, fnum2);
3510 d_fprintf(stderr, "lock_ntcancel_send failed\n");
3514 ok = tevent_req_poll_ntstatus(req, ev, &status);
3516 d_fprintf(stderr, "tevent_req_poll_ntstatus failed\n");
3520 if (!NT_STATUS_IS_OK(status)) {
3522 "tevent_req_poll_ntstatus returned %s\n",
3527 status = lock_ntcancel_recv(req);
3528 if (!NT_STATUS_IS_OK(status)) {
3530 "lock_ntcancel returned %s\n",
3538 torture_close_connection(cli);
3544 test whether fnums and tids open on one VC are available on another (a major
3547 static bool run_fdpasstest(int dummy)
3549 struct cli_state *cli1, *cli2;
3550 const char *fname = "\\fdpass.tst";
3555 if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
3558 smbXcli_conn_set_sockopt(cli1->conn, sockops);
3559 smbXcli_conn_set_sockopt(cli2->conn, sockops);
3561 printf("starting fdpasstest\n");
3563 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3565 status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
3567 if (!NT_STATUS_IS_OK(status)) {
3568 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
3572 status = cli_writeall(cli1, fnum1, 0, (const uint8_t *)"hello world\n", 0,
3574 if (!NT_STATUS_IS_OK(status)) {
3575 printf("write failed (%s)\n", nt_errstr(status));
3579 cli_state_set_uid(cli2, cli_state_get_uid(cli1));
3580 cli_state_set_tid(cli2, cli_state_get_tid(cli1));
3581 cli_setpid(cli2, cli_getpid(cli1));
3583 if (test_cli_read(cli2, fnum1, buf, 0, 13, NULL, 13)) {
3584 printf("read succeeded! nasty security hole [%s]\n", buf);
3588 cli_close(cli1, fnum1);
3589 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3591 torture_close_connection(cli1);
3592 torture_close_connection(cli2);
3594 printf("finished fdpasstest\n");
3598 static bool run_fdsesstest(int dummy)
3600 struct cli_state *cli;
3602 uint16_t saved_vuid;
3604 uint32_t saved_cnum;
3605 const char *fname = "\\fdsess.tst";
3606 const char *fname1 = "\\fdsess1.tst";
3613 if (!torture_open_connection(&cli, 0))
3615 smbXcli_conn_set_sockopt(cli->conn, sockops);
3617 if (!torture_cli_session_setup2(cli, &new_vuid))
3620 saved_cnum = cli_state_get_tid(cli);
3621 if (!NT_STATUS_IS_OK(cli_tree_connect(cli, share, "?????", NULL)))
3623 new_cnum = cli_state_get_tid(cli);
3624 cli_state_set_tid(cli, saved_cnum);
3626 printf("starting fdsesstest\n");
3628 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3629 cli_unlink(cli, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3631 status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
3632 if (!NT_STATUS_IS_OK(status)) {
3633 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
3637 status = cli_writeall(cli, fnum1, 0, (const uint8_t *)"hello world\n", 0, 13,
3639 if (!NT_STATUS_IS_OK(status)) {
3640 printf("write failed (%s)\n", nt_errstr(status));
3644 saved_vuid = cli_state_get_uid(cli);
3645 cli_state_set_uid(cli, new_vuid);
3647 if (test_cli_read(cli, fnum1, buf, 0, 13, NULL, 13)) {
3648 printf("read succeeded with different vuid! "
3649 "nasty security hole [%s]\n", buf);
3652 /* Try to open a file with different vuid, samba cnum. */
3653 if (NT_STATUS_IS_OK(cli_openx(cli, fname1, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum2))) {
3654 printf("create with different vuid, same cnum succeeded.\n");
3655 cli_close(cli, fnum2);
3656 cli_unlink(cli, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3658 printf("create with different vuid, same cnum failed.\n");
3659 printf("This will cause problems with service clients.\n");
3663 cli_state_set_uid(cli, saved_vuid);
3665 /* Try with same vuid, different cnum. */
3666 cli_state_set_tid(cli, new_cnum);
3668 if (test_cli_read(cli, fnum1, buf, 0, 13, NULL, 13)) {
3669 printf("read succeeded with different cnum![%s]\n", buf);
3673 cli_state_set_tid(cli, saved_cnum);
3674 cli_close(cli, fnum1);
3675 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3677 torture_close_connection(cli);
3679 printf("finished fdsesstest\n");
3684 This test checks that
3686 1) the server does not allow an unlink on a file that is open
3688 static bool run_unlinktest(int dummy)
3690 struct cli_state *cli;
3691 const char *fname = "\\unlink.tst";
3693 bool correct = True;
3696 if (!torture_open_connection(&cli, 0)) {
3700 smbXcli_conn_set_sockopt(cli->conn, sockops);
3702 printf("starting unlink test\n");
3704 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3708 status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
3709 if (!NT_STATUS_IS_OK(status)) {
3710 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
3714 status = cli_unlink(cli, fname,
3715 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3716 if (NT_STATUS_IS_OK(status)) {
3717 printf("error: server allowed unlink on an open file\n");
3720 correct = check_error(__LINE__, status, ERRDOS, ERRbadshare,
3721 NT_STATUS_SHARING_VIOLATION);
3724 cli_close(cli, fnum);
3725 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3727 if (!torture_close_connection(cli)) {
3731 printf("unlink test finished\n");
3738 test how many open files this server supports on the one socket
3740 static bool run_maxfidtest(int dummy)
3742 struct cli_state *cli;
3744 uint16_t fnums[0x11000];
3747 bool correct = True;
3753 printf("failed to connect\n");
3757 smbXcli_conn_set_sockopt(cli->conn, sockops);
3759 for (i=0; i<0x11000; i++) {
3760 slprintf(fname,sizeof(fname)-1,"\\maxfid.%d.%d", i,(int)getpid());
3761 status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_TRUNC, DENY_NONE,
3763 if (!NT_STATUS_IS_OK(status)) {
3764 printf("open of %s failed (%s)\n",
3765 fname, nt_errstr(status));
3766 printf("maximum fnum is %d\n", i);
3774 printf("cleaning up\n");
3776 slprintf(fname,sizeof(fname)-1,"\\maxfid.%d.%d", i,(int)getpid());
3777 cli_close(cli, fnums[i]);
3779 status = cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3780 if (!NT_STATUS_IS_OK(status)) {
3781 printf("unlink of %s failed (%s)\n",
3782 fname, nt_errstr(status));
3789 printf("maxfid test finished\n");
3790 if (!torture_close_connection(cli)) {
3796 /* generate a random buffer */
3797 static void rand_buf(char *buf, int len)
3800 *buf = (char)sys_random();
3805 /* send smb negprot commands, not reading the response */
3806 static bool run_negprot_nowait(int dummy)
3808 struct tevent_context *ev;
3810 struct cli_state *cli;
3811 bool correct = True;
3813 printf("starting negprot nowait test\n");
3815 ev = samba_tevent_context_init(talloc_tos());
3820 if (!(cli = open_nbt_connection())) {
3825 for (i=0;i<50000;i++) {
3826 struct tevent_req *req;
3828 req = smbXcli_negprot_send(ev, ev, cli->conn, cli->timeout,
3829 PROTOCOL_CORE, PROTOCOL_NT1, 0);
3834 if (!tevent_req_poll(req, ev)) {
3835 d_fprintf(stderr, "tevent_req_poll failed: %s\n",
3843 if (torture_close_connection(cli)) {
3847 printf("finished negprot nowait test\n");
3852 /* send smb negprot commands, not reading the response */
3853 static bool run_bad_nbt_session(int dummy)
3855 struct nmb_name called, calling;
3856 struct sockaddr_storage ss;
3861 printf("starting bad nbt session test\n");
3863 make_nmb_name(&calling, myname, 0x0);
3864 make_nmb_name(&called , host, 0x20);
3866 if (!resolve_name(host, &ss, 0x20, true)) {
3867 d_fprintf(stderr, "Could not resolve name %s\n", host);
3871 status = open_socket_out(&ss, NBT_SMB_PORT, 10000, &fd);
3872 if (!NT_STATUS_IS_OK(status)) {
3873 d_fprintf(stderr, "open_socket_out failed: %s\n",
3878 ret = cli_bad_session_request(fd, &calling, &called);
3881 d_fprintf(stderr, "open_socket_out failed: %s\n",
3886 printf("finished bad nbt session test\n");
3890 /* send random IPC commands */
3891 static bool run_randomipc(int dummy)
3893 char *rparam = NULL;
3895 unsigned int rdrcnt,rprcnt;
3897 int api, param_len, i;
3898 struct cli_state *cli;
3899 bool correct = True;
3902 printf("starting random ipc test\n");
3904 if (!torture_open_connection(&cli, 0)) {
3908 for (i=0;i<count;i++) {
3909 api = sys_random() % 500;
3910 param_len = (sys_random() % 64);
3912 rand_buf(param, param_len);
3917 param, param_len, 8,
3918 NULL, 0, CLI_BUFFER_SIZE,
3922 printf("%d/%d\r", i,count);
3925 printf("%d/%d\n", i, count);
3927 if (!torture_close_connection(cli)) {
3934 printf("finished random ipc test\n");
3941 static void browse_callback(const char *sname, uint32_t stype,
3942 const char *comment, void *state)
3944 printf("\t%20.20s %08x %s\n", sname, stype, comment);
3950 This test checks the browse list code
3953 static bool run_browsetest(int dummy)
3955 static struct cli_state *cli;
3956 bool correct = True;
3958 printf("starting browse test\n");
3960 if (!torture_open_connection(&cli, 0)) {
3964 printf("domain list:\n");
3965 cli_NetServerEnum(cli, cli->server_domain,
3966 SV_TYPE_DOMAIN_ENUM,
3967 browse_callback, NULL);
3969 printf("machine list:\n");
3970 cli_NetServerEnum(cli, cli->server_domain,
3972 browse_callback, NULL);
3974 if (!torture_close_connection(cli)) {
3978 printf("browse test finished\n");
3984 static bool check_attributes(struct cli_state *cli,
3986 uint32_t expected_attrs)
3989 NTSTATUS status = cli_getatr(cli,
3994 if (!NT_STATUS_IS_OK(status)) {
3995 printf("cli_getatr failed with %s\n",
3999 if (attrs != expected_attrs) {
4000 printf("Attributes incorrect 0x%x, should be 0x%x\n",
4001 (unsigned int)attrs,
4002 (unsigned int)expected_attrs);
4009 This checks how the getatr calls works
4011 static bool run_attrtest(int dummy)
4013 struct cli_state *cli;
4016 const char *fname = "\\attrib123456789.tst";
4017 bool correct = True;
4020 printf("starting attrib test\n");
4022 if (!torture_open_connection(&cli, 0)) {
4026 /* Ensure we can't unlink with out-of-range (unknown) attribute. */
4027 status = cli_unlink(cli, fname, 0x20000);
4028 if (!NT_STATUS_EQUAL(status, NT_STATUS_INVALID_PARAMETER)) {
4033 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4034 cli_openx(cli, fname,
4035 O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum);
4036 cli_close(cli, fnum);
4038 status = cli_getatr(cli, fname, NULL, NULL, &t);
4039 if (!NT_STATUS_IS_OK(status)) {
4040 printf("getatr failed (%s)\n", nt_errstr(status));
4044 if (labs(t - time(NULL)) > 60*60*24*10) {
4045 printf("ERROR: SMBgetatr bug. time is %s",
4051 t2 = t-60*60*24; /* 1 day ago */
4053 /* Ensure we can't set with out-of-range (unknown) attribute. */
4054 status = cli_setatr(cli, fname, 0x20000, t2);
4055 if (!NT_STATUS_EQUAL(status, NT_STATUS_INVALID_PARAMETER)) {
4060 status = cli_setatr(cli, fname, 0, t2);
4061 if (!NT_STATUS_IS_OK(status)) {
4062 printf("setatr failed (%s)\n", nt_errstr(status));
4066 status = cli_getatr(cli, fname, NULL, NULL, &t);
4067 if (!NT_STATUS_IS_OK(status)) {
4068 printf("getatr failed (%s)\n", nt_errstr(status));
4073 printf("ERROR: getatr/setatr bug. times are\n%s",
4075 printf("%s", ctime(&t2));
4079 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4081 /* Check cli_setpathinfo_ext() */
4082 /* Re-create the file. */
4083 status = cli_openx(cli, fname,
4084 O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum);
4085 if (!NT_STATUS_IS_OK(status)) {
4086 printf("Failed to recreate %s (%s)\n",
4087 fname, nt_errstr(status));
4090 cli_close(cli, fnum);
4092 status = cli_setpathinfo_ext(
4095 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* create */
4096 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* access */
4097 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* write */
4098 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* change */
4099 FILE_ATTRIBUTE_SYSTEM |
4100 FILE_ATTRIBUTE_HIDDEN |
4101 FILE_ATTRIBUTE_READONLY);
4102 if (!NT_STATUS_IS_OK(status)) {
4103 printf("cli_setpathinfo_ext failed with %s\n",
4108 /* Check attributes are correct. */
4109 correct = check_attributes(cli,
4111 FILE_ATTRIBUTE_SYSTEM |
4112 FILE_ATTRIBUTE_HIDDEN |
4113 FILE_ATTRIBUTE_READONLY);
4114 if (correct == false) {
4118 /* Setting to FILE_ATTRIBUTE_NORMAL should be ignored. */
4119 status = cli_setpathinfo_ext(
4122 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* create */
4123 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* access */
4124 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* write */
4125 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* change */
4126 FILE_ATTRIBUTE_NORMAL);
4127 if (!NT_STATUS_IS_OK(status)) {
4128 printf("cli_setpathinfo_ext failed with %s\n",
4133 /* Check attributes are correct. */
4134 correct = check_attributes(cli,
4136 FILE_ATTRIBUTE_SYSTEM |
4137 FILE_ATTRIBUTE_HIDDEN |
4138 FILE_ATTRIBUTE_READONLY);
4139 if (correct == false) {
4143 /* Setting to (uint16_t)-1 should also be ignored. */
4144 status = cli_setpathinfo_ext(
4147 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* create */
4148 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* access */
4149 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* write */
4150 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* change */
4152 if (!NT_STATUS_IS_OK(status)) {
4153 printf("cli_setpathinfo_ext failed with %s\n",
4158 /* Check attributes are correct. */
4159 correct = check_attributes(cli,
4161 FILE_ATTRIBUTE_SYSTEM |
4162 FILE_ATTRIBUTE_HIDDEN |
4163 FILE_ATTRIBUTE_READONLY);
4164 if (correct == false) {
4168 /* Setting to 0 should clear them all. */
4169 status = cli_setpathinfo_ext(
4172 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* create */
4173 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* access */
4174 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* write */
4175 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* change */
4177 if (!NT_STATUS_IS_OK(status)) {
4178 printf("cli_setpathinfo_ext failed with %s\n",
4183 /* Check attributes are correct. */
4184 correct = check_attributes(cli,
4186 FILE_ATTRIBUTE_NORMAL);
4187 if (correct == false) {
4195 FILE_ATTRIBUTE_SYSTEM |
4196 FILE_ATTRIBUTE_HIDDEN|
4197 FILE_ATTRIBUTE_READONLY);
4199 if (!torture_close_connection(cli)) {
4203 printf("attrib test finished\n");
4210 This checks a couple of trans2 calls
4212 static bool run_trans2test(int dummy)
4214 struct cli_state *cli;
4217 time_t c_time, a_time, m_time;
4218 struct timespec c_time_ts, a_time_ts, m_time_ts, w_time_ts, m_time2_ts;
4219 const char *fname = "\\trans2.tst";
4220 const char *dname = "\\trans2";
4221 const char *fname2 = "\\trans2\\trans2.tst";
4223 bool correct = True;
4228 printf("starting trans2 test\n");
4230 if (!torture_open_connection(&cli, 0)) {
4234 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
4235 /* Ensure ino is zero, SMB2 gets a real one. */
4238 /* Ensure ino is -1, SMB1 never gets a real one. */
4242 status = cli_get_fs_attr_info(cli, &fs_attr);
4243 if (!NT_STATUS_IS_OK(status)) {
4244 printf("ERROR: cli_get_fs_attr_info returned %s\n",
4249 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4250 cli_openx(cli, fname, O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum);
4251 status = cli_qfileinfo_basic(cli, fnum, NULL, &size, &c_time_ts,
4252 &a_time_ts, &w_time_ts, &m_time_ts, NULL);
4253 if (!NT_STATUS_IS_OK(status)) {
4254 printf("ERROR: qfileinfo failed (%s)\n", nt_errstr(status));
4258 status = cli_qfilename(cli, fnum, talloc_tos(), &pname);
4259 if (!NT_STATUS_IS_OK(status)) {
4260 printf("ERROR: qfilename failed (%s)\n", nt_errstr(status));
4263 else if (strcmp(pname, fname)) {
4264 printf("qfilename gave different name? [%s] [%s]\n",
4269 cli_close(cli, fnum);
4273 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4274 status = cli_openx(cli, fname, O_RDWR | O_CREAT | O_TRUNC, DENY_NONE,
4276 if (!NT_STATUS_IS_OK(status)) {
4277 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
4280 cli_close(cli, fnum);
4282 status = cli_qpathinfo1(cli, fname, &c_time, &a_time, &m_time, &size,
4284 if (!NT_STATUS_IS_OK(status)) {
4285 printf("ERROR: qpathinfo failed (%s)\n", nt_errstr(status));
4288 time_t t = time(NULL);
4290 if (c_time != m_time) {
4291 printf("create time=%s", ctime(&c_time));
4292 printf("modify time=%s", ctime(&m_time));
4293 printf("This system appears to have sticky create times\n");
4295 if ((labs(a_time - t) > 60) && (a_time % (60*60) == 0)) {
4296 printf("access time=%s", ctime(&a_time));
4297 printf("This system appears to set a midnight access time\n");
4301 if (labs(m_time - t) > 60*60*24*7) {
4302 printf("ERROR: totally incorrect times - maybe word reversed? mtime=%s", ctime(&m_time));
4308 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4309 cli_openx(cli, fname,
4310 O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum);
4311 cli_close(cli, fnum);
4312 status = cli_qpathinfo2(cli, fname, &c_time_ts, &a_time_ts, &w_time_ts,
4313 &m_time_ts, &size, NULL, &ino);
4314 if (!NT_STATUS_IS_OK(status)) {
4315 printf("ERROR: qpathinfo2 failed (%s)\n", nt_errstr(status));
4318 if (w_time_ts.tv_sec < 60*60*24*2) {
4319 printf("write time=%s", ctime(&w_time_ts.tv_sec));
4320 printf("This system appears to set a initial 0 write time\n");
4323 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
4324 /* SMB2 should always return an inode. */
4326 printf("SMB2 bad inode (0)\n");
4330 /* SMB1 must always return zero here. */
4332 printf("SMB1 bad inode (!0)\n");
4338 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4341 /* check if the server updates the directory modification time
4342 when creating a new file */
4343 status = cli_mkdir(cli, dname);
4344 if (!NT_STATUS_IS_OK(status)) {
4345 printf("ERROR: mkdir failed (%s)\n", nt_errstr(status));
4349 status = cli_qpathinfo2(cli, "\\trans2\\", &c_time_ts, &a_time_ts,
4350 &w_time_ts, &m_time_ts, &size, NULL, NULL);
4351 if (!NT_STATUS_IS_OK(status)) {
4352 printf("ERROR: qpathinfo2 failed (%s)\n", nt_errstr(status));
4356 cli_openx(cli, fname2,
4357 O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum);
4358 cli_writeall(cli, fnum, 0, (uint8_t *)&fnum, 0, sizeof(fnum), NULL);
4359 cli_close(cli, fnum);
4360 status = cli_qpathinfo2(cli, "\\trans2\\", &c_time_ts, &a_time_ts,
4361 &w_time_ts, &m_time2_ts, &size, NULL, NULL);
4362 if (!NT_STATUS_IS_OK(status)) {
4363 printf("ERROR: qpathinfo2 failed (%s)\n", nt_errstr(status));
4366 if (memcmp(&m_time_ts, &m_time2_ts, sizeof(struct timespec))
4368 printf("This system does not update directory modification times\n");
4372 cli_unlink(cli, fname2, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4373 cli_rmdir(cli, dname);
4375 if (!torture_close_connection(cli)) {
4379 printf("trans2 test finished\n");
4385 This checks new W2K calls.
4388 static NTSTATUS new_trans(struct cli_state *pcli, int fnum, int level)
4390 uint8_t *buf = NULL;
4394 status = cli_qfileinfo(talloc_tos(), pcli, fnum, level, 0,
4395 CLI_BUFFER_SIZE, NULL, &buf, &len);
4396 if (!NT_STATUS_IS_OK(status)) {
4397 printf("ERROR: qfileinfo (%d) failed (%s)\n", level,
4400 printf("qfileinfo: level %d, len = %u\n", level, len);
4401 dump_data(0, (uint8_t *)buf, len);
4408 static bool run_w2ktest(int dummy)
4410 struct cli_state *cli;
4412 const char *fname = "\\w2ktest\\w2k.tst";
4414 bool correct = True;
4416 printf("starting w2k test\n");
4418 if (!torture_open_connection(&cli, 0)) {
4422 cli_openx(cli, fname,
4423 O_RDWR | O_CREAT , DENY_NONE, &fnum);
4425 for (level = 1004; level < 1040; level++) {
4426 new_trans(cli, fnum, level);
4429 cli_close(cli, fnum);
4431 if (!torture_close_connection(cli)) {
4435 printf("w2k test finished\n");
4442 this is a harness for some oplock tests
4444 static bool run_oplock1(int dummy)
4446 struct cli_state *cli1;
4447 const char *fname = "\\lockt1.lck";
4449 bool correct = True;
4452 printf("starting oplock test 1\n");
4454 if (!torture_open_connection(&cli1, 0)) {
4458 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4460 smbXcli_conn_set_sockopt(cli1->conn, sockops);
4462 cli1->use_oplocks = True;
4464 status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
4466 if (!NT_STATUS_IS_OK(status)) {
4467 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
4471 cli1->use_oplocks = False;
4473 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4474 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4476 status = cli_close(cli1, fnum1);
4477 if (!NT_STATUS_IS_OK(status)) {
4478 printf("close2 failed (%s)\n", nt_errstr(status));
4482 status = cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4483 if (!NT_STATUS_IS_OK(status)) {
4484 printf("unlink failed (%s)\n", nt_errstr(status));
4488 if (!torture_close_connection(cli1)) {
4492 printf("finished oplock test 1\n");
4497 static bool run_oplock2(int dummy)
4499 struct cli_state *cli1, *cli2;
4500 const char *fname = "\\lockt2.lck";
4501 uint16_t fnum1, fnum2;
4502 int saved_use_oplocks = use_oplocks;
4504 bool correct = True;
4505 volatile bool *shared_correct;
4509 shared_correct = (volatile bool *)anonymous_shared_allocate(sizeof(bool));
4510 *shared_correct = True;
4512 use_level_II_oplocks = True;
4515 printf("starting oplock test 2\n");
4517 if (!torture_open_connection(&cli1, 0)) {
4518 use_level_II_oplocks = False;
4519 use_oplocks = saved_use_oplocks;
4523 if (!torture_open_connection(&cli2, 1)) {
4524 use_level_II_oplocks = False;
4525 use_oplocks = saved_use_oplocks;
4529 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4531 smbXcli_conn_set_sockopt(cli1->conn, sockops);
4532 smbXcli_conn_set_sockopt(cli2->conn, sockops);
4534 status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
4536 if (!NT_STATUS_IS_OK(status)) {
4537 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
4541 /* Don't need the globals any more. */
4542 use_level_II_oplocks = False;
4543 use_oplocks = saved_use_oplocks;
4547 status = cli_openx(cli2, fname, O_RDWR, DENY_NONE, &fnum2);
4548 if (!NT_STATUS_IS_OK(status)) {
4549 printf("second open of %s failed (%s)\n", fname, nt_errstr(status));
4550 *shared_correct = False;
4556 status = cli_close(cli2, fnum2);
4557 if (!NT_STATUS_IS_OK(status)) {
4558 printf("close2 failed (%s)\n", nt_errstr(status));
4559 *shared_correct = False;
4567 /* Ensure cli1 processes the break. Empty file should always return 0
4569 status = cli_read(cli1, fnum1, buf, 0, 4, &nread);
4570 if (!NT_STATUS_IS_OK(status)) {
4571 printf("read on fnum1 failed (%s)\n", nt_errstr(status));
4573 } else if (nread != 0) {
4574 printf("read on empty fnum1 failed. recv %ld expected %d\n",
4575 (unsigned long)nread, 0);
4579 /* Should now be at level II. */
4580 /* Test if sending a write locks causes a break to none. */
4581 status = cli_lock32(cli1, fnum1, 0, 4, 0, READ_LOCK);
4582 if (!NT_STATUS_IS_OK(status)) {
4583 printf("lock failed (%s)\n", nt_errstr(status));
4587 cli_unlock(cli1, fnum1, 0, 4);
4591 status = cli_lock32(cli1, fnum1, 0, 4, 0, WRITE_LOCK);
4592 if (!NT_STATUS_IS_OK(status)) {
4593 printf("lock failed (%s)\n", nt_errstr(status));
4597 cli_unlock(cli1, fnum1, 0, 4);
4601 cli_read(cli1, fnum1, buf, 0, 4, NULL);
4603 status = cli_close(cli1, fnum1);
4604 if (!NT_STATUS_IS_OK(status)) {
4605 printf("close1 failed (%s)\n", nt_errstr(status));
4611 status = cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4612 if (!NT_STATUS_IS_OK(status)) {
4613 printf("unlink failed (%s)\n", nt_errstr(status));
4617 if (!torture_close_connection(cli1)) {
4621 if (!*shared_correct) {
4625 printf("finished oplock test 2\n");
4630 struct oplock4_state {
4631 struct tevent_context *ev;
4632 struct cli_state *cli;
4637 static void oplock4_got_break(struct tevent_req *req);
4638 static void oplock4_got_open(struct tevent_req *req);
4640 static bool run_oplock4(int dummy)
4642 struct tevent_context *ev;
4643 struct cli_state *cli1, *cli2;
4644 struct tevent_req *oplock_req, *open_req;
4645 const char *fname = "\\lockt4.lck";
4646 const char *fname_ln = "\\lockt4_ln.lck";
4647 uint16_t fnum1, fnum2;
4648 int saved_use_oplocks = use_oplocks;
4650 bool correct = true;
4654 struct oplock4_state *state;
4656 printf("starting oplock test 4\n");
4658 if (!torture_open_connection(&cli1, 0)) {
4659 use_level_II_oplocks = false;
4660 use_oplocks = saved_use_oplocks;
4664 if (!torture_open_connection(&cli2, 1)) {
4665 use_level_II_oplocks = false;
4666 use_oplocks = saved_use_oplocks;
4670 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4671 cli_unlink(cli1, fname_ln, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4673 smbXcli_conn_set_sockopt(cli1->conn, sockops);
4674 smbXcli_conn_set_sockopt(cli2->conn, sockops);
4676 /* Create the file. */
4677 status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
4679 if (!NT_STATUS_IS_OK(status)) {
4680 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
4684 status = cli_close(cli1, fnum1);
4685 if (!NT_STATUS_IS_OK(status)) {
4686 printf("close1 failed (%s)\n", nt_errstr(status));
4690 /* Now create a hardlink. */
4691 status = cli_hardlink(cli1, fname, fname_ln);
4692 if (!NT_STATUS_IS_OK(status)) {
4693 printf("nt hardlink failed (%s)\n", nt_errstr(status));
4697 /* Prove that opening hardlinks cause deny modes to conflict. */
4698 status = cli_openx(cli1, fname, O_RDWR, DENY_ALL, &fnum1);
4699 if (!NT_STATUS_IS_OK(status)) {
4700 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
4704 status = cli_openx(cli1, fname_ln, O_RDWR, DENY_NONE, &fnum2);
4705 if (NT_STATUS_IS_OK(status)) {
4706 printf("open of %s succeeded - should fail with sharing violation.\n",
4711 if (!NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
4712 printf("open of %s should fail with sharing violation. Got %s\n",
4713 fname_ln, nt_errstr(status));
4717 status = cli_close(cli1, fnum1);
4718 if (!NT_STATUS_IS_OK(status)) {
4719 printf("close1 failed (%s)\n", nt_errstr(status));
4723 cli1->use_oplocks = true;
4724 cli2->use_oplocks = true;
4726 status = cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
4727 if (!NT_STATUS_IS_OK(status)) {
4728 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
4732 ev = samba_tevent_context_init(talloc_tos());
4734 printf("tevent_context_init failed\n");
4738 state = talloc(ev, struct oplock4_state);
4739 if (state == NULL) {
4740 printf("talloc failed\n");
4745 state->got_break = &got_break;
4746 state->fnum2 = &fnum2;
4748 oplock_req = cli_smb_oplock_break_waiter_send(
4749 talloc_tos(), ev, cli1);
4750 if (oplock_req == NULL) {
4751 printf("cli_smb_oplock_break_waiter_send failed\n");
4754 tevent_req_set_callback(oplock_req, oplock4_got_break, state);
4756 open_req = cli_openx_send(
4757 talloc_tos(), ev, cli2, fname_ln, O_RDWR, DENY_NONE);
4758 if (open_req == NULL) {
4759 printf("cli_openx_send failed\n");
4762 tevent_req_set_callback(open_req, oplock4_got_open, state);
4767 while (!got_break || fnum2 == 0xffff) {
4769 ret = tevent_loop_once(ev);
4771 printf("tevent_loop_once failed: %s\n",
4777 status = cli_close(cli2, fnum2);
4778 if (!NT_STATUS_IS_OK(status)) {
4779 printf("close2 failed (%s)\n", nt_errstr(status));
4783 status = cli_close(cli1, fnum1);
4784 if (!NT_STATUS_IS_OK(status)) {
4785 printf("close1 failed (%s)\n", nt_errstr(status));
4789 status = cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4790 if (!NT_STATUS_IS_OK(status)) {
4791 printf("unlink failed (%s)\n", nt_errstr(status));
4795 status = cli_unlink(cli1, fname_ln, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4796 if (!NT_STATUS_IS_OK(status)) {
4797 printf("unlink failed (%s)\n", nt_errstr(status));
4801 if (!torture_close_connection(cli1)) {
4809 printf("finished oplock test 4\n");
4814 static void oplock4_got_break(struct tevent_req *req)
4816 struct oplock4_state *state = tevent_req_callback_data(
4817 req, struct oplock4_state);
4822 status = cli_smb_oplock_break_waiter_recv(req, &fnum, &level);
4824 if (!NT_STATUS_IS_OK(status)) {
4825 printf("cli_smb_oplock_break_waiter_recv returned %s\n",
4829 *state->got_break = true;
4831 req = cli_oplock_ack_send(state, state->ev, state->cli, fnum,
4834 printf("cli_oplock_ack_send failed\n");
4839 static void oplock4_got_open(struct tevent_req *req)
4841 struct oplock4_state *state = tevent_req_callback_data(
4842 req, struct oplock4_state);
4845 status = cli_openx_recv(req, state->fnum2);
4846 if (!NT_STATUS_IS_OK(status)) {
4847 printf("cli_openx_recv returned %s\n", nt_errstr(status));
4848 *state->fnum2 = 0xffff;
4852 #ifdef HAVE_KERNEL_OPLOCKS_LINUX
4854 struct oplock5_state {
4859 * Async open the file that has a kernel oplock, do an echo to get
4860 * that 100% across, close the file to signal to the child fd that the
4861 * oplock can be dropped, wait for the open reply.
4864 static void oplock5_opened(struct tevent_req *subreq);
4865 static void oplock5_pong(struct tevent_req *subreq);
4866 static void oplock5_timedout(struct tevent_req *subreq);
4868 static struct tevent_req *oplock5_send(
4869 TALLOC_CTX *mem_ctx,
4870 struct tevent_context *ev,
4871 struct cli_state *cli,
4875 struct tevent_req *req = NULL, *subreq = NULL;
4876 struct oplock5_state *state = NULL;
4877 static uint8_t data = 0;
4879 req = tevent_req_create(mem_ctx, &state, struct oplock5_state);
4883 state->pipe_down_fd = pipe_down_fd;
4885 subreq = cli_ntcreate_send(
4891 SEC_FILE_READ_DATA, /* DesiredAccess */
4892 FILE_ATTRIBUTE_NORMAL, /* FileAttributes */
4893 FILE_SHARE_WRITE|FILE_SHARE_READ, /* ShareAccess */
4894 FILE_OPEN, /* CreateDisposition */
4895 FILE_NON_DIRECTORY_FILE, /* CreateOptions */
4896 0, /* Impersonation */
4897 0); /* SecurityFlags */
4898 if (tevent_req_nomem(subreq, req)) {
4899 return tevent_req_post(req, ev);
4901 tevent_req_set_callback(subreq, oplock5_opened, req);
4903 subreq = cli_echo_send(
4908 (DATA_BLOB) { .data = &data, .length = sizeof(data) });
4909 if (tevent_req_nomem(subreq, req)) {
4910 return tevent_req_post(req, ev);
4912 tevent_req_set_callback(subreq, oplock5_pong, req);
4914 subreq = tevent_wakeup_send(state, ev, timeval_current_ofs(20, 0));
4915 if (tevent_req_nomem(subreq, req)) {
4916 return tevent_req_post(req, ev);
4918 tevent_req_set_callback(subreq, oplock5_timedout, req);
4923 static void oplock5_opened(struct tevent_req *subreq)
4925 struct tevent_req *req = tevent_req_callback_data(
4926 subreq, struct tevent_req);
4930 status = cli_ntcreate_recv(subreq, &fnum, NULL);
4931 TALLOC_FREE(subreq);
4932 if (tevent_req_nterror(req, status)) {
4935 tevent_req_done(req);
4938 static void oplock5_pong(struct tevent_req *subreq)
4940 struct tevent_req *req = tevent_req_callback_data(
4941 subreq, struct tevent_req);
4942 struct oplock5_state *state = tevent_req_data(
4943 req, struct oplock5_state);
4946 status = cli_echo_recv(subreq);
4947 TALLOC_FREE(subreq);
4948 if (tevent_req_nterror(req, status)) {
4952 close(state->pipe_down_fd);
4955 static void oplock5_timedout(struct tevent_req *subreq)
4957 struct tevent_req *req = tevent_req_callback_data(
4958 subreq, struct tevent_req);
4961 ok = tevent_wakeup_recv(subreq);
4962 TALLOC_FREE(subreq);
4964 tevent_req_oom(req);
4967 tevent_req_nterror(req, NT_STATUS_TIMEOUT);
4970 static NTSTATUS oplock5_recv(struct tevent_req *req)
4972 return tevent_req_simple_recv_ntstatus(req);
4975 static bool run_oplock5(int dummy)
4977 struct tevent_context *ev = NULL;
4978 struct tevent_req *req = NULL;
4979 struct cli_state *cli = NULL;
4980 const char *fname = "oplock5.txt";
4981 int pipe_down[2], pipe_up[2];
4988 printf("starting oplock5\n");
4990 if (local_path == NULL) {
4991 d_fprintf(stderr, "oplock5 must be given a local path via "
4992 "-l <localpath>\n");
4996 ret = pipe(pipe_down);
4998 d_fprintf(stderr, "pipe() failed: %s\n", strerror(errno));
5001 ret = pipe(pipe_up);
5003 d_fprintf(stderr, "pipe() failed: %s\n", strerror(errno));
5008 if (child_pid == -1) {
5009 d_fprintf(stderr, "fork() failed: %s\n", strerror(errno));
5013 if (child_pid == 0) {
5014 char *local_file = NULL;
5017 close(pipe_down[1]);
5020 local_file = talloc_asprintf(
5021 talloc_tos(), "%s/%s", local_path, fname);
5022 if (local_file == 0) {
5026 fd = open(local_file, O_RDWR|O_CREAT, 0644);
5029 "open(%s) in child failed: %s\n",
5036 signal(SIGIO, SIG_IGN);
5038 ret = fcntl(fd, F_SETLEASE, F_WRLCK);
5041 "SETLEASE in child failed: %s\n",
5048 ret = sys_write(pipe_up[1], &c, sizeof(c));
5051 "sys_write failed: %s\n",
5055 ret = sys_read(pipe_down[0], &c, sizeof(c));
5058 "sys_read failed: %s\n",
5066 close(pipe_down[0]);
5068 ret = sys_read(pipe_up[0], &c, sizeof(c));
5071 "sys_read failed: %s\n",
5076 d_fprintf(stderr, "got error code %"PRIu8"\n", c);
5080 ok = torture_open_connection(&cli, 0);
5082 d_fprintf(stderr, "torture_open_connection failed\n");
5086 ev = samba_tevent_context_init(talloc_tos());
5088 d_fprintf(stderr, "samba_tevent_context_init failed\n");
5092 req = oplock5_send(ev, ev, cli, fname, pipe_down[1]);
5094 d_fprintf(stderr, "oplock5_send failed\n");
5098 ok = tevent_req_poll_ntstatus(req, ev, &status);
5101 "tevent_req_poll_ntstatus failed: %s\n",
5106 status = oplock5_recv(req);
5108 if (!NT_STATUS_IS_OK(status)) {
5110 "oplock5 failed: %s\n",
5118 #endif /* HAVE_KERNEL_OPLOCKS_LINUX */
5121 Test delete on close semantics.
5123 static bool run_deletetest(int dummy)
5125 struct cli_state *cli1 = NULL;
5126 struct cli_state *cli2 = NULL;
5127 const char *fname = "\\delete.file";
5128 uint16_t fnum1 = (uint16_t)-1;
5129 uint16_t fnum2 = (uint16_t)-1;
5130 bool correct = false;
5133 printf("starting delete test\n");
5135 if (!torture_open_connection(&cli1, 0)) {
5139 smbXcli_conn_set_sockopt(cli1->conn, sockops);
5141 /* Test 1 - this should delete the file on close. */
5143 cli_setatr(cli1, fname, 0, 0);
5144 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5146 status = cli_ntcreate(cli1, fname, 0, GENERIC_ALL_ACCESS|DELETE_ACCESS,
5147 FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
5148 FILE_DELETE_ON_CLOSE, 0, &fnum1, NULL);
5149 if (!NT_STATUS_IS_OK(status)) {
5150 printf("[1] open of %s failed (%s)\n", fname, nt_errstr(status));
5154 status = cli_close(cli1, fnum1);
5155 if (!NT_STATUS_IS_OK(status)) {
5156 printf("[1] close failed (%s)\n", nt_errstr(status));
5160 status = cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
5161 if (NT_STATUS_IS_OK(status)) {
5162 printf("[1] open of %s succeeded (should fail)\n", fname);
5166 printf("first delete on close test succeeded.\n");
5168 /* Test 2 - this should delete the file on close. */
5170 cli_setatr(cli1, fname, 0, 0);
5171 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5173 status = cli_ntcreate(cli1, fname, 0, GENERIC_ALL_ACCESS,
5174 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
5175 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
5176 if (!NT_STATUS_IS_OK(status)) {
5177 printf("[2] open of %s failed (%s)\n", fname, nt_errstr(status));
5181 status = cli_nt_delete_on_close(cli1, fnum1, true);
5182 if (!NT_STATUS_IS_OK(status)) {
5183 printf("[2] setting delete_on_close failed (%s)\n", nt_errstr(status));
5187 status = cli_close(cli1, fnum1);
5188 if (!NT_STATUS_IS_OK(status)) {
5189 printf("[2] close failed (%s)\n", nt_errstr(status));
5193 status = cli_openx(cli1, fname, O_RDONLY, DENY_NONE, &fnum1);
5194 if (NT_STATUS_IS_OK(status)) {
5195 printf("[2] open of %s succeeded should have been deleted on close !\n", fname);
5196 status = cli_close(cli1, fnum1);
5197 if (!NT_STATUS_IS_OK(status)) {
5198 printf("[2] close failed (%s)\n", nt_errstr(status));
5200 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5204 printf("second delete on close test succeeded.\n");
5207 cli_setatr(cli1, fname, 0, 0);
5208 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5210 status = cli_ntcreate(cli1, fname, 0, GENERIC_ALL_ACCESS,
5211 FILE_ATTRIBUTE_NORMAL,
5212 FILE_SHARE_READ|FILE_SHARE_WRITE,
5213 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
5214 if (!NT_STATUS_IS_OK(status)) {
5215 printf("[3] open - 1 of %s failed (%s)\n", fname, nt_errstr(status));
5219 /* This should fail with a sharing violation - open for delete is only compatible
5220 with SHARE_DELETE. */
5222 status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
5223 FILE_ATTRIBUTE_NORMAL,
5224 FILE_SHARE_READ|FILE_SHARE_WRITE,
5225 FILE_OPEN, 0, 0, &fnum2, NULL);
5226 if (NT_STATUS_IS_OK(status)) {
5227 printf("[3] open - 2 of %s succeeded - should have failed.\n", fname);
5231 /* This should succeed. */
5232 status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
5233 FILE_ATTRIBUTE_NORMAL,
5234 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5235 FILE_OPEN, 0, 0, &fnum2, NULL);
5236 if (!NT_STATUS_IS_OK(status)) {
5237 printf("[3] open - 3 of %s failed (%s)\n", fname, nt_errstr(status));
5241 status = cli_nt_delete_on_close(cli1, fnum1, true);
5242 if (!NT_STATUS_IS_OK(status)) {
5243 printf("[3] setting delete_on_close failed (%s)\n", nt_errstr(status));
5247 status = cli_close(cli1, fnum1);
5248 if (!NT_STATUS_IS_OK(status)) {
5249 printf("[3] close 1 failed (%s)\n", nt_errstr(status));
5253 status = cli_close(cli1, fnum2);
5254 if (!NT_STATUS_IS_OK(status)) {
5255 printf("[3] close 2 failed (%s)\n", nt_errstr(status));
5259 /* This should fail - file should no longer be there. */
5261 status = cli_openx(cli1, fname, O_RDONLY, DENY_NONE, &fnum1);
5262 if (NT_STATUS_IS_OK(status)) {
5263 printf("[3] open of %s succeeded should have been deleted on close !\n", fname);
5264 status = cli_close(cli1, fnum1);
5265 if (!NT_STATUS_IS_OK(status)) {
5266 printf("[3] close failed (%s)\n", nt_errstr(status));
5268 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5272 printf("third delete on close test succeeded.\n");
5275 cli_setatr(cli1, fname, 0, 0);
5276 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5278 status = cli_ntcreate(cli1, fname, 0,
5279 FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
5280 FILE_ATTRIBUTE_NORMAL,
5281 FILE_SHARE_READ|FILE_SHARE_WRITE,
5282 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
5283 if (!NT_STATUS_IS_OK(status)) {
5284 printf("[4] open of %s failed (%s)\n", fname, nt_errstr(status));
5288 /* This should succeed. */
5289 status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
5290 FILE_ATTRIBUTE_NORMAL,
5291 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5292 FILE_OPEN, 0, 0, &fnum2, NULL);
5293 if (!NT_STATUS_IS_OK(status)) {
5294 printf("[4] open - 2 of %s failed (%s)\n", fname, nt_errstr(status));
5298 status = cli_close(cli1, fnum2);
5299 if (!NT_STATUS_IS_OK(status)) {
5300 printf("[4] close - 1 failed (%s)\n", nt_errstr(status));
5304 status = cli_nt_delete_on_close(cli1, fnum1, true);
5305 if (!NT_STATUS_IS_OK(status)) {
5306 printf("[4] setting delete_on_close failed (%s)\n", nt_errstr(status));
5310 /* This should fail - no more opens once delete on close set. */
5311 status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
5312 FILE_ATTRIBUTE_NORMAL,
5313 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5314 FILE_OPEN, 0, 0, &fnum2, NULL);
5315 if (NT_STATUS_IS_OK(status)) {
5316 printf("[4] open - 3 of %s succeeded ! Should have failed.\n", fname );
5320 status = cli_close(cli1, fnum1);
5321 if (!NT_STATUS_IS_OK(status)) {
5322 printf("[4] close - 2 failed (%s)\n", nt_errstr(status));
5326 printf("fourth delete on close test succeeded.\n");
5329 cli_setatr(cli1, fname, 0, 0);
5330 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5332 status = cli_openx(cli1, fname, O_RDWR|O_CREAT, DENY_NONE, &fnum1);
5333 if (!NT_STATUS_IS_OK(status)) {
5334 printf("[5] open of %s failed (%s)\n", fname, nt_errstr(status));
5338 /* This should fail - only allowed on NT opens with DELETE access. */
5340 status = cli_nt_delete_on_close(cli1, fnum1, true);
5341 if (NT_STATUS_IS_OK(status)) {
5342 printf("[5] setting delete_on_close on OpenX file succeeded - should fail !\n");
5346 status = cli_close(cli1, fnum1);
5347 if (!NT_STATUS_IS_OK(status)) {
5348 printf("[5] close failed (%s)\n", nt_errstr(status));
5352 printf("fifth delete on close test succeeded.\n");
5355 cli_setatr(cli1, fname, 0, 0);
5356 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5358 status = cli_ntcreate(cli1, fname, 0, FILE_READ_DATA|FILE_WRITE_DATA,
5359 FILE_ATTRIBUTE_NORMAL,
5360 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5361 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
5362 if (!NT_STATUS_IS_OK(status)) {
5363 printf("[6] open of %s failed (%s)\n", fname,
5368 /* This should fail - only allowed on NT opens with DELETE access. */
5370 status = cli_nt_delete_on_close(cli1, fnum1, true);
5371 if (NT_STATUS_IS_OK(status)) {
5372 printf("[6] setting delete_on_close on file with no delete access succeeded - should fail !\n");
5376 status = cli_close(cli1, fnum1);
5377 if (!NT_STATUS_IS_OK(status)) {
5378 printf("[6] close failed (%s)\n", nt_errstr(status));
5382 printf("sixth delete on close test succeeded.\n");
5385 cli_setatr(cli1, fname, 0, 0);
5386 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5388 status = cli_ntcreate(cli1, fname, 0,
5389 FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
5390 FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
5391 0, 0, &fnum1, NULL);
5392 if (!NT_STATUS_IS_OK(status)) {
5393 printf("[7] open of %s failed (%s)\n", fname, nt_errstr(status));
5397 status = cli_nt_delete_on_close(cli1, fnum1, true);
5398 if (!NT_STATUS_IS_OK(status)) {
5399 printf("[7] setting delete_on_close on file failed !\n");
5403 status = cli_nt_delete_on_close(cli1, fnum1, false);
5404 if (!NT_STATUS_IS_OK(status)) {
5405 printf("[7] unsetting delete_on_close on file failed !\n");
5409 status = cli_close(cli1, fnum1);
5410 if (!NT_STATUS_IS_OK(status)) {
5411 printf("[7] close - 1 failed (%s)\n", nt_errstr(status));
5415 /* This next open should succeed - we reset the flag. */
5416 status = cli_openx(cli1, fname, O_RDONLY, DENY_NONE, &fnum1);
5417 if (!NT_STATUS_IS_OK(status)) {
5418 printf("[7] open of %s failed (%s)\n", fname, nt_errstr(status));
5422 status = cli_close(cli1, fnum1);
5423 if (!NT_STATUS_IS_OK(status)) {
5424 printf("[7] close - 2 failed (%s)\n", nt_errstr(status));
5428 printf("seventh delete on close test succeeded.\n");
5431 cli_setatr(cli1, fname, 0, 0);
5432 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5434 if (!torture_open_connection(&cli2, 1)) {
5435 printf("[8] failed to open second connection.\n");
5439 smbXcli_conn_set_sockopt(cli1->conn, sockops);
5441 status = cli_ntcreate(cli1, fname, 0,
5442 FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
5443 FILE_ATTRIBUTE_NORMAL,
5444 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5445 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
5446 if (!NT_STATUS_IS_OK(status)) {
5447 printf("[8] open 1 of %s failed (%s)\n", fname, nt_errstr(status));
5451 status = cli_ntcreate(cli2, fname, 0,
5452 FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
5453 FILE_ATTRIBUTE_NORMAL,
5454 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5455 FILE_OPEN, 0, 0, &fnum2, NULL);
5456 if (!NT_STATUS_IS_OK(status)) {
5457 printf("[8] open 2 of %s failed (%s)\n", fname, nt_errstr(status));
5461 status = cli_nt_delete_on_close(cli1, fnum1, true);
5462 if (!NT_STATUS_IS_OK(status)) {
5463 printf("[8] setting delete_on_close on file failed !\n");
5467 status = cli_close(cli1, fnum1);
5468 if (!NT_STATUS_IS_OK(status)) {
5469 printf("[8] close - 1 failed (%s)\n", nt_errstr(status));
5473 status = cli_close(cli2, fnum2);
5474 if (!NT_STATUS_IS_OK(status)) {
5475 printf("[8] close - 2 failed (%s)\n", nt_errstr(status));
5479 /* This should fail.. */
5480 status = cli_openx(cli1, fname, O_RDONLY, DENY_NONE, &fnum1);
5481 if (NT_STATUS_IS_OK(status)) {
5482 printf("[8] open of %s succeeded should have been deleted on close !\n", fname);
5486 printf("eighth delete on close test succeeded.\n");
5490 /* This should fail - we need to set DELETE_ACCESS. */
5491 status = cli_ntcreate(cli1, fname, 0, FILE_READ_DATA|FILE_WRITE_DATA,
5492 FILE_ATTRIBUTE_NORMAL,
5495 FILE_DELETE_ON_CLOSE, 0, &fnum1, NULL);
5496 if (NT_STATUS_IS_OK(status)) {
5497 printf("[9] open of %s succeeded should have failed!\n", fname);
5501 printf("ninth delete on close test succeeded.\n");
5505 status = cli_ntcreate(cli1, fname, 0,
5506 FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
5507 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
5508 FILE_OVERWRITE_IF, FILE_DELETE_ON_CLOSE,
5510 if (!NT_STATUS_IS_OK(status)) {
5511 printf("[10] open of %s failed (%s)\n", fname, nt_errstr(status));
5515 /* This should delete the file. */
5516 status = cli_close(cli1, fnum1);
5517 if (!NT_STATUS_IS_OK(status)) {
5518 printf("[10] close failed (%s)\n", nt_errstr(status));
5522 /* This should fail.. */
5523 status = cli_openx(cli1, fname, O_RDONLY, DENY_NONE, &fnum1);
5524 if (NT_STATUS_IS_OK(status)) {
5525 printf("[10] open of %s succeeded should have been deleted on close !\n", fname);
5529 printf("tenth delete on close test succeeded.\n");
5533 cli_setatr(cli1, fname, 0, 0);
5534 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5536 /* Can we open a read-only file with delete access? */
5538 /* Create a readonly file. */
5539 status = cli_ntcreate(cli1, fname, 0, FILE_READ_DATA|FILE_WRITE_DATA,
5540 FILE_ATTRIBUTE_READONLY, FILE_SHARE_NONE,
5541 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
5542 if (!NT_STATUS_IS_OK(status)) {
5543 printf("[11] open of %s failed (%s)\n", fname, nt_errstr(status));
5547 status = cli_close(cli1, fnum1);
5548 if (!NT_STATUS_IS_OK(status)) {
5549 printf("[11] close failed (%s)\n", nt_errstr(status));
5553 /* Now try open for delete access. */
5554 status = cli_ntcreate(cli1, fname, 0,
5555 FILE_READ_ATTRIBUTES|DELETE_ACCESS,
5557 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5558 FILE_OPEN, 0, 0, &fnum1, NULL);
5559 if (!NT_STATUS_IS_OK(status)) {
5560 printf("[11] open of %s failed: %s\n", fname, nt_errstr(status));
5564 cli_close(cli1, fnum1);
5566 printf("eleventh delete on close test succeeded.\n");
5570 * like test 4 but with initial delete on close
5573 cli_setatr(cli1, fname, 0, 0);
5574 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5576 status = cli_ntcreate(cli1, fname, 0,
5577 FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
5578 FILE_ATTRIBUTE_NORMAL,
5579 FILE_SHARE_READ|FILE_SHARE_WRITE,
5581 FILE_DELETE_ON_CLOSE, 0, &fnum1, NULL);
5582 if (!NT_STATUS_IS_OK(status)) {
5583 printf("[12] open 1 of %s failed (%s)\n", fname, nt_errstr(status));
5587 status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
5588 FILE_ATTRIBUTE_NORMAL,
5589 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5590 FILE_OPEN, 0, 0, &fnum2, NULL);
5591 if (!NT_STATUS_IS_OK(status)) {
5592 printf("[12] open 2 of %s failed(%s).\n", fname, nt_errstr(status));
5596 status = cli_close(cli1, fnum2);
5597 if (!NT_STATUS_IS_OK(status)) {
5598 printf("[12] close 1 failed (%s)\n", nt_errstr(status));
5602 status = cli_nt_delete_on_close(cli1, fnum1, true);
5603 if (!NT_STATUS_IS_OK(status)) {
5604 printf("[12] setting delete_on_close failed (%s)\n", nt_errstr(status));
5608 /* This should fail - no more opens once delete on close set. */
5609 status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
5610 FILE_ATTRIBUTE_NORMAL,
5611 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5612 FILE_OPEN, 0, 0, &fnum2, NULL);
5613 if (NT_STATUS_IS_OK(status)) {
5614 printf("[12] open 3 of %s succeeded - should fail).\n", fname);
5618 status = cli_nt_delete_on_close(cli1, fnum1, false);
5619 if (!NT_STATUS_IS_OK(status)) {
5620 printf("[12] unsetting delete_on_close failed (%s)\n", nt_errstr(status));
5624 status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
5625 FILE_ATTRIBUTE_NORMAL,
5626 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5627 FILE_OPEN, 0, 0, &fnum2, NULL);
5628 if (!NT_STATUS_IS_OK(status)) {
5629 printf("[12] open 4 of %s failed (%s)\n", fname, nt_errstr(status));
5633 status = cli_close(cli1, fnum2);
5634 if (!NT_STATUS_IS_OK(status)) {
5635 printf("[12] close 2 failed (%s)\n", nt_errstr(status));
5639 status = cli_close(cli1, fnum1);
5640 if (!NT_STATUS_IS_OK(status)) {
5641 printf("[12] close 3 failed (%s)\n", nt_errstr(status));
5646 * setting delete on close on the handle does
5647 * not unset the initial delete on close...
5649 status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
5650 FILE_ATTRIBUTE_NORMAL,
5651 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5652 FILE_OPEN, 0, 0, &fnum2, NULL);
5653 if (NT_STATUS_IS_OK(status)) {
5654 printf("[12] open 5 of %s succeeded - should fail).\n", fname);
5656 } else if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
5657 printf("ntcreate returned %s, expected "
5658 "NT_STATUS_OBJECT_NAME_NOT_FOUND\n",
5663 printf("twelfth delete on close test succeeded.\n");
5666 printf("finished delete test\n");
5671 /* FIXME: This will crash if we aborted before cli2 got
5672 * intialized, because these functions don't handle
5673 * uninitialized connections. */
5675 if (fnum1 != (uint16_t)-1) cli_close(cli1, fnum1);
5676 if (fnum2 != (uint16_t)-1) cli_close(cli1, fnum2);
5677 cli_setatr(cli1, fname, 0, 0);
5678 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5680 if (cli1 && !torture_close_connection(cli1)) {
5683 if (cli2 && !torture_close_connection(cli2)) {
5689 struct delete_stream_state {
5693 static void delete_stream_unlinked(struct tevent_req *subreq);
5694 static void delete_stream_closed(struct tevent_req *subreq);
5696 static struct tevent_req *delete_stream_send(
5697 TALLOC_CTX *mem_ctx,
5698 struct tevent_context *ev,
5699 struct cli_state *cli,
5700 const char *base_fname,
5701 uint16_t stream_fnum)
5703 struct tevent_req *req = NULL, *subreq = NULL;
5704 struct delete_stream_state *state = NULL;
5706 req = tevent_req_create(
5707 mem_ctx, &state, struct delete_stream_state);
5712 subreq = cli_unlink_send(
5717 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5718 if (tevent_req_nomem(subreq, req)) {
5719 return tevent_req_post(req, ev);
5721 tevent_req_set_callback(subreq, delete_stream_unlinked, req);
5723 subreq = cli_close_send(state, ev, cli, stream_fnum);
5724 if (tevent_req_nomem(subreq, req)) {
5725 return tevent_req_post(req, ev);
5727 tevent_req_set_callback(subreq, delete_stream_closed, req);
5732 static void delete_stream_unlinked(struct tevent_req *subreq)
5734 struct tevent_req *req = tevent_req_callback_data(
5735 subreq, struct tevent_req);
5736 struct delete_stream_state *state = tevent_req_data(
5737 req, struct delete_stream_state);
5740 status = cli_unlink_recv(subreq);
5741 TALLOC_FREE(subreq);
5742 if (!NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
5743 printf("cli_unlink returned %s\n",
5745 tevent_req_nterror(req, NT_STATUS_UNSUCCESSFUL);
5748 if (!state->closed) {
5749 /* close reply should have come in first */
5750 printf("Not closed\n");
5751 tevent_req_nterror(req, NT_STATUS_UNSUCCESSFUL);
5754 tevent_req_done(req);
5757 static void delete_stream_closed(struct tevent_req *subreq)
5759 struct tevent_req *req = tevent_req_callback_data(
5760 subreq, struct tevent_req);
5761 struct delete_stream_state *state = tevent_req_data(
5762 req, struct delete_stream_state);
5765 status = cli_close_recv(subreq);
5766 TALLOC_FREE(subreq);
5767 if (tevent_req_nterror(req, status)) {
5770 /* also waiting for the unlink to come back */
5771 state->closed = true;
5774 static NTSTATUS delete_stream_recv(struct tevent_req *req)
5776 return tevent_req_simple_recv_ntstatus(req);
5779 static bool run_delete_stream(int dummy)
5781 struct tevent_context *ev = NULL;
5782 struct tevent_req *req = NULL;
5783 struct cli_state *cli = NULL;
5784 const char fname[] = "delete_stream";
5785 const char fname_stream[] = "delete_stream:Zone.Identifier:$DATA";
5786 uint16_t fnum1, fnum2;
5790 printf("Starting stream delete test\n");
5792 ok = torture_open_connection(&cli, 0);
5797 cli_setatr(cli, fname, 0, 0);
5798 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5800 /* Create the file. */
5801 status = cli_ntcreate(
5805 READ_CONTROL_ACCESS,
5807 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5813 if (!NT_STATUS_IS_OK(status)) {
5815 "cli_ntcreate of %s failed (%s)\n",
5820 status = cli_close(cli, fnum1);
5821 if (!NT_STATUS_IS_OK(status)) {
5823 "cli_close of %s failed (%s)\n",
5829 /* Now create the stream. */
5830 status = cli_ntcreate(
5836 FILE_SHARE_READ|FILE_SHARE_WRITE,
5843 if (!NT_STATUS_IS_OK(status)) {
5845 "cli_ntcreate of %s failed (%s)\n",
5851 /* open it a second time */
5853 status = cli_ntcreate(
5859 FILE_SHARE_READ|FILE_SHARE_WRITE,
5866 if (!NT_STATUS_IS_OK(status)) {
5868 "2nd cli_ntcreate of %s failed (%s)\n",
5874 ev = samba_tevent_context_init(talloc_tos());
5876 d_fprintf(stderr, "samba_tevent_context_init failed\n");
5880 req = delete_stream_send(ev, ev, cli, fname, fnum1);
5882 d_fprintf(stderr, "delete_stream_send failed\n");
5886 ok = tevent_req_poll_ntstatus(req, ev, &status);
5889 "tevent_req_poll_ntstatus failed: %s\n",
5894 status = delete_stream_recv(req);
5896 if (!NT_STATUS_IS_OK(status)) {
5898 "delete_stream failed: %s\n",
5903 status = cli_close(cli, fnum2);
5904 if (!NT_STATUS_IS_OK(status)) {
5906 "close failed: %s\n",
5911 status = cli_unlink(
5912 cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5913 if (!NT_STATUS_IS_OK(status)) {
5915 "unlink failed: %s\n",
5924 Exercise delete on close semantics - use on the PRINT1 share in torture
5927 static bool run_delete_print_test(int dummy)
5929 struct cli_state *cli1 = NULL;
5930 const char *fname = "print_delete.file";
5931 uint16_t fnum1 = (uint16_t)-1;
5932 bool correct = false;
5933 const char *buf = "print file data\n";
5936 printf("starting print delete test\n");
5938 if (!torture_open_connection(&cli1, 0)) {
5942 smbXcli_conn_set_sockopt(cli1->conn, sockops);
5944 status = cli_ntcreate(cli1, fname, 0, GENERIC_ALL_ACCESS|DELETE_ACCESS,
5945 FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
5946 0, 0, &fnum1, NULL);
5947 if (!NT_STATUS_IS_OK(status)) {
5948 printf("open of %s failed (%s)\n",
5954 status = cli_writeall(cli1,
5957 (const uint8_t *)buf,
5959 strlen(buf), /* size */
5961 if (!NT_STATUS_IS_OK(status)) {
5962 printf("writing print file data failed (%s)\n",
5967 status = cli_nt_delete_on_close(cli1, fnum1, true);
5968 if (!NT_STATUS_IS_OK(status)) {
5969 printf("setting delete_on_close failed (%s)\n",
5974 status = cli_close(cli1, fnum1);
5975 if (!NT_STATUS_IS_OK(status)) {
5976 printf("close failed (%s)\n", nt_errstr(status));
5980 printf("finished print delete test\n");
5986 if (fnum1 != (uint16_t)-1) {
5987 cli_close(cli1, fnum1);
5990 if (cli1 && !torture_close_connection(cli1)) {
5997 Test wildcard delete.
5999 static bool run_wild_deletetest(int dummy)
6001 struct cli_state *cli = NULL;
6002 const char *dname = "\\WTEST";
6003 const char *fname = "\\WTEST\\A";
6004 const char *wunlink_name = "\\WTEST\\*";
6005 uint16_t fnum1 = (uint16_t)-1;
6006 bool correct = false;
6009 printf("starting wildcard delete test\n");
6011 if (!torture_open_connection(&cli, 0)) {
6015 smbXcli_conn_set_sockopt(cli->conn, sockops);
6017 cli_unlink(cli, fname, 0);
6018 cli_rmdir(cli, dname);
6019 status = cli_mkdir(cli, dname);
6020 if (!NT_STATUS_IS_OK(status)) {
6021 printf("mkdir of %s failed %s!\n", dname, nt_errstr(status));
6024 status = cli_openx(cli, fname, O_CREAT|O_RDONLY, DENY_NONE, &fnum1);
6025 if (!NT_STATUS_IS_OK(status)) {
6026 printf("open of %s failed %s!\n", fname, nt_errstr(status));
6029 status = cli_close(cli, fnum1);
6033 * Note the unlink attribute-type of zero. This should
6034 * map into FILE_ATTRIBUTE_NORMAL at the server even
6035 * on a wildcard delete.
6038 status = cli_unlink(cli, wunlink_name, 0);
6039 if (!NT_STATUS_IS_OK(status)) {
6040 printf("unlink of %s failed %s!\n",
6041 wunlink_name, nt_errstr(status));
6045 printf("finished wildcard delete test\n");
6051 if (fnum1 != (uint16_t)-1) cli_close(cli, fnum1);
6052 cli_unlink(cli, fname, 0);
6053 cli_rmdir(cli, dname);
6055 if (cli && !torture_close_connection(cli)) {
6061 static bool run_deletetest_ln(int dummy)
6063 struct cli_state *cli;
6064 const char *fname = "\\delete1";
6065 const char *fname_ln = "\\delete1_ln";
6069 bool correct = true;
6072 printf("starting deletetest-ln\n");
6074 if (!torture_open_connection(&cli, 0)) {
6078 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6079 cli_unlink(cli, fname_ln, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6081 smbXcli_conn_set_sockopt(cli->conn, sockops);
6083 /* Create the file. */
6084 status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
6085 if (!NT_STATUS_IS_OK(status)) {
6086 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
6090 status = cli_close(cli, fnum);
6091 if (!NT_STATUS_IS_OK(status)) {
6092 printf("close1 failed (%s)\n", nt_errstr(status));
6096 /* Now create a hardlink. */
6097 status = cli_hardlink(cli, fname, fname_ln);
6098 if (!NT_STATUS_IS_OK(status)) {
6099 printf("nt hardlink failed (%s)\n", nt_errstr(status));
6103 /* Open the original file. */
6104 status = cli_ntcreate(cli, fname, 0, FILE_READ_DATA,
6105 FILE_ATTRIBUTE_NORMAL,
6106 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6107 FILE_OPEN_IF, 0, 0, &fnum, NULL);
6108 if (!NT_STATUS_IS_OK(status)) {
6109 printf("ntcreate of %s failed (%s)\n", fname, nt_errstr(status));
6113 /* Unlink the hard link path. */
6114 status = cli_ntcreate(cli, fname_ln, 0, DELETE_ACCESS,
6115 FILE_ATTRIBUTE_NORMAL,
6116 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6117 FILE_OPEN_IF, 0, 0, &fnum1, NULL);
6118 if (!NT_STATUS_IS_OK(status)) {
6119 printf("ntcreate of %s failed (%s)\n", fname_ln, nt_errstr(status));
6122 status = cli_nt_delete_on_close(cli, fnum1, true);
6123 if (!NT_STATUS_IS_OK(status)) {
6124 d_printf("(%s) failed to set delete_on_close %s: %s\n",
6125 __location__, fname_ln, nt_errstr(status));
6129 status = cli_close(cli, fnum1);
6130 if (!NT_STATUS_IS_OK(status)) {
6131 printf("close %s failed (%s)\n",
6132 fname_ln, nt_errstr(status));
6136 status = cli_close(cli, fnum);
6137 if (!NT_STATUS_IS_OK(status)) {
6138 printf("close %s failed (%s)\n",
6139 fname, nt_errstr(status));
6143 /* Ensure the original file is still there. */
6144 status = cli_getatr(cli, fname, NULL, NULL, &t);
6145 if (!NT_STATUS_IS_OK(status)) {
6146 printf("%s getatr on file %s failed (%s)\n",
6153 /* Ensure the link path is gone. */
6154 status = cli_getatr(cli, fname_ln, NULL, NULL, &t);
6155 if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
6156 printf("%s, getatr for file %s returned wrong error code %s "
6157 "- should have been deleted\n",
6159 fname_ln, nt_errstr(status));
6163 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6164 cli_unlink(cli, fname_ln, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6166 if (!torture_close_connection(cli)) {
6170 printf("finished deletetest-ln\n");
6176 print out server properties
6178 static bool run_properties(int dummy)
6180 struct cli_state *cli;
6181 bool correct = True;
6183 printf("starting properties test\n");
6187 if (!torture_open_connection(&cli, 0)) {
6191 smbXcli_conn_set_sockopt(cli->conn, sockops);
6193 d_printf("Capabilities 0x%08x\n", smb1cli_conn_capabilities(cli->conn));
6195 if (!torture_close_connection(cli)) {
6204 /* FIRST_DESIRED_ACCESS 0xf019f */
6205 #define FIRST_DESIRED_ACCESS FILE_READ_DATA|FILE_WRITE_DATA|FILE_APPEND_DATA|\
6206 FILE_READ_EA| /* 0xf */ \
6207 FILE_WRITE_EA|FILE_READ_ATTRIBUTES| /* 0x90 */ \
6208 FILE_WRITE_ATTRIBUTES| /* 0x100 */ \
6209 DELETE_ACCESS|READ_CONTROL_ACCESS|\
6210 WRITE_DAC_ACCESS|WRITE_OWNER_ACCESS /* 0xf0000 */
6211 /* SECOND_DESIRED_ACCESS 0xe0080 */
6212 #define SECOND_DESIRED_ACCESS FILE_READ_ATTRIBUTES| /* 0x80 */ \
6213 READ_CONTROL_ACCESS|WRITE_DAC_ACCESS|\
6214 WRITE_OWNER_ACCESS /* 0xe0000 */
6217 #define THIRD_DESIRED_ACCESS FILE_READ_ATTRIBUTES| /* 0x80 */ \
6218 READ_CONTROL_ACCESS|WRITE_DAC_ACCESS|\
6220 WRITE_OWNER_ACCESS /* */
6224 Test ntcreate calls made by xcopy
6226 static bool run_xcopy(int dummy)
6228 static struct cli_state *cli1;
6229 const char *fname = "\\test.txt";
6230 bool correct = True;
6231 uint16_t fnum1, fnum2;
6234 printf("starting xcopy test\n");
6236 if (!torture_open_connection(&cli1, 0)) {
6240 status = cli_ntcreate(cli1, fname, 0, FIRST_DESIRED_ACCESS,
6241 FILE_ATTRIBUTE_ARCHIVE, FILE_SHARE_NONE,
6242 FILE_OVERWRITE_IF, 0x4044, 0, &fnum1, NULL);
6243 if (!NT_STATUS_IS_OK(status)) {
6244 printf("First open failed - %s\n", nt_errstr(status));
6248 status = cli_ntcreate(cli1, fname, 0, SECOND_DESIRED_ACCESS, 0,
6249 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6250 FILE_OPEN, 0x200000, 0, &fnum2, NULL);
6251 if (!NT_STATUS_IS_OK(status)) {
6252 printf("second open failed - %s\n", nt_errstr(status));
6256 if (!torture_close_connection(cli1)) {
6264 Test rename on files open with share delete and no share delete.
6266 static bool run_rename(int dummy)
6268 static struct cli_state *cli1;
6269 const char *fname = "\\test.txt";
6270 const char *fname1 = "\\test1.txt";
6271 bool correct = True;
6276 printf("starting rename test\n");
6278 if (!torture_open_connection(&cli1, 0)) {
6282 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6283 cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6285 status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
6286 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ,
6287 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
6288 if (!NT_STATUS_IS_OK(status)) {
6289 printf("First open failed - %s\n", nt_errstr(status));
6293 status = cli_rename(cli1, fname, fname1, false);
6294 if (!NT_STATUS_IS_OK(status)) {
6295 printf("First rename failed (SHARE_READ) (this is correct) - %s\n", nt_errstr(status));
6297 printf("First rename succeeded (SHARE_READ) - this should have failed !\n");
6301 status = cli_close(cli1, fnum1);
6302 if (!NT_STATUS_IS_OK(status)) {
6303 printf("close - 1 failed (%s)\n", nt_errstr(status));
6307 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6308 cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6309 status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS, FILE_ATTRIBUTE_NORMAL,
6311 FILE_SHARE_DELETE|FILE_SHARE_NONE,
6313 FILE_SHARE_DELETE|FILE_SHARE_READ,
6315 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
6316 if (!NT_STATUS_IS_OK(status)) {
6317 printf("Second open failed - %s\n", nt_errstr(status));
6321 status = cli_rename(cli1, fname, fname1, false);
6322 if (!NT_STATUS_IS_OK(status)) {
6323 printf("Second rename failed (SHARE_DELETE | SHARE_READ) - this should have succeeded - %s\n", nt_errstr(status));
6326 printf("Second rename succeeded (SHARE_DELETE | SHARE_READ)\n");
6329 status = cli_close(cli1, fnum1);
6330 if (!NT_STATUS_IS_OK(status)) {
6331 printf("close - 2 failed (%s)\n", nt_errstr(status));
6335 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6336 cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6338 status = cli_ntcreate(cli1, fname, 0, READ_CONTROL_ACCESS,
6339 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
6340 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
6341 if (!NT_STATUS_IS_OK(status)) {
6342 printf("Third open failed - %s\n", nt_errstr(status));
6347 status = cli_rename(cli1, fname, fname1, false);
6348 if (!NT_STATUS_IS_OK(status)) {
6349 printf("Third rename failed (SHARE_NONE) - this should have succeeded - %s\n", nt_errstr(status));
6352 printf("Third rename succeeded (SHARE_NONE)\n");
6355 status = cli_close(cli1, fnum1);
6356 if (!NT_STATUS_IS_OK(status)) {
6357 printf("close - 3 failed (%s)\n", nt_errstr(status));
6361 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6362 cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6366 status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
6367 FILE_ATTRIBUTE_NORMAL,
6368 FILE_SHARE_READ | FILE_SHARE_WRITE,
6369 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
6370 if (!NT_STATUS_IS_OK(status)) {
6371 printf("Fourth open failed - %s\n", nt_errstr(status));
6375 status = cli_rename(cli1, fname, fname1, false);
6376 if (!NT_STATUS_IS_OK(status)) {
6377 printf("Fourth rename failed (SHARE_READ | SHARE_WRITE) (this is correct) - %s\n", nt_errstr(status));
6379 printf("Fourth rename succeeded (SHARE_READ | SHARE_WRITE) - this should have failed !\n");
6383 status = cli_close(cli1, fnum1);
6384 if (!NT_STATUS_IS_OK(status)) {
6385 printf("close - 4 failed (%s)\n", nt_errstr(status));
6389 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6390 cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6394 status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
6395 FILE_ATTRIBUTE_NORMAL,
6396 FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
6397 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
6398 if (!NT_STATUS_IS_OK(status)) {
6399 printf("Fifth open failed - %s\n", nt_errstr(status));
6403 status = cli_rename(cli1, fname, fname1, false);
6404 if (!NT_STATUS_IS_OK(status)) {
6405 printf("Fifth rename failed (SHARE_READ | SHARE_WRITE | SHARE_DELETE) - this should have succeeded - %s ! \n", nt_errstr(status));
6408 printf("Fifth rename succeeded (SHARE_READ | SHARE_WRITE | SHARE_DELETE) (this is correct) - %s\n", nt_errstr(status));
6412 status = cli_close(cli1, fnum1);
6413 if (!NT_STATUS_IS_OK(status)) {
6414 printf("close - 5 failed (%s)\n", nt_errstr(status));
6418 /* Check that the renamed file has FILE_ATTRIBUTE_ARCHIVE. */
6419 status = cli_getatr(cli1, fname1, &attr, NULL, NULL);
6420 if (!NT_STATUS_IS_OK(status)) {
6421 printf("getatr on file %s failed - %s ! \n",
6422 fname1, nt_errstr(status));
6425 if (attr != FILE_ATTRIBUTE_ARCHIVE) {
6426 printf("Renamed file %s has wrong attr 0x%x "
6427 "(should be 0x%x)\n",
6430 (unsigned int)FILE_ATTRIBUTE_ARCHIVE);
6433 printf("Renamed file %s has archive bit set\n", fname1);
6437 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6438 cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6440 if (!torture_close_connection(cli1)) {
6448 Test rename into a directory with an ACL denying it.
6450 static bool run_rename_access(int dummy)
6452 static struct cli_state *cli = NULL;
6453 static struct cli_state *posix_cli = NULL;
6454 const char *src = "test.txt";
6455 const char *dname = "dir";
6456 const char *dst = "dir\\test.txt";
6457 const char *dsrc = "test.dir";
6458 const char *ddst = "dir\\test.dir";
6459 uint16_t fnum = (uint16_t)-1;
6460 struct security_descriptor *sd = NULL;
6461 struct security_descriptor *newsd = NULL;
6463 TALLOC_CTX *frame = NULL;
6465 frame = talloc_stackframe();
6466 printf("starting rename access test\n");
6468 /* Windows connection. */
6469 if (!torture_open_connection(&cli, 0)) {
6473 smbXcli_conn_set_sockopt(cli->conn, sockops);
6475 /* Posix connection. */
6476 if (!torture_open_connection(&posix_cli, 0)) {
6480 smbXcli_conn_set_sockopt(posix_cli->conn, sockops);
6482 status = torture_setup_unix_extensions(posix_cli);
6483 if (!NT_STATUS_IS_OK(status)) {
6487 /* Start with a clean slate. */
6488 cli_unlink(cli, src, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6489 cli_unlink(cli, dst, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6490 cli_rmdir(cli, dsrc);
6491 cli_rmdir(cli, ddst);
6492 cli_rmdir(cli, dname);
6495 * Setup the destination directory with a DENY ACE to
6496 * prevent new files within it.
6498 status = cli_ntcreate(cli,
6501 FILE_READ_ATTRIBUTES|READ_CONTROL_ACCESS|
6502 WRITE_DAC_ACCESS|FILE_READ_DATA|
6504 FILE_ATTRIBUTE_DIRECTORY,
6505 FILE_SHARE_READ|FILE_SHARE_WRITE,
6507 FILE_DIRECTORY_FILE,
6511 if (!NT_STATUS_IS_OK(status)) {
6512 printf("Create of %s - %s\n", dname, nt_errstr(status));
6516 status = cli_query_secdesc(cli,
6520 if (!NT_STATUS_IS_OK(status)) {
6521 printf("cli_query_secdesc failed for %s (%s)\n",
6522 dname, nt_errstr(status));
6526 newsd = security_descriptor_dacl_create(frame,
6531 SEC_ACE_TYPE_ACCESS_DENIED,
6532 SEC_DIR_ADD_FILE|SEC_DIR_ADD_SUBDIR,
6535 if (newsd == NULL) {
6538 sd->dacl = security_acl_concatenate(frame,
6541 if (sd->dacl == NULL) {
6544 status = cli_set_secdesc(cli, fnum, sd);
6545 if (!NT_STATUS_IS_OK(status)) {
6546 printf("cli_set_secdesc failed for %s (%s)\n",
6547 dname, nt_errstr(status));
6550 status = cli_close(cli, fnum);
6551 if (!NT_STATUS_IS_OK(status)) {
6552 printf("close failed for %s (%s)\n",
6553 dname, nt_errstr(status));
6556 /* Now go around the back and chmod to 777 via POSIX. */
6557 status = cli_posix_chmod(posix_cli, dname, 0777);
6558 if (!NT_STATUS_IS_OK(status)) {
6559 printf("cli_posix_chmod failed for %s (%s)\n",
6560 dname, nt_errstr(status));
6564 /* Check we can't create a file within dname via Windows. */
6565 status = cli_openx(cli, dst, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
6566 if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
6567 cli_close(posix_cli, fnum);
6568 printf("Create of %s should be ACCESS denied, was %s\n",
6569 dst, nt_errstr(status));
6573 /* Make the sample file/directory. */
6574 status = cli_openx(cli, src, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
6575 if (!NT_STATUS_IS_OK(status)) {
6576 printf("open of %s failed (%s)\n", src, nt_errstr(status));
6579 status = cli_close(cli, fnum);
6580 if (!NT_STATUS_IS_OK(status)) {
6581 printf("cli_close failed (%s)\n", nt_errstr(status));
6585 status = cli_mkdir(cli, dsrc);
6586 if (!NT_STATUS_IS_OK(status)) {
6587 printf("cli_mkdir of %s failed (%s)\n",
6588 dsrc, nt_errstr(status));
6593 * OK - renames of the new file and directory into the
6594 * dst directory should fail.
6597 status = cli_rename(cli, src, dst, false);
6598 if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
6599 printf("rename of %s -> %s should be ACCESS denied, was %s\n",
6600 src, dst, nt_errstr(status));
6603 status = cli_rename(cli, dsrc, ddst, false);
6604 if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
6605 printf("rename of %s -> %s should be ACCESS denied, was %s\n",
6606 src, dst, nt_errstr(status));
6616 torture_close_connection(posix_cli);
6620 if (fnum != (uint16_t)-1) {
6621 cli_close(cli, fnum);
6623 cli_unlink(cli, src,
6624 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6625 cli_unlink(cli, dst,
6626 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6627 cli_rmdir(cli, dsrc);
6628 cli_rmdir(cli, ddst);
6629 cli_rmdir(cli, dname);
6631 torture_close_connection(cli);
6639 Test owner rights ACE.
6641 static bool run_owner_rights(int dummy)
6643 static struct cli_state *cli = NULL;
6644 const char *fname = "owner_rights.txt";
6645 uint16_t fnum = (uint16_t)-1;
6646 struct security_descriptor *sd = NULL;
6647 struct security_descriptor *newsd = NULL;
6649 TALLOC_CTX *frame = NULL;
6651 frame = talloc_stackframe();
6652 printf("starting owner rights test\n");
6654 /* Windows connection. */
6655 if (!torture_open_connection(&cli, 0)) {
6659 smbXcli_conn_set_sockopt(cli->conn, sockops);
6661 /* Start with a clean slate. */
6662 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6664 /* Create the test file. */
6665 /* Now try and open for read and write-dac. */
6666 status = cli_ntcreate(cli,
6670 FILE_ATTRIBUTE_NORMAL,
6671 FILE_SHARE_READ|FILE_SHARE_WRITE|
6678 if (!NT_STATUS_IS_OK(status)) {
6679 printf("Create of %s - %s\n", fname, nt_errstr(status));
6683 /* Get the original SD. */
6684 status = cli_query_secdesc(cli,
6688 if (!NT_STATUS_IS_OK(status)) {
6689 printf("cli_query_secdesc failed for %s (%s)\n",
6690 fname, nt_errstr(status));
6695 * Add an "owner-rights" ACE denying WRITE_DATA,
6696 * and an "owner-rights" ACE allowing READ_DATA.
6699 newsd = security_descriptor_dacl_create(frame,
6704 SEC_ACE_TYPE_ACCESS_DENIED,
6708 SEC_ACE_TYPE_ACCESS_ALLOWED,
6712 if (newsd == NULL) {
6715 sd->dacl = security_acl_concatenate(frame,
6718 if (sd->dacl == NULL) {
6721 status = cli_set_secdesc(cli, fnum, sd);
6722 if (!NT_STATUS_IS_OK(status)) {
6723 printf("cli_set_secdesc failed for %s (%s)\n",
6724 fname, nt_errstr(status));
6727 status = cli_close(cli, fnum);
6728 if (!NT_STATUS_IS_OK(status)) {
6729 printf("close failed for %s (%s)\n",
6730 fname, nt_errstr(status));
6733 fnum = (uint16_t)-1;
6735 /* Try and open for FILE_WRITE_DATA */
6736 status = cli_ntcreate(cli,
6740 FILE_ATTRIBUTE_NORMAL,
6741 FILE_SHARE_READ|FILE_SHARE_WRITE|
6748 if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
6749 printf("Open of %s - %s\n", fname, nt_errstr(status));
6753 /* Now try and open for FILE_READ_DATA */
6754 status = cli_ntcreate(cli,
6758 FILE_ATTRIBUTE_NORMAL,
6759 FILE_SHARE_READ|FILE_SHARE_WRITE|
6766 if (!NT_STATUS_IS_OK(status)) {
6767 printf("Open of %s - %s\n", fname, nt_errstr(status));
6771 status = cli_close(cli, fnum);
6772 if (!NT_STATUS_IS_OK(status)) {
6773 printf("close failed for %s (%s)\n",
6774 fname, nt_errstr(status));
6778 /* Restore clean slate. */
6780 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6782 /* Create the test file. */
6783 status = cli_ntcreate(cli,
6787 FILE_ATTRIBUTE_NORMAL,
6788 FILE_SHARE_READ|FILE_SHARE_WRITE|
6795 if (!NT_STATUS_IS_OK(status)) {
6796 printf("Create of %s - %s\n", fname, nt_errstr(status));
6800 /* Get the original SD. */
6801 status = cli_query_secdesc(cli,
6805 if (!NT_STATUS_IS_OK(status)) {
6806 printf("cli_query_secdesc failed for %s (%s)\n",
6807 fname, nt_errstr(status));
6812 * Add an "owner-rights ACE denying WRITE_DATA,
6813 * and an "owner-rights ACE allowing READ_DATA|WRITE_DATA.
6816 newsd = security_descriptor_dacl_create(frame,
6821 SEC_ACE_TYPE_ACCESS_DENIED,
6825 SEC_ACE_TYPE_ACCESS_ALLOWED,
6826 FILE_READ_DATA|FILE_WRITE_DATA,
6829 if (newsd == NULL) {
6832 sd->dacl = security_acl_concatenate(frame,
6835 if (sd->dacl == NULL) {
6838 status = cli_set_secdesc(cli, fnum, sd);
6839 if (!NT_STATUS_IS_OK(status)) {
6840 printf("cli_set_secdesc failed for %s (%s)\n",
6841 fname, nt_errstr(status));
6844 status = cli_close(cli, fnum);
6845 if (!NT_STATUS_IS_OK(status)) {
6846 printf("close failed for %s (%s)\n",
6847 fname, nt_errstr(status));
6850 fnum = (uint16_t)-1;
6852 /* Try and open for FILE_WRITE_DATA */
6853 status = cli_ntcreate(cli,
6857 FILE_ATTRIBUTE_NORMAL,
6858 FILE_SHARE_READ|FILE_SHARE_WRITE|
6865 if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
6866 printf("Open of %s - %s\n", fname, nt_errstr(status));
6870 /* Now try and open for FILE_READ_DATA */
6871 status = cli_ntcreate(cli,
6875 FILE_ATTRIBUTE_NORMAL,
6876 FILE_SHARE_READ|FILE_SHARE_WRITE|
6883 if (!NT_STATUS_IS_OK(status)) {
6884 printf("Open of %s - %s\n", fname, nt_errstr(status));
6888 status = cli_close(cli, fnum);
6889 if (!NT_STATUS_IS_OK(status)) {
6890 printf("close failed for %s (%s)\n",
6891 fname, nt_errstr(status));
6895 /* Restore clean slate. */
6897 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6900 /* Create the test file. */
6901 status = cli_ntcreate(cli,
6905 FILE_ATTRIBUTE_NORMAL,
6906 FILE_SHARE_READ|FILE_SHARE_WRITE|
6913 if (!NT_STATUS_IS_OK(status)) {
6914 printf("Create of %s - %s\n", fname, nt_errstr(status));
6918 /* Get the original SD. */
6919 status = cli_query_secdesc(cli,
6923 if (!NT_STATUS_IS_OK(status)) {
6924 printf("cli_query_secdesc failed for %s (%s)\n",
6925 fname, nt_errstr(status));
6930 * Add an "authenticated users" ACE allowing READ_DATA,
6931 * add an "owner-rights" denying READ_DATA,
6932 * and an "authenticated users" ACE allowing WRITE_DATA.
6935 newsd = security_descriptor_dacl_create(frame,
6939 SID_NT_AUTHENTICATED_USERS,
6940 SEC_ACE_TYPE_ACCESS_ALLOWED,
6944 SEC_ACE_TYPE_ACCESS_DENIED,
6947 SID_NT_AUTHENTICATED_USERS,
6948 SEC_ACE_TYPE_ACCESS_ALLOWED,
6952 if (newsd == NULL) {
6953 printf("newsd == NULL\n");
6956 sd->dacl = security_acl_concatenate(frame,
6959 if (sd->dacl == NULL) {
6960 printf("sd->dacl == NULL\n");
6963 status = cli_set_secdesc(cli, fnum, sd);
6964 if (!NT_STATUS_IS_OK(status)) {
6965 printf("cli_set_secdesc failed for %s (%s)\n",
6966 fname, nt_errstr(status));
6969 status = cli_close(cli, fnum);
6970 if (!NT_STATUS_IS_OK(status)) {
6971 printf("close failed for %s (%s)\n",
6972 fname, nt_errstr(status));
6975 fnum = (uint16_t)-1;
6977 /* Now try and open for FILE_READ_DATA|FILE_WRITE_DATA */
6978 status = cli_ntcreate(cli,
6981 FILE_READ_DATA|FILE_WRITE_DATA,
6982 FILE_ATTRIBUTE_NORMAL,
6983 FILE_SHARE_READ|FILE_SHARE_WRITE|
6990 if (!NT_STATUS_IS_OK(status)) {
6991 printf("Open of %s - %s\n", fname, nt_errstr(status));
6995 status = cli_close(cli, fnum);
6996 if (!NT_STATUS_IS_OK(status)) {
6997 printf("close failed for %s (%s)\n",
6998 fname, nt_errstr(status));
7002 cli_unlink(cli, fname,
7003 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7011 if (fnum != (uint16_t)-1) {
7012 cli_close(cli, fnum);
7014 cli_unlink(cli, fname,
7015 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7016 torture_close_connection(cli);
7024 * Test SMB1-specific open with SEC_FLAG_SYSTEM_SECURITY.
7025 * Note this test only works with a user with SeSecurityPrivilege set.
7027 * NB. This is also tested in samba3.base.createx_access
7028 * but this makes it very explicit what we're looking for.
7030 static bool run_smb1_system_security(int dummy)
7032 static struct cli_state *cli = NULL;
7033 const char *fname = "system_security.txt";
7034 uint16_t fnum = (uint16_t)-1;
7036 TALLOC_CTX *frame = NULL;
7038 frame = talloc_stackframe();
7039 printf("starting smb1 system security test\n");
7041 /* SMB1 connection - torture_open_connection() forces this. */
7042 if (!torture_open_connection(&cli, 0)) {
7046 smbXcli_conn_set_sockopt(cli->conn, sockops);
7048 /* Start with a clean slate. */
7049 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7051 /* Create the test file. */
7052 status = cli_ntcreate(cli,
7056 FILE_ATTRIBUTE_NORMAL,
7057 FILE_SHARE_READ|FILE_SHARE_WRITE|
7064 if (!NT_STATUS_IS_OK(status)) {
7065 printf("Create of %s - %s\n", fname, nt_errstr(status));
7069 status = cli_close(cli, fnum);
7071 /* Open with SEC_FLAG_SYSTEM_SECURITY only. */
7073 * On SMB1 this succeeds - SMB2 it fails,
7074 * see the SMB2-SACL test.
7076 status = cli_ntcreate(cli,
7079 SEC_FLAG_SYSTEM_SECURITY,
7080 FILE_ATTRIBUTE_NORMAL,
7081 FILE_SHARE_READ|FILE_SHARE_WRITE|
7088 if (!NT_STATUS_IS_OK(status)) {
7089 printf("Open of %s - %s\n", fname, nt_errstr(status));
7093 status = cli_close(cli, fnum);
7095 cli_unlink(cli, fname,
7096 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7098 torture_close_connection(cli);
7105 if (fnum != (uint16_t)-1) {
7106 cli_close(cli, fnum);
7108 cli_unlink(cli, fname,
7109 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7110 torture_close_connection(cli);
7117 static bool run_pipe_number(int dummy)
7119 struct cli_state *cli1;
7120 const char *pipe_name = "\\SPOOLSS";
7125 printf("starting pipenumber test\n");
7126 if (!torture_open_connection(&cli1, 0)) {
7130 smbXcli_conn_set_sockopt(cli1->conn, sockops);
7132 status = cli_ntcreate(cli1, pipe_name, 0, FILE_READ_DATA,
7133 FILE_ATTRIBUTE_NORMAL,
7134 FILE_SHARE_READ|FILE_SHARE_WRITE,
7135 FILE_OPEN_IF, 0, 0, &fnum, NULL);
7136 if (!NT_STATUS_IS_OK(status)) {
7137 printf("Open of pipe %s failed with error (%s)\n", pipe_name, nt_errstr(status));
7141 printf("\r%6d", num_pipes);
7144 printf("pipe_number test - we can open %d %s pipes.\n", num_pipes, pipe_name );
7145 torture_close_connection(cli1);
7150 Test open mode returns on read-only files.
7152 static bool run_opentest(int dummy)
7154 static struct cli_state *cli1;
7155 static struct cli_state *cli2;
7156 const char *fname = "\\readonly.file";
7157 uint16_t fnum1, fnum2;
7160 bool correct = True;
7164 printf("starting open test\n");
7166 if (!torture_open_connection(&cli1, 0)) {
7170 cli_setatr(cli1, fname, 0, 0);
7171 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7173 smbXcli_conn_set_sockopt(cli1->conn, sockops);
7175 status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
7176 if (!NT_STATUS_IS_OK(status)) {
7177 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
7181 status = cli_close(cli1, fnum1);
7182 if (!NT_STATUS_IS_OK(status)) {
7183 printf("close2 failed (%s)\n", nt_errstr(status));
7187 status = cli_setatr(cli1, fname, FILE_ATTRIBUTE_READONLY, 0);
7188 if (!NT_STATUS_IS_OK(status)) {
7189 printf("cli_setatr failed (%s)\n", nt_errstr(status));
7193 status = cli_openx(cli1, fname, O_RDONLY, DENY_WRITE, &fnum1);
7194 if (!NT_STATUS_IS_OK(status)) {
7195 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
7199 /* This will fail - but the error should be ERRnoaccess, not ERRbadshare. */
7200 status = cli_openx(cli1, fname, O_RDWR, DENY_ALL, &fnum2);
7202 if (check_error(__LINE__, status, ERRDOS, ERRnoaccess,
7203 NT_STATUS_ACCESS_DENIED)) {
7204 printf("correct error code ERRDOS/ERRnoaccess returned\n");
7207 printf("finished open test 1\n");
7209 cli_close(cli1, fnum1);
7211 /* Now try not readonly and ensure ERRbadshare is returned. */
7213 cli_setatr(cli1, fname, 0, 0);
7215 status = cli_openx(cli1, fname, O_RDONLY, DENY_WRITE, &fnum1);
7216 if (!NT_STATUS_IS_OK(status)) {
7217 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
7221 /* This will fail - but the error should be ERRshare. */
7222 status = cli_openx(cli1, fname, O_RDWR, DENY_ALL, &fnum2);
7224 if (check_error(__LINE__, status, ERRDOS, ERRbadshare,
7225 NT_STATUS_SHARING_VIOLATION)) {
7226 printf("correct error code ERRDOS/ERRbadshare returned\n");
7229 status = cli_close(cli1, fnum1);
7230 if (!NT_STATUS_IS_OK(status)) {
7231 printf("close2 failed (%s)\n", nt_errstr(status));
7235 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7237 printf("finished open test 2\n");
7239 /* Test truncate open disposition on file opened for read. */
7240 status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
7241 if (!NT_STATUS_IS_OK(status)) {
7242 printf("(3) open (1) of %s failed (%s)\n", fname, nt_errstr(status));
7246 /* write 20 bytes. */
7248 memset(buf, '\0', 20);
7250 status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 0, 20, NULL);
7251 if (!NT_STATUS_IS_OK(status)) {
7252 printf("write failed (%s)\n", nt_errstr(status));
7256 status = cli_close(cli1, fnum1);
7257 if (!NT_STATUS_IS_OK(status)) {
7258 printf("(3) close1 failed (%s)\n", nt_errstr(status));
7262 /* Ensure size == 20. */
7263 status = cli_getatr(cli1, fname, NULL, &fsize, NULL);
7264 if (!NT_STATUS_IS_OK(status)) {
7265 printf("(3) getatr failed (%s)\n", nt_errstr(status));
7270 printf("(3) file size != 20\n");
7274 /* Now test if we can truncate a file opened for readonly. */
7275 status = cli_openx(cli1, fname, O_RDONLY|O_TRUNC, DENY_NONE, &fnum1);
7276 if (!NT_STATUS_IS_OK(status)) {
7277 printf("(3) open (2) of %s failed (%s)\n", fname, nt_errstr(status));
7281 status = cli_close(cli1, fnum1);
7282 if (!NT_STATUS_IS_OK(status)) {
7283 printf("close2 failed (%s)\n", nt_errstr(status));
7287 /* Ensure size == 0. */
7288 status = cli_getatr(cli1, fname, NULL, &fsize, NULL);
7289 if (!NT_STATUS_IS_OK(status)) {
7290 printf("(3) getatr failed (%s)\n", nt_errstr(status));
7295 printf("(3) file size != 0\n");
7298 printf("finished open test 3\n");
7300 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7302 printf("Do ctemp tests\n");
7303 status = cli_ctemp(cli1, talloc_tos(), "\\", &fnum1, &tmp_path);
7304 if (!NT_STATUS_IS_OK(status)) {
7305 printf("ctemp failed (%s)\n", nt_errstr(status));
7309 printf("ctemp gave path %s\n", tmp_path);
7310 status = cli_close(cli1, fnum1);
7311 if (!NT_STATUS_IS_OK(status)) {
7312 printf("close of temp failed (%s)\n", nt_errstr(status));
7315 status = cli_unlink(cli1, tmp_path, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7316 if (!NT_STATUS_IS_OK(status)) {
7317 printf("unlink of temp failed (%s)\n", nt_errstr(status));
7320 /* Test the non-io opens... */
7322 if (!torture_open_connection(&cli2, 1)) {
7326 cli_setatr(cli2, fname, 0, 0);
7327 cli_unlink(cli2, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7329 smbXcli_conn_set_sockopt(cli2->conn, sockops);
7331 printf("TEST #1 testing 2 non-io opens (no delete)\n");
7332 status = cli_ntcreate(cli1, fname, 0, FILE_READ_ATTRIBUTES,
7333 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7334 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
7335 if (!NT_STATUS_IS_OK(status)) {
7336 printf("TEST #1 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
7340 status = cli_ntcreate(cli2, fname, 0, FILE_READ_ATTRIBUTES,
7341 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7342 FILE_OPEN_IF, 0, 0, &fnum2, NULL);
7343 if (!NT_STATUS_IS_OK(status)) {
7344 printf("TEST #1 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
7348 status = cli_close(cli1, fnum1);
7349 if (!NT_STATUS_IS_OK(status)) {
7350 printf("TEST #1 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
7354 status = cli_close(cli2, fnum2);
7355 if (!NT_STATUS_IS_OK(status)) {
7356 printf("TEST #1 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
7360 printf("non-io open test #1 passed.\n");
7362 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7364 printf("TEST #2 testing 2 non-io opens (first with delete)\n");
7366 status = cli_ntcreate(cli1, fname, 0,
7367 DELETE_ACCESS|FILE_READ_ATTRIBUTES,
7368 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7369 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
7370 if (!NT_STATUS_IS_OK(status)) {
7371 printf("TEST #2 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
7375 status = cli_ntcreate(cli2, fname, 0, FILE_READ_ATTRIBUTES,
7376 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7377 FILE_OPEN_IF, 0, 0, &fnum2, NULL);
7378 if (!NT_STATUS_IS_OK(status)) {
7379 printf("TEST #2 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
7383 status = cli_close(cli1, fnum1);
7384 if (!NT_STATUS_IS_OK(status)) {
7385 printf("TEST #2 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
7389 status = cli_close(cli2, fnum2);
7390 if (!NT_STATUS_IS_OK(status)) {
7391 printf("TEST #2 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
7395 printf("non-io open test #2 passed.\n");
7397 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7399 printf("TEST #3 testing 2 non-io opens (second with delete)\n");
7401 status = cli_ntcreate(cli1, fname, 0, FILE_READ_ATTRIBUTES,
7402 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7403 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
7404 if (!NT_STATUS_IS_OK(status)) {
7405 printf("TEST #3 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
7409 status = cli_ntcreate(cli2, fname, 0,
7410 DELETE_ACCESS|FILE_READ_ATTRIBUTES,
7411 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7412 FILE_OPEN_IF, 0, 0, &fnum2, NULL);
7413 if (!NT_STATUS_IS_OK(status)) {
7414 printf("TEST #3 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
7418 status = cli_close(cli1, fnum1);
7419 if (!NT_STATUS_IS_OK(status)) {
7420 printf("TEST #3 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
7424 status = cli_close(cli2, fnum2);
7425 if (!NT_STATUS_IS_OK(status)) {
7426 printf("TEST #3 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
7430 printf("non-io open test #3 passed.\n");
7432 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7434 printf("TEST #4 testing 2 non-io opens (both with delete)\n");
7436 status = cli_ntcreate(cli1, fname, 0,
7437 DELETE_ACCESS|FILE_READ_ATTRIBUTES,
7438 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7439 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
7440 if (!NT_STATUS_IS_OK(status)) {
7441 printf("TEST #4 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
7445 status = cli_ntcreate(cli2, fname, 0,
7446 DELETE_ACCESS|FILE_READ_ATTRIBUTES,
7447 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7448 FILE_OPEN_IF, 0, 0, &fnum2, NULL);
7449 if (NT_STATUS_IS_OK(status)) {
7450 printf("TEST #4 open 2 of %s SUCCEEDED - should have failed (%s)\n", fname, nt_errstr(status));
7454 printf("TEST #4 open 2 of %s gave %s (correct error should be %s)\n", fname, nt_errstr(status), "sharing violation");
7456 status = cli_close(cli1, fnum1);
7457 if (!NT_STATUS_IS_OK(status)) {
7458 printf("TEST #4 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
7462 printf("non-io open test #4 passed.\n");
7464 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7466 printf("TEST #5 testing 2 non-io opens (both with delete - both with file share delete)\n");
7468 status = cli_ntcreate(cli1, fname, 0,
7469 DELETE_ACCESS|FILE_READ_ATTRIBUTES,
7470 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_DELETE,
7471 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
7472 if (!NT_STATUS_IS_OK(status)) {
7473 printf("TEST #5 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
7477 status = cli_ntcreate(cli2, fname, 0,
7478 DELETE_ACCESS|FILE_READ_ATTRIBUTES,
7479 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_DELETE,
7480 FILE_OPEN_IF, 0, 0, &fnum2, NULL);
7481 if (!NT_STATUS_IS_OK(status)) {
7482 printf("TEST #5 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
7486 status = cli_close(cli1, fnum1);
7487 if (!NT_STATUS_IS_OK(status)) {
7488 printf("TEST #5 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
7492 status = cli_close(cli2, fnum2);
7493 if (!NT_STATUS_IS_OK(status)) {
7494 printf("TEST #5 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
7498 printf("non-io open test #5 passed.\n");
7500 printf("TEST #6 testing 1 non-io open, one io open\n");
7502 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7504 status = cli_ntcreate(cli1, fname, 0, FILE_READ_DATA,
7505 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7506 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
7507 if (!NT_STATUS_IS_OK(status)) {
7508 printf("TEST #6 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
7512 status = cli_ntcreate(cli2, fname, 0, FILE_READ_ATTRIBUTES,
7513 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ,
7514 FILE_OPEN_IF, 0, 0, &fnum2, NULL);
7515 if (!NT_STATUS_IS_OK(status)) {
7516 printf("TEST #6 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
7520 status = cli_close(cli1, fnum1);
7521 if (!NT_STATUS_IS_OK(status)) {
7522 printf("TEST #6 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
7526 status = cli_close(cli2, fnum2);
7527 if (!NT_STATUS_IS_OK(status)) {
7528 printf("TEST #6 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
7532 printf("non-io open test #6 passed.\n");
7534 printf("TEST #7 testing 1 non-io open, one io open with delete\n");
7536 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7538 status = cli_ntcreate(cli1, fname, 0, FILE_READ_DATA,
7539 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7540 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
7541 if (!NT_STATUS_IS_OK(status)) {
7542 printf("TEST #7 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
7546 status = cli_ntcreate(cli2, fname, 0,
7547 DELETE_ACCESS|FILE_READ_ATTRIBUTES,
7548 FILE_ATTRIBUTE_NORMAL,
7549 FILE_SHARE_READ|FILE_SHARE_DELETE,
7550 FILE_OPEN_IF, 0, 0, &fnum2, NULL);
7551 if (NT_STATUS_IS_OK(status)) {
7552 printf("TEST #7 open 2 of %s SUCCEEDED - should have failed (%s)\n", fname, nt_errstr(status));
7556 printf("TEST #7 open 2 of %s gave %s (correct error should be %s)\n", fname, nt_errstr(status), "sharing violation");
7558 status = cli_close(cli1, fnum1);
7559 if (!NT_STATUS_IS_OK(status)) {
7560 printf("TEST #7 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
7564 printf("non-io open test #7 passed.\n");
7566 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7568 printf("TEST #8 testing open without WRITE_ATTRIBUTES, updating close write time.\n");
7569 status = cli_ntcreate(cli1, fname, 0, FILE_WRITE_DATA, FILE_ATTRIBUTE_NORMAL,
7570 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
7571 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
7572 if (!NT_STATUS_IS_OK(status)) {
7573 printf("TEST #8 open of %s failed (%s)\n", fname, nt_errstr(status));
7578 /* Write to ensure we have to update the file time. */
7579 status = cli_writeall(cli1, fnum1, 0, (const uint8_t *)"TEST DATA\n", 0, 10,
7581 if (!NT_STATUS_IS_OK(status)) {
7582 printf("TEST #8 cli_write failed: %s\n", nt_errstr(status));
7587 status = cli_close(cli1, fnum1);
7588 if (!NT_STATUS_IS_OK(status)) {
7589 printf("TEST #8 close of %s failed (%s)\n", fname, nt_errstr(status));
7595 if (!torture_close_connection(cli1)) {
7598 if (!torture_close_connection(cli2)) {
7605 NTSTATUS torture_setup_unix_extensions(struct cli_state *cli)
7607 uint16_t major, minor;
7608 uint32_t caplow, caphigh;
7611 if (!SERVER_HAS_UNIX_CIFS(cli)) {
7612 printf("Server doesn't support UNIX CIFS extensions.\n");
7613 return NT_STATUS_NOT_SUPPORTED;
7616 status = cli_unix_extensions_version(cli, &major, &minor, &caplow,
7618 if (!NT_STATUS_IS_OK(status)) {
7619 printf("Server didn't return UNIX CIFS extensions: %s\n",
7624 status = cli_set_unix_extensions_capabilities(cli, major, minor,
7626 if (!NT_STATUS_IS_OK(status)) {
7627 printf("Server doesn't support setting UNIX CIFS extensions: "
7628 "%s.\n", nt_errstr(status));
7632 return NT_STATUS_OK;
7636 Test POSIX open /mkdir calls.
7638 static bool run_simple_posix_open_test(int dummy)
7640 static struct cli_state *cli1;
7641 const char *fname = "posix:file";
7642 const char *hname = "posix:hlink";
7643 const char *sname = "posix:symlink";
7644 const char *dname = "posix:dir";
7646 char *target = NULL;
7647 uint16_t fnum1 = (uint16_t)-1;
7648 SMB_STRUCT_STAT sbuf;
7649 bool correct = false;
7652 const char *fname_windows = "windows_file";
7653 uint16_t fnum2 = (uint16_t)-1;
7655 printf("Starting simple POSIX open test\n");
7657 if (!torture_open_connection(&cli1, 0)) {
7661 smbXcli_conn_set_sockopt(cli1->conn, sockops);
7663 status = torture_setup_unix_extensions(cli1);
7664 if (!NT_STATUS_IS_OK(status)) {
7668 cli_setatr(cli1, fname, 0, 0);
7669 cli_posix_unlink(cli1, fname);
7670 cli_setatr(cli1, dname, 0, 0);
7671 cli_posix_rmdir(cli1, dname);
7672 cli_setatr(cli1, hname, 0, 0);
7673 cli_posix_unlink(cli1, hname);
7674 cli_setatr(cli1, sname, 0, 0);
7675 cli_posix_unlink(cli1, sname);
7676 cli_setatr(cli1, fname_windows, 0, 0);
7677 cli_posix_unlink(cli1, fname_windows);
7679 /* Create a directory. */
7680 status = cli_posix_mkdir(cli1, dname, 0777);
7681 if (!NT_STATUS_IS_OK(status)) {
7682 printf("POSIX mkdir of %s failed (%s)\n", dname, nt_errstr(status));
7686 status = cli_posix_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL,
7688 if (!NT_STATUS_IS_OK(status)) {
7689 printf("POSIX create of %s failed (%s)\n", fname, nt_errstr(status));
7693 /* Test ftruncate - set file size. */
7694 status = cli_ftruncate(cli1, fnum1, 1000);
7695 if (!NT_STATUS_IS_OK(status)) {
7696 printf("ftruncate failed (%s)\n", nt_errstr(status));
7700 /* Ensure st_size == 1000 */
7701 status = cli_posix_stat(cli1, fname, &sbuf);
7702 if (!NT_STATUS_IS_OK(status)) {
7703 printf("stat failed (%s)\n", nt_errstr(status));
7707 if (sbuf.st_ex_size != 1000) {
7708 printf("ftruncate - stat size (%u) != 1000\n", (unsigned int)sbuf.st_ex_size);
7712 /* Ensure st_mode == 0600 */
7713 if ((sbuf.st_ex_mode & 07777) != 0600) {
7714 printf("posix_open - bad permissions 0%o != 0600\n",
7715 (unsigned int)(sbuf.st_ex_mode & 07777));
7719 /* Test ftruncate - set file size back to zero. */
7720 status = cli_ftruncate(cli1, fnum1, 0);
7721 if (!NT_STATUS_IS_OK(status)) {
7722 printf("ftruncate failed (%s)\n", nt_errstr(status));
7726 status = cli_close(cli1, fnum1);
7727 if (!NT_STATUS_IS_OK(status)) {
7728 printf("close failed (%s)\n", nt_errstr(status));
7732 /* Now open the file again for read only. */
7733 status = cli_posix_open(cli1, fname, O_RDONLY, 0, &fnum1);
7734 if (!NT_STATUS_IS_OK(status)) {
7735 printf("POSIX open of %s failed (%s)\n", fname, nt_errstr(status));
7739 /* Now unlink while open. */
7740 status = cli_posix_unlink(cli1, fname);
7741 if (!NT_STATUS_IS_OK(status)) {
7742 printf("POSIX unlink of %s failed (%s)\n", fname, nt_errstr(status));
7746 status = cli_close(cli1, fnum1);
7747 if (!NT_STATUS_IS_OK(status)) {
7748 printf("close(2) failed (%s)\n", nt_errstr(status));
7752 /* Ensure the file has gone. */
7753 status = cli_posix_open(cli1, fname, O_RDONLY, 0, &fnum1);
7754 if (NT_STATUS_IS_OK(status)) {
7755 printf("POSIX open of %s succeeded, should have been deleted.\n", fname);
7759 /* Create again to test open with O_TRUNC. */
7760 status = cli_posix_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL, 0600, &fnum1);
7761 if (!NT_STATUS_IS_OK(status)) {
7762 printf("POSIX create of %s failed (%s)\n", fname, nt_errstr(status));
7766 /* Test ftruncate - set file size. */
7767 status = cli_ftruncate(cli1, fnum1, 1000);
7768 if (!NT_STATUS_IS_OK(status)) {
7769 printf("ftruncate failed (%s)\n", nt_errstr(status));
7773 /* Ensure st_size == 1000 */
7774 status = cli_posix_stat(cli1, fname, &sbuf);
7775 if (!NT_STATUS_IS_OK(status)) {
7776 printf("stat failed (%s)\n", nt_errstr(status));
7780 if (sbuf.st_ex_size != 1000) {
7781 printf("ftruncate - stat size (%u) != 1000\n", (unsigned int)sbuf.st_ex_size);
7785 status = cli_close(cli1, fnum1);
7786 if (!NT_STATUS_IS_OK(status)) {
7787 printf("close(2) failed (%s)\n", nt_errstr(status));
7791 /* Re-open with O_TRUNC. */
7792 status = cli_posix_open(cli1, fname, O_WRONLY|O_TRUNC, 0600, &fnum1);
7793 if (!NT_STATUS_IS_OK(status)) {
7794 printf("POSIX create of %s failed (%s)\n", fname, nt_errstr(status));
7798 /* Ensure st_size == 0 */
7799 status = cli_posix_stat(cli1, fname, &sbuf);
7800 if (!NT_STATUS_IS_OK(status)) {
7801 printf("stat failed (%s)\n", nt_errstr(status));
7805 if (sbuf.st_ex_size != 0) {
7806 printf("O_TRUNC - stat size (%u) != 0\n", (unsigned int)sbuf.st_ex_size);
7810 status = cli_close(cli1, fnum1);
7811 if (!NT_STATUS_IS_OK(status)) {
7812 printf("close failed (%s)\n", nt_errstr(status));
7816 status = cli_posix_unlink(cli1, fname);
7817 if (!NT_STATUS_IS_OK(status)) {
7818 printf("POSIX unlink of %s failed (%s)\n", fname, nt_errstr(status));
7822 status = cli_posix_open(cli1, dname, O_RDONLY, 0, &fnum1);
7823 if (!NT_STATUS_IS_OK(status)) {
7824 printf("POSIX open directory O_RDONLY of %s failed (%s)\n",
7825 dname, nt_errstr(status));
7829 cli_close(cli1, fnum1);
7831 /* What happens when we try and POSIX open a directory for write ? */
7832 status = cli_posix_open(cli1, dname, O_RDWR, 0, &fnum1);
7833 if (NT_STATUS_IS_OK(status)) {
7834 printf("POSIX open of directory %s succeeded, "
7835 "should have failed.\n",
7839 if (!check_both_error(__LINE__, status, ERRDOS, EISDIR,
7840 NT_STATUS_FILE_IS_A_DIRECTORY)) {
7845 /* Create the file. */
7846 status = cli_posix_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL,
7848 if (!NT_STATUS_IS_OK(status)) {
7849 printf("POSIX create of %s failed (%s)\n", fname, nt_errstr(status));
7853 /* Write some data into it. */
7854 status = cli_writeall(cli1, fnum1, 0, (const uint8_t *)"TEST DATA\n", 0, 10,
7856 if (!NT_STATUS_IS_OK(status)) {
7857 printf("cli_write failed: %s\n", nt_errstr(status));
7861 cli_close(cli1, fnum1);
7863 /* Now create a hardlink. */
7864 status = cli_posix_hardlink(cli1, fname, hname);
7865 if (!NT_STATUS_IS_OK(status)) {
7866 printf("POSIX hardlink of %s failed (%s)\n", hname, nt_errstr(status));
7870 /* Now create a symlink. */
7871 status = cli_posix_symlink(cli1, fname, sname);
7872 if (!NT_STATUS_IS_OK(status)) {
7873 printf("POSIX symlink of %s failed (%s)\n", sname, nt_errstr(status));
7877 /* Open the hardlink for read. */
7878 status = cli_posix_open(cli1, hname, O_RDONLY, 0, &fnum1);
7879 if (!NT_STATUS_IS_OK(status)) {
7880 printf("POSIX open of %s failed (%s)\n", hname, nt_errstr(status));
7884 status = cli_read(cli1, fnum1, buf, 0, 10, &nread);
7885 if (!NT_STATUS_IS_OK(status)) {
7886 printf("POSIX read of %s failed (%s)\n", hname,
7889 } else if (nread != 10) {
7890 printf("POSIX read of %s failed. Received %ld, expected %d\n",
7891 hname, (unsigned long)nread, 10);
7895 if (memcmp(buf, "TEST DATA\n", 10)) {
7896 printf("invalid data read from hardlink\n");
7900 /* Do a POSIX lock/unlock. */
7901 status = cli_posix_lock(cli1, fnum1, 0, 100, true, READ_LOCK);
7902 if (!NT_STATUS_IS_OK(status)) {
7903 printf("POSIX lock failed %s\n", nt_errstr(status));
7907 /* Punch a hole in the locked area. */
7908 status = cli_posix_unlock(cli1, fnum1, 10, 80);
7909 if (!NT_STATUS_IS_OK(status)) {
7910 printf("POSIX unlock failed %s\n", nt_errstr(status));
7914 cli_close(cli1, fnum1);
7916 /* Open the symlink for read - this should fail. A POSIX
7917 client should not be doing opens on a symlink. */
7918 status = cli_posix_open(cli1, sname, O_RDONLY, 0, &fnum1);
7919 if (NT_STATUS_IS_OK(status)) {
7920 printf("POSIX open of %s succeeded (should have failed)\n", sname);
7923 if (!check_both_error(__LINE__, status, ERRDOS, ERRbadpath,
7924 NT_STATUS_OBJECT_PATH_NOT_FOUND)) {
7925 printf("POSIX open of %s should have failed "
7926 "with NT_STATUS_OBJECT_PATH_NOT_FOUND, "
7927 "failed with %s instead.\n",
7928 sname, nt_errstr(status));
7933 status = cli_posix_readlink(cli1, sname, talloc_tos(), &target);
7934 if (!NT_STATUS_IS_OK(status)) {
7935 printf("POSIX readlink on %s failed (%s)\n", sname, nt_errstr(status));
7939 if (strcmp(target, fname) != 0) {
7940 printf("POSIX readlink on %s failed to match name %s (read %s)\n",
7941 sname, fname, target);
7945 status = cli_posix_rmdir(cli1, dname);
7946 if (!NT_STATUS_IS_OK(status)) {
7947 printf("POSIX rmdir failed (%s)\n", nt_errstr(status));
7951 /* Check directory opens with a specific permission. */
7952 status = cli_posix_mkdir(cli1, dname, 0700);
7953 if (!NT_STATUS_IS_OK(status)) {
7954 printf("POSIX mkdir of %s failed (%s)\n", dname, nt_errstr(status));
7958 /* Ensure st_mode == 0700 */
7959 status = cli_posix_stat(cli1, dname, &sbuf);
7960 if (!NT_STATUS_IS_OK(status)) {
7961 printf("stat failed (%s)\n", nt_errstr(status));
7965 if ((sbuf.st_ex_mode & 07777) != 0700) {
7966 printf("posix_mkdir - bad permissions 0%o != 0700\n",
7967 (unsigned int)(sbuf.st_ex_mode & 07777));
7972 * Now create a Windows file, and attempt a POSIX unlink.
7973 * This should fail with a sharing violation but due to:
7975 * [Bug 9571] Unlink after open causes smbd to panic
7977 * ensure we've fixed the lock ordering violation.
7980 status = cli_ntcreate(cli1, fname_windows, 0,
7981 FILE_READ_DATA|FILE_WRITE_DATA, 0,
7982 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
7984 0x0, 0x0, &fnum2, NULL);
7985 if (!NT_STATUS_IS_OK(status)) {
7986 printf("Windows create of %s failed (%s)\n", fname_windows,
7991 /* Now try posix_unlink. */
7992 status = cli_posix_unlink(cli1, fname_windows);
7993 if (!NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
7994 printf("POSIX unlink of %s should fail "
7995 "with NT_STATUS_SHARING_VIOLATION "
7996 "got %s instead !\n",
8002 cli_close(cli1, fnum2);
8004 printf("Simple POSIX open test passed\n");
8009 if (fnum1 != (uint16_t)-1) {
8010 cli_close(cli1, fnum1);
8011 fnum1 = (uint16_t)-1;
8014 if (fnum2 != (uint16_t)-1) {
8015 cli_close(cli1, fnum2);
8016 fnum2 = (uint16_t)-1;
8019 cli_setatr(cli1, sname, 0, 0);
8020 cli_posix_unlink(cli1, sname);
8021 cli_setatr(cli1, hname, 0, 0);
8022 cli_posix_unlink(cli1, hname);
8023 cli_setatr(cli1, fname, 0, 0);
8024 cli_posix_unlink(cli1, fname);
8025 cli_setatr(cli1, dname, 0, 0);
8026 cli_posix_rmdir(cli1, dname);
8027 cli_setatr(cli1, fname_windows, 0, 0);
8028 cli_posix_unlink(cli1, fname_windows);
8030 if (!torture_close_connection(cli1)) {
8038 Test POSIX and Windows ACLs are rejected on symlinks.
8040 static bool run_acl_symlink_test(int dummy)
8042 static struct cli_state *cli;
8043 const char *fname = "posix_file";
8044 const char *sname = "posix_symlink";
8045 uint16_t fnum = (uint16_t)-1;
8046 bool correct = false;
8048 char *posix_acl = NULL;
8049 size_t posix_acl_len = 0;
8050 char *posix_acl_sym = NULL;
8051 size_t posix_acl_len_sym = 0;
8052 struct security_descriptor *sd = NULL;
8053 TALLOC_CTX *frame = NULL;
8055 frame = talloc_stackframe();
8057 printf("Starting acl symlink test\n");
8059 if (!torture_open_connection(&cli, 0)) {
8064 smbXcli_conn_set_sockopt(cli->conn, sockops);
8066 status = torture_setup_unix_extensions(cli);
8067 if (!NT_STATUS_IS_OK(status)) {
8072 cli_setatr(cli, fname, 0, 0);
8073 cli_posix_unlink(cli, fname);
8074 cli_setatr(cli, sname, 0, 0);
8075 cli_posix_unlink(cli, sname);
8077 status = cli_ntcreate(cli,
8080 READ_CONTROL_ACCESS,
8082 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
8089 if (!NT_STATUS_IS_OK(status)) {
8090 printf("cli_ntcreate of %s failed (%s)\n",
8096 /* Get the Windows ACL on the file. */
8097 status = cli_query_secdesc(cli,
8101 if (!NT_STATUS_IS_OK(status)) {
8102 printf("cli_query_secdesc failed (%s)\n",
8107 /* Get the POSIX ACL on the file. */
8108 status = cli_posix_getacl(cli,
8114 if (!NT_STATUS_IS_OK(status)) {
8115 printf("cli_posix_getacl failed (%s)\n",
8120 status = cli_close(cli, fnum);
8121 if (!NT_STATUS_IS_OK(status)) {
8122 printf("close failed (%s)\n", nt_errstr(status));
8125 fnum = (uint16_t)-1;
8127 /* Now create a symlink. */
8128 status = cli_posix_symlink(cli, fname, sname);
8129 if (!NT_STATUS_IS_OK(status)) {
8130 printf("cli_posix_symlink of %s -> %s failed (%s)\n",
8137 /* Open a handle on the symlink for SD set/get should fail. */
8138 status = cli_ntcreate(cli,
8141 READ_CONTROL_ACCESS|SEC_STD_WRITE_DAC,
8143 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
8150 if (NT_STATUS_IS_OK(status)) {
8151 printf("Symlink open for getsd/setsd of %s "
8152 "succeeded (should fail)\n",
8157 /* Try a stat-open on the symlink, should also fail. */
8158 status = cli_ntcreate(cli,
8161 FILE_READ_ATTRIBUTES|FILE_WRITE_ATTRIBUTES,
8163 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
8170 if (NT_STATUS_IS_OK(status)) {
8171 printf("Stat-open of symlink succeeded (should fail)\n");
8175 /* Get the POSIX ACL on the symlink pathname. Should fail. */
8176 status = cli_posix_getacl(cli,
8182 if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
8183 printf("cli_posix_getacl on a symlink gave %s. "
8184 "Should be NT_STATUS_ACCESS_DENIED.\n",
8189 /* Set the POSIX ACL on the symlink pathname. Should fail. */
8190 status = cli_posix_setacl(cli,
8195 if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
8196 printf("cli_posix_setacl on a symlink gave %s. "
8197 "Should be NT_STATUS_ACCESS_DENIED.\n",
8202 printf("ACL symlink test passed\n");
8207 if (fnum != (uint16_t)-1) {
8208 cli_close(cli, fnum);
8209 fnum = (uint16_t)-1;
8212 cli_setatr(cli, sname, 0, 0);
8213 cli_posix_unlink(cli, sname);
8214 cli_setatr(cli, fname, 0, 0);
8215 cli_posix_unlink(cli, fname);
8217 if (!torture_close_connection(cli)) {
8226 Test POSIX can delete a file containing streams.
8228 static bool run_posix_stream_delete(int dummy)
8230 struct cli_state *cli1 = NULL;
8231 struct cli_state *cli2 = NULL;
8232 const char *fname = "streamfile";
8233 const char *stream_fname = "streamfile:Zone.Identifier:$DATA";
8234 uint16_t fnum1 = (uint16_t)-1;
8235 bool correct = false;
8237 TALLOC_CTX *frame = NULL;
8239 frame = talloc_stackframe();
8241 printf("Starting POSIX stream delete test\n");
8243 if (!torture_open_connection(&cli1, 0) ||
8244 !torture_open_connection(&cli2, 1)) {
8249 smbXcli_conn_set_sockopt(cli1->conn, sockops);
8250 smbXcli_conn_set_sockopt(cli2->conn, sockops);
8252 status = torture_setup_unix_extensions(cli2);
8253 if (!NT_STATUS_IS_OK(status)) {
8257 cli_setatr(cli1, fname, 0, 0);
8258 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
8260 /* Create the file. */
8261 status = cli_ntcreate(cli1,
8264 READ_CONTROL_ACCESS,
8266 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
8273 if (!NT_STATUS_IS_OK(status)) {
8274 printf("cli_ntcreate of %s failed (%s)\n",
8280 status = cli_close(cli1, fnum1);
8281 if (!NT_STATUS_IS_OK(status)) {
8282 printf("cli_close of %s failed (%s)\n",
8287 fnum1 = (uint16_t)-1;
8289 /* Now create the stream. */
8290 status = cli_ntcreate(cli1,
8295 FILE_SHARE_READ|FILE_SHARE_WRITE,
8302 if (!NT_STATUS_IS_OK(status)) {
8303 printf("cli_ntcreate of %s failed (%s)\n",
8309 /* Leave the stream handle open... */
8311 /* POSIX unlink should fail. */
8312 status = cli_posix_unlink(cli2, fname);
8313 if (NT_STATUS_IS_OK(status)) {
8314 printf("cli_posix_unlink of %s succeeded, should have failed\n",
8319 if (!NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
8320 printf("cli_posix_unlink of %s failed with (%s) "
8321 "should have been NT_STATUS_SHARING_VIOLATION\n",
8327 /* Close the stream handle. */
8328 status = cli_close(cli1, fnum1);
8329 if (!NT_STATUS_IS_OK(status)) {
8330 printf("cli_close of %s failed (%s)\n",
8335 fnum1 = (uint16_t)-1;
8337 /* POSIX unlink after stream handle closed should succeed. */
8338 status = cli_posix_unlink(cli2, fname);
8339 if (!NT_STATUS_IS_OK(status)) {
8340 printf("cli_posix_unlink of %s failed (%s)\n",
8346 printf("POSIX stream delete test passed\n");
8351 if (fnum1 != (uint16_t)-1) {
8352 cli_close(cli1, fnum1);
8353 fnum1 = (uint16_t)-1;
8356 cli_setatr(cli1, fname, 0, 0);
8357 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
8359 if (!torture_close_connection(cli1)) {
8362 if (!torture_close_connection(cli2)) {
8371 Test setting EA's are rejected on symlinks.
8373 static bool run_ea_symlink_test(int dummy)
8375 static struct cli_state *cli;
8376 const char *fname = "posix_file_ea";
8377 const char *sname = "posix_symlink_ea";
8378 const char *ea_name = "testea_name";
8379 const char *ea_value = "testea_value";
8380 uint16_t fnum = (uint16_t)-1;
8381 bool correct = false;
8384 struct ea_struct *eas = NULL;
8385 TALLOC_CTX *frame = NULL;
8387 frame = talloc_stackframe();
8389 printf("Starting EA symlink test\n");
8391 if (!torture_open_connection(&cli, 0)) {
8396 smbXcli_conn_set_sockopt(cli->conn, sockops);
8398 status = torture_setup_unix_extensions(cli);
8399 if (!NT_STATUS_IS_OK(status)) {
8404 cli_setatr(cli, fname, 0, 0);
8405 cli_posix_unlink(cli, fname);
8406 cli_setatr(cli, sname, 0, 0);
8407 cli_posix_unlink(cli, sname);
8409 status = cli_ntcreate(cli,
8412 READ_CONTROL_ACCESS,
8414 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
8421 if (!NT_STATUS_IS_OK(status)) {
8422 printf("cli_ntcreate of %s failed (%s)\n",
8428 status = cli_close(cli, fnum);
8429 if (!NT_STATUS_IS_OK(status)) {
8430 printf("close failed (%s)\n",
8434 fnum = (uint16_t)-1;
8436 /* Set an EA on the path. */
8437 status = cli_set_ea_path(cli,
8441 strlen(ea_value)+1);
8443 if (!NT_STATUS_IS_OK(status)) {
8444 printf("cli_set_ea_path failed (%s)\n",
8449 /* Now create a symlink. */
8450 status = cli_posix_symlink(cli, fname, sname);
8451 if (!NT_STATUS_IS_OK(status)) {
8452 printf("cli_posix_symlink of %s -> %s failed (%s)\n",
8459 /* Get the EA list on the path. Should return value set. */
8460 status = cli_get_ea_list_path(cli,
8466 if (!NT_STATUS_IS_OK(status)) {
8467 printf("cli_get_ea_list_path failed (%s)\n",
8472 /* Ensure the EA we set is there. */
8473 for (i=0; i<num_eas; i++) {
8474 if (strcmp(eas[i].name, ea_name) == 0 &&
8475 eas[i].value.length == strlen(ea_value)+1 &&
8476 memcmp(eas[i].value.data,
8478 eas[i].value.length) == 0) {
8484 printf("Didn't find EA on pathname %s\n",
8492 /* Get the EA list on the symlink. Should return empty list. */
8493 status = cli_get_ea_list_path(cli,
8499 if (!NT_STATUS_IS_OK(status)) {
8500 printf("cli_get_ea_list_path failed (%s)\n",
8506 printf("cli_get_ea_list_path failed (%s)\n",
8511 /* Set an EA on the symlink. Should fail. */
8512 status = cli_set_ea_path(cli,
8516 strlen(ea_value)+1);
8518 if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
8519 printf("cli_set_ea_path on a symlink gave %s. "
8520 "Should be NT_STATUS_ACCESS_DENIED.\n",
8525 printf("EA symlink test passed\n");
8530 if (fnum != (uint16_t)-1) {
8531 cli_close(cli, fnum);
8532 fnum = (uint16_t)-1;
8535 cli_setatr(cli, sname, 0, 0);
8536 cli_posix_unlink(cli, sname);
8537 cli_setatr(cli, fname, 0, 0);
8538 cli_posix_unlink(cli, fname);
8540 if (!torture_close_connection(cli)) {
8549 Test POSIX locks are OFD-locks.
8551 static bool run_posix_ofd_lock_test(int dummy)
8553 static struct cli_state *cli;
8554 const char *fname = "posix_file";
8555 uint16_t fnum1 = (uint16_t)-1;
8556 uint16_t fnum2 = (uint16_t)-1;
8557 bool correct = false;
8559 TALLOC_CTX *frame = NULL;
8561 frame = talloc_stackframe();
8563 printf("Starting POSIX ofd-lock test\n");
8565 if (!torture_open_connection(&cli, 0)) {
8570 smbXcli_conn_set_sockopt(cli->conn, sockops);
8572 status = torture_setup_unix_extensions(cli);
8573 if (!NT_STATUS_IS_OK(status)) {
8578 cli_setatr(cli, fname, 0, 0);
8579 cli_posix_unlink(cli, fname);
8581 /* Open the file twice. */
8582 status = cli_posix_open(cli, fname, O_RDWR|O_CREAT|O_EXCL,
8584 if (!NT_STATUS_IS_OK(status)) {
8585 printf("First POSIX open of %s failed\n", fname);
8589 status = cli_posix_open(cli, fname, O_RDWR, 0, &fnum2);
8590 if (!NT_STATUS_IS_OK(status)) {
8591 printf("First POSIX open of %s failed\n", fname);
8595 /* Set a 0-50 lock on fnum1. */
8596 status = cli_posix_lock(cli, fnum1, 0, 50, false, WRITE_LOCK);
8597 if (!NT_STATUS_IS_OK(status)) {
8598 printf("POSIX lock (1) failed %s\n", nt_errstr(status));
8602 /* Set a 60-100 lock on fnum2. */
8603 status = cli_posix_lock(cli, fnum2, 60, 100, false, WRITE_LOCK);
8604 if (!NT_STATUS_IS_OK(status)) {
8605 printf("POSIX lock (2) failed %s\n", nt_errstr(status));
8609 /* close fnum1 - 0-50 lock should go away. */
8610 status = cli_close(cli, fnum1);
8611 if (!NT_STATUS_IS_OK(status)) {
8612 printf("close failed (%s)\n",
8616 fnum1 = (uint16_t)-1;
8618 /* Change the lock context. */
8619 cli_setpid(cli, cli_getpid(cli) + 1);
8621 /* Re-open fnum1. */
8622 status = cli_posix_open(cli, fname, O_RDWR, 0, &fnum1);
8623 if (!NT_STATUS_IS_OK(status)) {
8624 printf("Third POSIX open of %s failed\n", fname);
8628 /* 60-100 lock should still be there. */
8629 status = cli_posix_lock(cli, fnum1, 60, 100, false, WRITE_LOCK);
8630 if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
8631 printf("POSIX lock 60-100 not there %s\n", nt_errstr(status));
8635 /* 0-50 lock should be gone. */
8636 status = cli_posix_lock(cli, fnum1, 0, 50, false, WRITE_LOCK);
8637 if (!NT_STATUS_IS_OK(status)) {
8638 printf("POSIX lock 0-50 failed %s\n", nt_errstr(status));
8642 printf("POSIX OFD lock test passed\n");
8647 if (fnum1 != (uint16_t)-1) {
8648 cli_close(cli, fnum1);
8649 fnum1 = (uint16_t)-1;
8651 if (fnum2 != (uint16_t)-1) {
8652 cli_close(cli, fnum2);
8653 fnum2 = (uint16_t)-1;
8656 cli_setatr(cli, fname, 0, 0);
8657 cli_posix_unlink(cli, fname);
8659 if (!torture_close_connection(cli)) {
8667 struct posix_blocking_state {
8668 struct tevent_context *ev;
8669 struct cli_state *cli1;
8671 struct cli_state *cli2;
8677 static void posix_blocking_locked(struct tevent_req *subreq);
8678 static void posix_blocking_gotblocked(struct tevent_req *subreq);
8679 static void posix_blocking_gotecho(struct tevent_req *subreq);
8680 static void posix_blocking_unlocked(struct tevent_req *subreq);
8682 static struct tevent_req *posix_blocking_send(
8683 TALLOC_CTX *mem_ctx,
8684 struct tevent_context *ev,
8685 struct cli_state *cli1,
8687 struct cli_state *cli2,
8690 struct tevent_req *req = NULL, *subreq = NULL;
8691 struct posix_blocking_state *state = NULL;
8693 req = tevent_req_create(mem_ctx, &state, struct posix_blocking_state);
8699 state->fnum1 = fnum1;
8701 state->fnum2 = fnum2;
8703 subreq = cli_posix_lock_send(
8712 if (tevent_req_nomem(subreq, req)) {
8713 return tevent_req_post(req, ev);
8715 tevent_req_set_callback(subreq, posix_blocking_locked, req);
8719 static void posix_blocking_locked(struct tevent_req *subreq)
8721 struct tevent_req *req = tevent_req_callback_data(
8722 subreq, struct tevent_req);
8723 struct posix_blocking_state *state = tevent_req_data(
8724 req, struct posix_blocking_state);
8727 status = cli_posix_lock_recv(subreq);
8728 TALLOC_FREE(subreq);
8729 if (tevent_req_nterror(req, status)) {
8733 subreq = cli_posix_lock_send(
8742 if (tevent_req_nomem(subreq, req)) {
8745 tevent_req_set_callback(subreq, posix_blocking_gotblocked, req);
8747 /* Make sure the blocking request is delivered */
8748 subreq = cli_echo_send(
8753 (DATA_BLOB) { .data = (uint8_t *)state, .length = 1 });
8754 if (tevent_req_nomem(subreq, req)) {
8757 tevent_req_set_callback(subreq, posix_blocking_gotecho, req);
8760 static void posix_blocking_gotblocked(struct tevent_req *subreq)
8762 struct tevent_req *req = tevent_req_callback_data(
8763 subreq, struct tevent_req);
8764 struct posix_blocking_state *state = tevent_req_data(
8765 req, struct posix_blocking_state);
8768 status = cli_posix_lock_recv(subreq);
8769 TALLOC_FREE(subreq);
8770 if (tevent_req_nterror(req, status)) {
8773 if (!state->gotecho) {
8774 printf("blocked req got through before echo\n");
8775 tevent_req_nterror(req, NT_STATUS_INVALID_LOCK_SEQUENCE);
8778 tevent_req_done(req);
8781 static void posix_blocking_gotecho(struct tevent_req *subreq)
8783 struct tevent_req *req = tevent_req_callback_data(
8784 subreq, struct tevent_req);
8785 struct posix_blocking_state *state = tevent_req_data(
8786 req, struct posix_blocking_state);
8789 status = cli_echo_recv(subreq);
8790 TALLOC_FREE(subreq);
8791 if (tevent_req_nterror(req, status)) {
8794 if (state->gotblocked) {
8795 printf("blocked req got through before echo\n");
8796 tevent_req_nterror(req, NT_STATUS_INVALID_LOCK_SEQUENCE);
8799 state->gotecho = true;
8801 subreq = cli_posix_lock_send(
8810 if (tevent_req_nomem(subreq, req)) {
8813 tevent_req_set_callback(subreq, posix_blocking_unlocked, req);
8816 static void posix_blocking_unlocked(struct tevent_req *subreq)
8818 struct tevent_req *req = tevent_req_callback_data(
8819 subreq, struct tevent_req);
8822 status = cli_posix_lock_recv(subreq);
8823 TALLOC_FREE(subreq);
8824 if (tevent_req_nterror(req, status)) {
8827 /* tevent_req_done in posix_blocking_gotlocked */
8830 static NTSTATUS posix_blocking_recv(struct tevent_req *req)
8832 return tevent_req_simple_recv_ntstatus(req);
8835 static bool run_posix_blocking_lock(int dummy)
8837 struct tevent_context *ev = NULL;
8838 struct cli_state *cli1 = NULL, *cli2 = NULL;
8839 const char *fname = "posix_blocking";
8840 uint16_t fnum1 = UINT16_MAX, fnum2 = UINT16_MAX;
8841 struct tevent_req *req = NULL;
8846 printf("Starting posix blocking lock test\n");
8848 ev = samba_tevent_context_init(NULL);
8853 ok = torture_open_connection(&cli1, 0);
8857 ok = torture_open_connection(&cli2, 0);
8862 smbXcli_conn_set_sockopt(cli1->conn, sockops);
8864 status = torture_setup_unix_extensions(cli1);
8865 if (!NT_STATUS_IS_OK(status)) {
8869 cli_setatr(cli1, fname, 0, 0);
8870 cli_posix_unlink(cli1, fname);
8872 status = cli_posix_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL,
8874 if (!NT_STATUS_IS_OK(status)) {
8875 printf("First POSIX open of %s failed: %s\n",
8881 status = cli_posix_open(cli2, fname, O_RDWR, 0600, &fnum2);
8882 if (!NT_STATUS_IS_OK(status)) {
8883 printf("Second POSIX open of %s failed: %s\n",
8889 req = posix_blocking_send(ev, ev, cli1, fnum1, cli2, fnum2);
8891 printf("cli_posix_blocking failed\n");
8895 ok = tevent_req_poll_ntstatus(req, ev, &status);
8897 printf("tevent_req_poll_ntstatus failed: %s\n",
8901 status = posix_blocking_recv(req);
8903 if (!NT_STATUS_IS_OK(status)) {
8904 printf("posix_blocking_recv returned %s\n",
8912 if (fnum1 != UINT16_MAX) {
8913 cli_close(cli1, fnum1);
8916 if (fnum2 != UINT16_MAX) {
8917 cli_close(cli2, fnum2);
8922 cli_setatr(cli1, fname, 0, 0);
8923 cli_posix_unlink(cli1, fname);
8929 ok &= torture_close_connection(cli1);
8933 ok &= torture_close_connection(cli2);
8945 Test POSIX mkdir is case-sensitive.
8947 static bool run_posix_mkdir_test(int dummy)
8949 static struct cli_state *cli;
8950 const char *fname_foo = "POSIX_foo";
8951 const char *fname_foo_Foo = "POSIX_foo/Foo";
8952 const char *fname_foo_foo = "POSIX_foo/foo";
8953 const char *fname_Foo = "POSIX_Foo";
8954 const char *fname_Foo_Foo = "POSIX_Foo/Foo";
8955 const char *fname_Foo_foo = "POSIX_Foo/foo";
8956 bool correct = false;
8958 TALLOC_CTX *frame = NULL;
8959 uint16_t fnum = (uint16_t)-1;
8961 frame = talloc_stackframe();
8963 printf("Starting POSIX mkdir test\n");
8965 if (!torture_open_connection(&cli, 0)) {
8970 smbXcli_conn_set_sockopt(cli->conn, sockops);
8972 status = torture_setup_unix_extensions(cli);
8973 if (!NT_STATUS_IS_OK(status)) {
8978 cli_posix_rmdir(cli, fname_foo_foo);
8979 cli_posix_rmdir(cli, fname_foo_Foo);
8980 cli_posix_rmdir(cli, fname_foo);
8982 cli_posix_rmdir(cli, fname_Foo_foo);
8983 cli_posix_rmdir(cli, fname_Foo_Foo);
8984 cli_posix_rmdir(cli, fname_Foo);
8987 * Create a file POSIX_foo then try
8988 * and use it in a directory path by
8989 * doing mkdir POSIX_foo/bar.
8990 * The mkdir should fail with
8991 * NT_STATUS_OBJECT_PATH_NOT_FOUND
8994 status = cli_posix_open(cli,
8999 if (!NT_STATUS_IS_OK(status)) {
9000 printf("cli_posix_open of %s failed error %s\n",
9006 status = cli_posix_mkdir(cli, fname_foo_foo, 0777);
9007 if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_PATH_NOT_FOUND)) {
9008 printf("cli_posix_mkdir of %s should fail with "
9009 "NT_STATUS_OBJECT_PATH_NOT_FOUND got "
9016 status = cli_close(cli, fnum);
9017 if (!NT_STATUS_IS_OK(status)) {
9018 printf("cli_close failed %s\n", nt_errstr(status));
9021 fnum = (uint16_t)-1;
9023 status = cli_posix_unlink(cli, fname_foo);
9024 if (!NT_STATUS_IS_OK(status)) {
9025 printf("cli_posix_unlink of %s failed error %s\n",
9032 * Now we've deleted everything, posix_mkdir, posix_rmdir,
9033 * posix_open, posix_unlink, on
9034 * POSIX_foo/foo should return NT_STATUS_OBJECT_PATH_NOT_FOUND
9035 * not silently create POSIX_foo/foo.
9038 status = cli_posix_mkdir(cli, fname_foo_foo, 0777);
9039 if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_PATH_NOT_FOUND)) {
9040 printf("cli_posix_mkdir of %s should fail with "
9041 "NT_STATUS_OBJECT_PATH_NOT_FOUND got "
9048 status = cli_posix_rmdir(cli, fname_foo_foo);
9049 if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_PATH_NOT_FOUND)) {
9050 printf("cli_posix_rmdir of %s should fail with "
9051 "NT_STATUS_OBJECT_PATH_NOT_FOUND got "
9058 status = cli_posix_open(cli,
9063 if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_PATH_NOT_FOUND)) {
9064 printf("cli_posix_open of %s should fail with "
9065 "NT_STATUS_OBJECT_PATH_NOT_FOUND got "
9072 status = cli_posix_unlink(cli, fname_foo_foo);
9073 if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_PATH_NOT_FOUND)) {
9074 printf("cli_posix_unlink of %s should fail with "
9075 "NT_STATUS_OBJECT_PATH_NOT_FOUND got "
9082 status = cli_posix_mkdir(cli, fname_foo, 0777);
9083 if (!NT_STATUS_IS_OK(status)) {
9084 printf("cli_posix_mkdir of %s failed\n", fname_foo);
9088 status = cli_posix_mkdir(cli, fname_Foo, 0777);
9089 if (!NT_STATUS_IS_OK(status)) {
9090 printf("cli_posix_mkdir of %s failed\n", fname_Foo);
9094 status = cli_posix_mkdir(cli, fname_foo_foo, 0777);
9095 if (!NT_STATUS_IS_OK(status)) {
9096 printf("cli_posix_mkdir of %s failed\n", fname_foo_foo);
9100 status = cli_posix_mkdir(cli, fname_foo_Foo, 0777);
9101 if (!NT_STATUS_IS_OK(status)) {
9102 printf("cli_posix_mkdir of %s failed\n", fname_foo_Foo);
9106 status = cli_posix_mkdir(cli, fname_Foo_foo, 0777);
9107 if (!NT_STATUS_IS_OK(status)) {
9108 printf("cli_posix_mkdir of %s failed\n", fname_Foo_foo);
9112 status = cli_posix_mkdir(cli, fname_Foo_Foo, 0777);
9113 if (!NT_STATUS_IS_OK(status)) {
9114 printf("cli_posix_mkdir of %s failed\n", fname_Foo_Foo);
9118 printf("POSIX mkdir test passed\n");
9123 if (fnum != (uint16_t)-1) {
9124 cli_close(cli, fnum);
9125 fnum = (uint16_t)-1;
9128 cli_posix_rmdir(cli, fname_foo_foo);
9129 cli_posix_rmdir(cli, fname_foo_Foo);
9130 cli_posix_rmdir(cli, fname_foo);
9132 cli_posix_rmdir(cli, fname_Foo_foo);
9133 cli_posix_rmdir(cli, fname_Foo_Foo);
9134 cli_posix_rmdir(cli, fname_Foo);
9136 if (!torture_close_connection(cli)) {
9144 struct posix_acl_oplock_state {
9145 struct tevent_context *ev;
9146 struct cli_state *cli;
9152 static void posix_acl_oplock_got_break(struct tevent_req *req)
9154 struct posix_acl_oplock_state *state = tevent_req_callback_data(
9155 req, struct posix_acl_oplock_state);
9160 status = cli_smb_oplock_break_waiter_recv(req, &fnum, &level);
9162 if (!NT_STATUS_IS_OK(status)) {
9163 printf("cli_smb_oplock_break_waiter_recv returned %s\n",
9167 *state->got_break = true;
9169 req = cli_oplock_ack_send(state, state->ev, state->cli, fnum,
9172 printf("cli_oplock_ack_send failed\n");
9177 static void posix_acl_oplock_got_acl(struct tevent_req *req)
9179 struct posix_acl_oplock_state *state = tevent_req_callback_data(
9180 req, struct posix_acl_oplock_state);
9181 size_t ret_size = 0;
9182 char *ret_data = NULL;
9184 state->status = cli_posix_getacl_recv(req,
9189 if (!NT_STATUS_IS_OK(state->status)) {
9190 printf("cli_posix_getacl_recv returned %s\n",
9191 nt_errstr(state->status));
9193 *state->acl_ret = true;
9196 static bool run_posix_acl_oplock_test(int dummy)
9198 struct tevent_context *ev;
9199 struct cli_state *cli1, *cli2;
9200 struct tevent_req *oplock_req, *getacl_req;
9201 const char *fname = "posix_acl_oplock";
9203 int saved_use_oplocks = use_oplocks;
9205 bool correct = true;
9206 bool got_break = false;
9207 bool acl_ret = false;
9209 struct posix_acl_oplock_state *state;
9211 printf("starting posix_acl_oplock test\n");
9213 if (!torture_open_connection(&cli1, 0)) {
9214 use_level_II_oplocks = false;
9215 use_oplocks = saved_use_oplocks;
9219 if (!torture_open_connection(&cli2, 1)) {
9220 use_level_II_oplocks = false;
9221 use_oplocks = saved_use_oplocks;
9225 /* Setup posix on cli2 only. */
9226 status = torture_setup_unix_extensions(cli2);
9227 if (!NT_STATUS_IS_OK(status)) {
9231 smbXcli_conn_set_sockopt(cli1->conn, sockops);
9232 smbXcli_conn_set_sockopt(cli2->conn, sockops);
9234 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
9236 /* Create the file on the Windows connection. */
9237 status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
9239 if (!NT_STATUS_IS_OK(status)) {
9240 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
9244 status = cli_close(cli1, fnum);
9245 if (!NT_STATUS_IS_OK(status)) {
9246 printf("close1 failed (%s)\n", nt_errstr(status));
9250 cli1->use_oplocks = true;
9252 /* Open with oplock. */
9253 status = cli_ntcreate(cli1,
9257 FILE_ATTRIBUTE_NORMAL,
9258 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
9265 if (!NT_STATUS_IS_OK(status)) {
9266 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
9270 ev = samba_tevent_context_init(talloc_tos());
9272 printf("tevent_context_init failed\n");
9276 state = talloc_zero(ev, struct posix_acl_oplock_state);
9277 if (state == NULL) {
9278 printf("talloc failed\n");
9283 state->got_break = &got_break;
9284 state->acl_ret = &acl_ret;
9286 oplock_req = cli_smb_oplock_break_waiter_send(
9287 talloc_tos(), ev, cli1);
9288 if (oplock_req == NULL) {
9289 printf("cli_smb_oplock_break_waiter_send failed\n");
9292 tevent_req_set_callback(oplock_req, posix_acl_oplock_got_break, state);
9294 /* Get ACL on POSIX connection - should break oplock. */
9295 getacl_req = cli_posix_getacl_send(talloc_tos(),
9299 if (getacl_req == NULL) {
9300 printf("cli_posix_getacl_send failed\n");
9303 tevent_req_set_callback(getacl_req, posix_acl_oplock_got_acl, state);
9305 while (!got_break || !acl_ret) {
9307 ret = tevent_loop_once(ev);
9309 printf("tevent_loop_once failed: %s\n",
9315 if (!NT_STATUS_IS_OK(state->status)) {
9316 printf("getacl failed (%s)\n", nt_errstr(state->status));
9320 status = cli_close(cli1, fnum);
9321 if (!NT_STATUS_IS_OK(status)) {
9322 printf("close2 failed (%s)\n", nt_errstr(status));
9326 status = cli_unlink(cli1,
9328 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
9329 if (!NT_STATUS_IS_OK(status)) {
9330 printf("unlink failed (%s)\n", nt_errstr(status));
9334 if (!torture_close_connection(cli1)) {
9337 if (!torture_close_connection(cli2)) {
9345 printf("finished posix acl oplock test\n");
9350 static bool run_posix_acl_shareroot_test(int dummy)
9352 struct cli_state *cli;
9354 bool correct = false;
9355 char *posix_acl = NULL;
9356 size_t posix_acl_len = 0;
9357 uint16_t num_file_acls = 0;
9358 uint16_t num_dir_acls = 0;
9360 uint32_t expected_size = 0;
9361 bool got_user = false;
9362 bool got_group = false;
9363 bool got_other = false;
9364 TALLOC_CTX *frame = NULL;
9366 frame = talloc_stackframe();
9368 printf("starting posix_acl_shareroot test\n");
9370 if (!torture_open_connection(&cli, 0)) {
9375 smbXcli_conn_set_sockopt(cli->conn, sockops);
9377 status = torture_setup_unix_extensions(cli);
9378 if (!NT_STATUS_IS_OK(status)) {
9379 printf("Failed to setup unix extensions\n");
9383 /* Get the POSIX ACL on the root of the share. */
9384 status = cli_posix_getacl(cli,
9390 if (!NT_STATUS_IS_OK(status)) {
9391 printf("cli_posix_getacl of '.' failed (%s)\n",
9396 if (posix_acl_len < 6 ||
9397 SVAL(posix_acl,0) != SMB_POSIX_ACL_VERSION) {
9398 printf("getfacl ., unknown POSIX acl version %u.\n",
9399 (unsigned int)CVAL(posix_acl,0) );
9403 num_file_acls = SVAL(posix_acl,2);
9404 num_dir_acls = SVAL(posix_acl,4);
9405 expected_size = SMB_POSIX_ACL_HEADER_SIZE +
9406 SMB_POSIX_ACL_ENTRY_SIZE*
9407 (num_file_acls+num_dir_acls);
9409 if (posix_acl_len != expected_size) {
9410 printf("incorrect POSIX acl buffer size "
9411 "(should be %u, was %u).\n",
9412 (unsigned int)expected_size,
9413 (unsigned int)posix_acl_len);
9418 * We don't need to know what the ACL's are
9419 * we just need to know we have at least 3
9420 * file entries (u,g,o).
9423 for (i = 0; i < num_file_acls; i++) {
9424 unsigned char tagtype =
9426 SMB_POSIX_ACL_HEADER_SIZE+
9427 (i*SMB_POSIX_ACL_ENTRY_SIZE));
9430 case SMB_POSIX_ACL_USER_OBJ:
9433 case SMB_POSIX_ACL_GROUP_OBJ:
9436 case SMB_POSIX_ACL_OTHER:
9445 printf("Missing user entry\n");
9450 printf("Missing group entry\n");
9455 printf("Missing other entry\n");
9463 if (!torture_close_connection(cli)) {
9467 printf("finished posix acl shareroot test\n");
9473 static uint32_t open_attrs_table[] = {
9474 FILE_ATTRIBUTE_NORMAL,
9475 FILE_ATTRIBUTE_ARCHIVE,
9476 FILE_ATTRIBUTE_READONLY,
9477 FILE_ATTRIBUTE_HIDDEN,
9478 FILE_ATTRIBUTE_SYSTEM,
9480 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY,
9481 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN,
9482 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM,
9483 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN,
9484 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM,
9485 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM,
9487 FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN,
9488 FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM,
9489 FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM,
9490 FILE_ATTRIBUTE_HIDDEN,FILE_ATTRIBUTE_SYSTEM,
9493 struct trunc_open_results {
9496 uint32_t trunc_attr;
9497 uint32_t result_attr;
9500 static struct trunc_open_results attr_results[] = {
9501 { 0, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_ARCHIVE },
9502 { 1, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_ARCHIVE },
9503 { 2, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_READONLY, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY },
9504 { 16, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_ARCHIVE },
9505 { 17, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_ARCHIVE },
9506 { 18, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_READONLY, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY },
9507 { 51, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
9508 { 54, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
9509 { 56, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN },
9510 { 68, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
9511 { 71, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
9512 { 73, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM },
9513 { 99, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_HIDDEN,FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
9514 { 102, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
9515 { 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 },
9516 { 116, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
9517 { 119, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
9518 { 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 },
9519 { 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 },
9520 { 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 },
9521 { 227, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
9522 { 230, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
9523 { 232, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN },
9524 { 244, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
9525 { 247, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
9526 { 249, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM }
9529 static bool run_openattrtest(int dummy)
9531 static struct cli_state *cli1;
9532 const char *fname = "\\openattr.file";
9534 bool correct = True;
9536 unsigned int i, j, k, l;
9539 printf("starting open attr test\n");
9541 if (!torture_open_connection(&cli1, 0)) {
9545 smbXcli_conn_set_sockopt(cli1->conn, sockops);
9547 for (k = 0, i = 0; i < sizeof(open_attrs_table)/sizeof(uint32_t); i++) {
9548 cli_setatr(cli1, fname, 0, 0);
9549 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
9551 status = cli_ntcreate(cli1, fname, 0, FILE_WRITE_DATA,
9552 open_attrs_table[i], FILE_SHARE_NONE,
9553 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
9554 if (!NT_STATUS_IS_OK(status)) {
9555 printf("open %d (1) of %s failed (%s)\n", i, fname, nt_errstr(status));
9559 status = cli_close(cli1, fnum1);
9560 if (!NT_STATUS_IS_OK(status)) {
9561 printf("close %d (1) of %s failed (%s)\n", i, fname, nt_errstr(status));
9565 for (j = 0; j < sizeof(open_attrs_table)/sizeof(uint32_t); j++) {
9566 status = cli_ntcreate(cli1, fname, 0,
9567 FILE_READ_DATA|FILE_WRITE_DATA,
9568 open_attrs_table[j],
9569 FILE_SHARE_NONE, FILE_OVERWRITE,
9570 0, 0, &fnum1, NULL);
9571 if (!NT_STATUS_IS_OK(status)) {
9572 for (l = 0; l < sizeof(attr_results)/sizeof(struct trunc_open_results); l++) {
9573 if (attr_results[l].num == k) {
9574 printf("[%d] trunc open 0x%x -> 0x%x of %s failed - should have succeeded !(0x%x:%s)\n",
9575 k, open_attrs_table[i],
9576 open_attrs_table[j],
9577 fname, NT_STATUS_V(status), nt_errstr(status));
9582 if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
9583 printf("[%d] trunc open 0x%x -> 0x%x failed with wrong error code %s\n",
9584 k, open_attrs_table[i], open_attrs_table[j],
9589 printf("[%d] trunc open 0x%x -> 0x%x failed\n", k, open_attrs_table[i], open_attrs_table[j]);
9595 status = cli_close(cli1, fnum1);
9596 if (!NT_STATUS_IS_OK(status)) {
9597 printf("close %d (2) of %s failed (%s)\n", j, fname, nt_errstr(status));
9601 status = cli_getatr(cli1, fname, &attr, NULL, NULL);
9602 if (!NT_STATUS_IS_OK(status)) {
9603 printf("getatr(2) failed (%s)\n", nt_errstr(status));
9608 printf("[%d] getatr check [0x%x] trunc [0x%x] got attr 0x%x\n",
9609 k, open_attrs_table[i], open_attrs_table[j], attr );
9612 for (l = 0; l < sizeof(attr_results)/sizeof(struct trunc_open_results); l++) {
9613 if (attr_results[l].num == k) {
9614 if (attr != attr_results[l].result_attr ||
9615 open_attrs_table[i] != attr_results[l].init_attr ||
9616 open_attrs_table[j] != attr_results[l].trunc_attr) {
9617 printf("getatr check failed. [0x%x] trunc [0x%x] got attr 0x%x, should be 0x%x\n",
9618 open_attrs_table[i],
9619 open_attrs_table[j],
9621 attr_results[l].result_attr);
9631 cli_setatr(cli1, fname, 0, 0);
9632 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
9634 printf("open attr test %s.\n", correct ? "passed" : "failed");
9636 if (!torture_close_connection(cli1)) {
9642 static NTSTATUS list_fn(struct file_info *finfo,
9643 const char *name, void *state)
9645 int *matched = (int *)state;
9646 if (matched != NULL) {
9649 return NT_STATUS_OK;
9653 test directory listing speed
9655 static bool run_dirtest(int dummy)
9658 static struct cli_state *cli;
9660 struct timeval core_start;
9661 bool correct = True;
9664 printf("starting directory test\n");
9666 if (!torture_open_connection(&cli, 0)) {
9670 smbXcli_conn_set_sockopt(cli->conn, sockops);
9673 for (i=0;i<torture_numops;i++) {
9675 slprintf(fname, sizeof(fname), "\\%x", (int)random());
9676 if (!NT_STATUS_IS_OK(cli_openx(cli, fname, O_RDWR|O_CREAT, DENY_NONE, &fnum))) {
9677 fprintf(stderr,"Failed to open %s\n", fname);
9680 cli_close(cli, fnum);
9683 core_start = timeval_current();
9686 cli_list(cli, "a*.*", 0, list_fn, &matched);
9687 printf("Matched %d\n", matched);
9690 cli_list(cli, "b*.*", 0, list_fn, &matched);
9691 printf("Matched %d\n", matched);
9694 cli_list(cli, "xyzabc", 0, list_fn, &matched);
9695 printf("Matched %d\n", matched);
9697 printf("dirtest core %g seconds\n", timeval_elapsed(&core_start));
9700 for (i=0;i<torture_numops;i++) {
9702 slprintf(fname, sizeof(fname), "\\%x", (int)random());
9703 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
9706 if (!torture_close_connection(cli)) {
9710 printf("finished dirtest\n");
9715 static NTSTATUS del_fn(struct file_info *finfo, const char *mask,
9718 struct cli_state *pcli = (struct cli_state *)state;
9720 slprintf(fname, sizeof(fname), "\\LISTDIR\\%s", finfo->name);
9722 if (strcmp(finfo->name, ".") == 0 || strcmp(finfo->name, "..") == 0)
9723 return NT_STATUS_OK;
9725 if (finfo->attr & FILE_ATTRIBUTE_DIRECTORY) {
9726 if (!NT_STATUS_IS_OK(cli_rmdir(pcli, fname)))
9727 printf("del_fn: failed to rmdir %s\n,", fname );
9729 if (!NT_STATUS_IS_OK(cli_unlink(pcli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN)))
9730 printf("del_fn: failed to unlink %s\n,", fname );
9732 return NT_STATUS_OK;
9737 sees what IOCTLs are supported
9739 bool torture_ioctl_test(int dummy)
9741 static struct cli_state *cli;
9742 uint16_t device, function;
9744 const char *fname = "\\ioctl.dat";
9748 if (!torture_open_connection(&cli, 0)) {
9752 printf("starting ioctl test\n");
9754 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
9756 status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
9757 if (!NT_STATUS_IS_OK(status)) {
9758 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
9762 status = cli_raw_ioctl(cli, fnum, 0x2d0000 | (0x0420<<2), &blob);
9763 printf("ioctl device info: %s\n", nt_errstr(status));
9765 status = cli_raw_ioctl(cli, fnum, IOCTL_QUERY_JOB_INFO, &blob);
9766 printf("ioctl job info: %s\n", nt_errstr(status));
9768 for (device=0;device<0x100;device++) {
9769 printf("ioctl test with device = 0x%x\n", device);
9770 for (function=0;function<0x100;function++) {
9771 uint32_t code = (device<<16) | function;
9773 status = cli_raw_ioctl(cli, fnum, code, &blob);
9775 if (NT_STATUS_IS_OK(status)) {
9776 printf("ioctl 0x%x OK : %d bytes\n", (int)code,
9778 data_blob_free(&blob);
9783 if (!torture_close_connection(cli)) {
9792 tries varients of chkpath
9794 bool torture_chkpath_test(int dummy)
9796 static struct cli_state *cli;
9801 if (!torture_open_connection(&cli, 0)) {
9805 printf("starting chkpath test\n");
9807 /* cleanup from an old run */
9808 cli_rmdir(cli, "\\chkpath.dir\\dir2");
9809 cli_unlink(cli, "\\chkpath.dir\\*", FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
9810 cli_rmdir(cli, "\\chkpath.dir");
9812 status = cli_mkdir(cli, "\\chkpath.dir");
9813 if (!NT_STATUS_IS_OK(status)) {
9814 printf("mkdir1 failed : %s\n", nt_errstr(status));
9818 status = cli_mkdir(cli, "\\chkpath.dir\\dir2");
9819 if (!NT_STATUS_IS_OK(status)) {
9820 printf("mkdir2 failed : %s\n", nt_errstr(status));
9824 status = cli_openx(cli, "\\chkpath.dir\\foo.txt", O_RDWR|O_CREAT|O_EXCL,
9826 if (!NT_STATUS_IS_OK(status)) {
9827 printf("open1 failed (%s)\n", nt_errstr(status));
9830 cli_close(cli, fnum);
9832 status = cli_chkpath(cli, "\\chkpath.dir");
9833 if (!NT_STATUS_IS_OK(status)) {
9834 printf("chkpath1 failed: %s\n", nt_errstr(status));
9838 status = cli_chkpath(cli, "\\chkpath.dir\\dir2");
9839 if (!NT_STATUS_IS_OK(status)) {
9840 printf("chkpath2 failed: %s\n", nt_errstr(status));
9844 status = cli_chkpath(cli, "\\chkpath.dir\\foo.txt");
9845 if (!NT_STATUS_IS_OK(status)) {
9846 ret = check_error(__LINE__, status, ERRDOS, ERRbadpath,
9847 NT_STATUS_NOT_A_DIRECTORY);
9849 printf("* chkpath on a file should fail\n");
9853 status = cli_chkpath(cli, "\\chkpath.dir\\bar.txt");
9854 if (!NT_STATUS_IS_OK(status)) {
9855 ret = check_error(__LINE__, status, ERRDOS, ERRbadfile,
9856 NT_STATUS_OBJECT_NAME_NOT_FOUND);
9858 printf("* chkpath on a non existent file should fail\n");
9862 status = cli_chkpath(cli, "\\chkpath.dir\\dirxx\\bar.txt");
9863 if (!NT_STATUS_IS_OK(status)) {
9864 ret = check_error(__LINE__, status, ERRDOS, ERRbadpath,
9865 NT_STATUS_OBJECT_PATH_NOT_FOUND);
9867 printf("* chkpath on a non existent component should fail\n");
9871 cli_rmdir(cli, "\\chkpath.dir\\dir2");
9872 cli_unlink(cli, "\\chkpath.dir\\*", FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
9873 cli_rmdir(cli, "\\chkpath.dir");
9875 if (!torture_close_connection(cli)) {
9882 static bool run_eatest(int dummy)
9884 static struct cli_state *cli;
9885 const char *fname = "\\eatest.txt";
9886 bool correct = True;
9890 struct ea_struct *ea_list = NULL;
9891 TALLOC_CTX *mem_ctx = talloc_init("eatest");
9894 printf("starting eatest\n");
9896 if (!torture_open_connection(&cli, 0)) {
9897 talloc_destroy(mem_ctx);
9901 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
9903 status = cli_ntcreate(cli, fname, 0,
9904 FIRST_DESIRED_ACCESS, FILE_ATTRIBUTE_ARCHIVE,
9905 FILE_SHARE_NONE, FILE_OVERWRITE_IF,
9906 0x4044, 0, &fnum, NULL);
9907 if (!NT_STATUS_IS_OK(status)) {
9908 printf("open failed - %s\n", nt_errstr(status));
9909 talloc_destroy(mem_ctx);
9913 for (i = 0; i < 10; i++) {
9914 fstring ea_name, ea_val;
9916 slprintf(ea_name, sizeof(ea_name), "EA_%d", i);
9917 memset(ea_val, (char)i+1, i+1);
9918 status = cli_set_ea_fnum(cli, fnum, ea_name, ea_val, i+1);
9919 if (!NT_STATUS_IS_OK(status)) {
9920 printf("ea_set of name %s failed - %s\n", ea_name,
9922 talloc_destroy(mem_ctx);
9927 cli_close(cli, fnum);
9928 for (i = 0; i < 10; i++) {
9929 fstring ea_name, ea_val;
9931 slprintf(ea_name, sizeof(ea_name), "EA_%d", i+10);
9932 memset(ea_val, (char)i+1, i+1);
9933 status = cli_set_ea_path(cli, fname, ea_name, ea_val, i+1);
9934 if (!NT_STATUS_IS_OK(status)) {
9935 printf("ea_set of name %s failed - %s\n", ea_name,
9937 talloc_destroy(mem_ctx);
9942 status = cli_get_ea_list_path(cli, fname, mem_ctx, &num_eas, &ea_list);
9943 if (!NT_STATUS_IS_OK(status)) {
9944 printf("ea_get list failed - %s\n", nt_errstr(status));
9948 printf("num_eas = %d\n", (int)num_eas);
9950 if (num_eas != 20) {
9951 printf("Should be 20 EA's stored... failing.\n");
9955 for (i = 0; i < num_eas; i++) {
9956 printf("%d: ea_name = %s. Val = ", i, ea_list[i].name);
9957 dump_data(0, ea_list[i].value.data,
9958 ea_list[i].value.length);
9961 /* Setting EA's to zero length deletes them. Test this */
9962 printf("Now deleting all EA's - case indepenent....\n");
9965 cli_set_ea_path(cli, fname, "", "", 0);
9967 for (i = 0; i < 20; i++) {
9969 slprintf(ea_name, sizeof(ea_name), "ea_%d", i);
9970 status = cli_set_ea_path(cli, fname, ea_name, "", 0);
9971 if (!NT_STATUS_IS_OK(status)) {
9972 printf("ea_set of name %s failed - %s\n", ea_name,
9974 talloc_destroy(mem_ctx);
9980 status = cli_get_ea_list_path(cli, fname, mem_ctx, &num_eas, &ea_list);
9981 if (!NT_STATUS_IS_OK(status)) {
9982 printf("ea_get list failed - %s\n", nt_errstr(status));
9986 printf("num_eas = %d\n", (int)num_eas);
9987 for (i = 0; i < num_eas; i++) {
9988 printf("%d: ea_name = %s. Val = ", i, ea_list[i].name);
9989 dump_data(0, ea_list[i].value.data,
9990 ea_list[i].value.length);
9994 printf("deleting EA's failed.\n");
9998 /* Try and delete a non existent EA. */
9999 status = cli_set_ea_path(cli, fname, "foo", "", 0);
10000 if (!NT_STATUS_IS_OK(status)) {
10001 printf("deleting non-existent EA 'foo' should succeed. %s\n",
10002 nt_errstr(status));
10006 talloc_destroy(mem_ctx);
10007 if (!torture_close_connection(cli)) {
10014 static bool run_dirtest1(int dummy)
10017 static struct cli_state *cli;
10020 bool correct = True;
10022 printf("starting directory test\n");
10024 if (!torture_open_connection(&cli, 0)) {
10028 smbXcli_conn_set_sockopt(cli->conn, sockops);
10030 cli_list(cli, "\\LISTDIR\\*", 0, del_fn, cli);
10031 cli_list(cli, "\\LISTDIR\\*", FILE_ATTRIBUTE_DIRECTORY, del_fn, cli);
10032 cli_rmdir(cli, "\\LISTDIR");
10033 cli_mkdir(cli, "\\LISTDIR");
10035 /* Create 1000 files and 1000 directories. */
10036 for (i=0;i<1000;i++) {
10038 slprintf(fname, sizeof(fname), "\\LISTDIR\\f%d", i);
10039 if (!NT_STATUS_IS_OK(cli_ntcreate(cli, fname, 0, GENERIC_ALL_ACCESS, FILE_ATTRIBUTE_ARCHIVE,
10040 FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OVERWRITE_IF,
10041 0, 0, &fnum, NULL))) {
10042 fprintf(stderr,"Failed to open %s\n", fname);
10045 cli_close(cli, fnum);
10047 for (i=0;i<1000;i++) {
10049 slprintf(fname, sizeof(fname), "\\LISTDIR\\d%d", i);
10050 if (!NT_STATUS_IS_OK(cli_mkdir(cli, fname))) {
10051 fprintf(stderr,"Failed to open %s\n", fname);
10056 /* Now ensure that doing an old list sees both files and directories. */
10058 cli_list_old(cli, "\\LISTDIR\\*", FILE_ATTRIBUTE_DIRECTORY, list_fn, &num_seen);
10059 printf("num_seen = %d\n", num_seen );
10060 /* We should see 100 files + 1000 directories + . and .. */
10061 if (num_seen != 2002)
10064 /* Ensure if we have the "must have" bits we only see the
10065 * relevent entries.
10068 cli_list_old(cli, "\\LISTDIR\\*", (FILE_ATTRIBUTE_DIRECTORY<<8)|FILE_ATTRIBUTE_DIRECTORY, list_fn, &num_seen);
10069 printf("num_seen = %d\n", num_seen );
10070 if (num_seen != 1002)
10074 cli_list_old(cli, "\\LISTDIR\\*", (FILE_ATTRIBUTE_ARCHIVE<<8)|FILE_ATTRIBUTE_DIRECTORY, list_fn, &num_seen);
10075 printf("num_seen = %d\n", num_seen );
10076 if (num_seen != 1000)
10079 /* Delete everything. */
10080 cli_list(cli, "\\LISTDIR\\*", 0, del_fn, cli);
10081 cli_list(cli, "\\LISTDIR\\*", FILE_ATTRIBUTE_DIRECTORY, del_fn, cli);
10082 cli_rmdir(cli, "\\LISTDIR");
10085 printf("Matched %d\n", cli_list(cli, "a*.*", 0, list_fn, NULL));
10086 printf("Matched %d\n", cli_list(cli, "b*.*", 0, list_fn, NULL));
10087 printf("Matched %d\n", cli_list(cli, "xyzabc", 0, list_fn, NULL));
10090 if (!torture_close_connection(cli)) {
10094 printf("finished dirtest1\n");
10099 static bool run_error_map_extract(int dummy) {
10101 static struct cli_state *c_dos;
10102 static struct cli_state *c_nt;
10110 NTSTATUS nt_status;
10114 /* NT-Error connection */
10116 disable_spnego = true;
10117 if (!(c_nt = open_nbt_connection())) {
10118 disable_spnego = false;
10121 disable_spnego = false;
10123 status = smbXcli_negprot(c_nt->conn, c_nt->timeout, PROTOCOL_CORE,
10126 if (!NT_STATUS_IS_OK(status)) {
10127 printf("%s rejected the NT-error negprot (%s)\n", host,
10128 nt_errstr(status));
10129 cli_shutdown(c_nt);
10133 status = cli_session_setup_anon(c_nt);
10134 if (!NT_STATUS_IS_OK(status)) {
10135 printf("%s rejected the NT-error initial session setup (%s)\n",host, nt_errstr(status));
10139 /* DOS-Error connection */
10141 disable_spnego = true;
10142 force_dos_errors = true;
10143 if (!(c_dos = open_nbt_connection())) {
10144 disable_spnego = false;
10145 force_dos_errors = false;
10148 disable_spnego = false;
10149 force_dos_errors = false;
10151 status = smbXcli_negprot(c_dos->conn, c_dos->timeout, PROTOCOL_CORE,
10153 if (!NT_STATUS_IS_OK(status)) {
10154 printf("%s rejected the DOS-error negprot (%s)\n", host,
10155 nt_errstr(status));
10156 cli_shutdown(c_dos);
10160 status = cli_session_setup_anon(c_dos);
10161 if (!NT_STATUS_IS_OK(status)) {
10162 printf("%s rejected the DOS-error initial session setup (%s)\n",
10163 host, nt_errstr(status));
10167 c_nt->map_dos_errors = false;
10168 c_dos->map_dos_errors = false;
10170 for (error=(0xc0000000 | 0x1); error < (0xc0000000| 0xFFF); error++) {
10171 struct cli_credentials *user_creds = NULL;
10173 fstr_sprintf(user, "%X", error);
10175 user_creds = cli_session_creds_init(talloc_tos(),
10180 false, /* use_kerberos */
10181 false, /* fallback_after_kerberos */
10182 false, /* use_ccache */
10183 false); /* password_is_nt_hash */
10184 if (user_creds == NULL) {
10185 printf("cli_session_creds_init(%s) failed\n", user);
10189 status = cli_session_setup_creds(c_nt, user_creds);
10190 if (NT_STATUS_IS_OK(status)) {
10191 printf("/** Session setup succeeded. This shouldn't happen...*/\n");
10194 /* Case #1: 32-bit NT errors */
10195 if (!NT_STATUS_IS_DOS(status)) {
10196 nt_status = status;
10198 printf("/** Dos error on NT connection! (%s) */\n",
10199 nt_errstr(status));
10200 nt_status = NT_STATUS(0xc0000000);
10203 status = cli_session_setup_creds(c_dos, user_creds);
10204 if (NT_STATUS_IS_OK(status)) {
10205 printf("/** Session setup succeeded. This shouldn't happen...*/\n");
10208 /* Case #1: 32-bit NT errors */
10209 if (NT_STATUS_IS_DOS(status)) {
10210 printf("/** NT error on DOS connection! (%s) */\n",
10211 nt_errstr(status));
10212 errnum = errclass = 0;
10214 errclass = NT_STATUS_DOS_CLASS(status);
10215 errnum = NT_STATUS_DOS_CODE(status);
10218 if (NT_STATUS_V(nt_status) != error) {
10219 printf("/*\t{ This NT error code was 'sqashed'\n\t from %s to %s \n\t during the session setup }\n*/\n",
10220 get_nt_error_c_code(talloc_tos(), NT_STATUS(error)),
10221 get_nt_error_c_code(talloc_tos(), nt_status));
10224 printf("\t{%s,\t%s,\t%s},\n",
10225 smb_dos_err_class(errclass),
10226 smb_dos_err_name(errclass, errnum),
10227 get_nt_error_c_code(talloc_tos(), NT_STATUS(error)));
10229 TALLOC_FREE(user_creds);
10234 static bool run_sesssetup_bench(int dummy)
10236 static struct cli_state *c;
10237 const char *fname = "\\file.dat";
10242 if (!torture_open_connection(&c, 0)) {
10246 status = cli_ntcreate(c, fname, 0, GENERIC_ALL_ACCESS|DELETE_ACCESS,
10247 FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
10248 FILE_DELETE_ON_CLOSE, 0, &fnum, NULL);
10249 if (!NT_STATUS_IS_OK(status)) {
10250 d_printf("open %s failed: %s\n", fname, nt_errstr(status));
10254 for (i=0; i<torture_numops; i++) {
10255 status = cli_session_setup_creds(c, torture_creds);
10256 if (!NT_STATUS_IS_OK(status)) {
10257 d_printf("(%s) cli_session_setup_creds failed: %s\n",
10258 __location__, nt_errstr(status));
10262 d_printf("\r%d ", (int)cli_state_get_uid(c));
10264 status = cli_ulogoff(c);
10265 if (!NT_STATUS_IS_OK(status)) {
10266 d_printf("(%s) cli_ulogoff failed: %s\n",
10267 __location__, nt_errstr(status));
10275 static bool subst_test(const char *str, const char *user, const char *domain,
10276 uid_t uid, gid_t gid, const char *expected)
10279 bool result = true;
10281 subst = talloc_sub_specified(talloc_tos(), str, user, NULL, domain, uid, gid);
10283 if (strcmp(subst, expected) != 0) {
10284 printf("sub_specified(%s, %s, %s, %d, %d) returned [%s], expected "
10285 "[%s]\n", str, user, domain, (int)uid, (int)gid, subst,
10290 TALLOC_FREE(subst);
10294 static void chain1_open_completion(struct tevent_req *req)
10298 status = cli_openx_recv(req, &fnum);
10301 d_printf("cli_openx_recv returned %s: %d\n",
10303 NT_STATUS_IS_OK(status) ? fnum : -1);
10306 static void chain1_write_completion(struct tevent_req *req)
10310 status = cli_write_andx_recv(req, &written);
10313 d_printf("cli_write_andx_recv returned %s: %d\n",
10315 NT_STATUS_IS_OK(status) ? (int)written : -1);
10318 static void chain1_close_completion(struct tevent_req *req)
10321 bool *done = (bool *)tevent_req_callback_data_void(req);
10323 status = cli_close_recv(req);
10328 d_printf("cli_close returned %s\n", nt_errstr(status));
10331 static bool run_chain1(int dummy)
10333 struct cli_state *cli1;
10334 struct tevent_context *evt = samba_tevent_context_init(NULL);
10335 struct tevent_req *reqs[3], *smbreqs[3];
10337 const char *str = "foobar";
10338 const char *fname = "\\test_chain";
10341 printf("starting chain1 test\n");
10342 if (!torture_open_connection(&cli1, 0)) {
10346 smbXcli_conn_set_sockopt(cli1->conn, sockops);
10348 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
10350 reqs[0] = cli_openx_create(talloc_tos(), evt, cli1, fname,
10351 O_CREAT|O_RDWR, 0, &smbreqs[0]);
10352 if (reqs[0] == NULL) return false;
10353 tevent_req_set_callback(reqs[0], chain1_open_completion, NULL);
10356 reqs[1] = cli_write_andx_create(talloc_tos(), evt, cli1, 0, 0,
10357 (const uint8_t *)str, 0, strlen(str)+1,
10358 smbreqs, 1, &smbreqs[1]);
10359 if (reqs[1] == NULL) return false;
10360 tevent_req_set_callback(reqs[1], chain1_write_completion, NULL);
10362 reqs[2] = cli_smb1_close_create(talloc_tos(), evt, cli1, 0, &smbreqs[2]);
10363 if (reqs[2] == NULL) return false;
10364 tevent_req_set_callback(reqs[2], chain1_close_completion, &done);
10366 status = smb1cli_req_chain_submit(smbreqs, ARRAY_SIZE(smbreqs));
10367 if (!NT_STATUS_IS_OK(status)) {
10372 tevent_loop_once(evt);
10375 torture_close_connection(cli1);
10379 static void chain2_sesssetup_completion(struct tevent_req *req)
10382 status = cli_session_setup_guest_recv(req);
10383 d_printf("sesssetup returned %s\n", nt_errstr(status));
10386 static void chain2_tcon_completion(struct tevent_req *req)
10388 bool *done = (bool *)tevent_req_callback_data_void(req);
10390 status = cli_tcon_andx_recv(req);
10391 d_printf("tcon_and_x returned %s\n", nt_errstr(status));
10395 static bool run_chain2(int dummy)
10397 struct cli_state *cli1;
10398 struct tevent_context *evt = samba_tevent_context_init(NULL);
10399 struct tevent_req *reqs[2], *smbreqs[2];
10402 int flags = CLI_FULL_CONNECTION_FORCE_SMB1;
10404 printf("starting chain2 test\n");
10405 status = cli_start_connection(&cli1, lp_netbios_name(), host, NULL,
10406 port_to_use, SMB_SIGNING_DEFAULT, flags);
10407 if (!NT_STATUS_IS_OK(status)) {
10411 smbXcli_conn_set_sockopt(cli1->conn, sockops);
10413 reqs[0] = cli_session_setup_guest_create(talloc_tos(), evt, cli1,
10415 if (reqs[0] == NULL) return false;
10416 tevent_req_set_callback(reqs[0], chain2_sesssetup_completion, NULL);
10418 reqs[1] = cli_tcon_andx_create(talloc_tos(), evt, cli1, "IPC$",
10419 "?????", NULL, 0, &smbreqs[1]);
10420 if (reqs[1] == NULL) return false;
10421 tevent_req_set_callback(reqs[1], chain2_tcon_completion, &done);
10423 status = smb1cli_req_chain_submit(smbreqs, ARRAY_SIZE(smbreqs));
10424 if (!NT_STATUS_IS_OK(status)) {
10429 tevent_loop_once(evt);
10432 torture_close_connection(cli1);
10437 struct torture_createdel_state {
10438 struct tevent_context *ev;
10439 struct cli_state *cli;
10442 static void torture_createdel_created(struct tevent_req *subreq);
10443 static void torture_createdel_closed(struct tevent_req *subreq);
10445 static struct tevent_req *torture_createdel_send(TALLOC_CTX *mem_ctx,
10446 struct tevent_context *ev,
10447 struct cli_state *cli,
10450 struct tevent_req *req, *subreq;
10451 struct torture_createdel_state *state;
10453 req = tevent_req_create(mem_ctx, &state,
10454 struct torture_createdel_state);
10461 subreq = cli_ntcreate_send(
10462 state, ev, cli, name, 0,
10463 FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
10464 FILE_ATTRIBUTE_NORMAL,
10465 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
10466 FILE_OPEN_IF, FILE_DELETE_ON_CLOSE,
10467 SMB2_IMPERSONATION_IMPERSONATION, 0);
10469 if (tevent_req_nomem(subreq, req)) {
10470 return tevent_req_post(req, ev);
10472 tevent_req_set_callback(subreq, torture_createdel_created, req);
10476 static void torture_createdel_created(struct tevent_req *subreq)
10478 struct tevent_req *req = tevent_req_callback_data(
10479 subreq, struct tevent_req);
10480 struct torture_createdel_state *state = tevent_req_data(
10481 req, struct torture_createdel_state);
10485 status = cli_ntcreate_recv(subreq, &fnum, NULL);
10486 TALLOC_FREE(subreq);
10487 if (tevent_req_nterror(req, status)) {
10488 DEBUG(10, ("cli_ntcreate_recv returned %s\n",
10489 nt_errstr(status)));
10493 subreq = cli_close_send(state, state->ev, state->cli, fnum);
10494 if (tevent_req_nomem(subreq, req)) {
10497 tevent_req_set_callback(subreq, torture_createdel_closed, req);
10500 static void torture_createdel_closed(struct tevent_req *subreq)
10502 struct tevent_req *req = tevent_req_callback_data(
10503 subreq, struct tevent_req);
10506 status = cli_close_recv(subreq);
10507 if (tevent_req_nterror(req, status)) {
10508 DEBUG(10, ("cli_close_recv returned %s\n", nt_errstr(status)));
10511 tevent_req_done(req);
10514 static NTSTATUS torture_createdel_recv(struct tevent_req *req)
10516 return tevent_req_simple_recv_ntstatus(req);
10519 struct torture_createdels_state {
10520 struct tevent_context *ev;
10521 struct cli_state *cli;
10522 const char *base_name;
10526 struct tevent_req **reqs;
10529 static void torture_createdels_done(struct tevent_req *subreq);
10531 static struct tevent_req *torture_createdels_send(TALLOC_CTX *mem_ctx,
10532 struct tevent_context *ev,
10533 struct cli_state *cli,
10534 const char *base_name,
10538 struct tevent_req *req;
10539 struct torture_createdels_state *state;
10542 req = tevent_req_create(mem_ctx, &state,
10543 struct torture_createdels_state);
10549 state->base_name = talloc_strdup(state, base_name);
10550 if (tevent_req_nomem(state->base_name, req)) {
10551 return tevent_req_post(req, ev);
10553 state->num_files = MAX(num_parallel, num_files);
10555 state->received = 0;
10557 state->reqs = talloc_array(state, struct tevent_req *, num_parallel);
10558 if (tevent_req_nomem(state->reqs, req)) {
10559 return tevent_req_post(req, ev);
10562 for (i=0; i<num_parallel; i++) {
10565 name = talloc_asprintf(state, "%s%8.8d", state->base_name,
10567 if (tevent_req_nomem(name, req)) {
10568 return tevent_req_post(req, ev);
10570 state->reqs[i] = torture_createdel_send(
10571 state->reqs, state->ev, state->cli, name);
10572 if (tevent_req_nomem(state->reqs[i], req)) {
10573 return tevent_req_post(req, ev);
10575 name = talloc_move(state->reqs[i], &name);
10576 tevent_req_set_callback(state->reqs[i],
10577 torture_createdels_done, req);
10583 static void torture_createdels_done(struct tevent_req *subreq)
10585 struct tevent_req *req = tevent_req_callback_data(
10586 subreq, struct tevent_req);
10587 struct torture_createdels_state *state = tevent_req_data(
10588 req, struct torture_createdels_state);
10589 size_t num_parallel = talloc_array_length(state->reqs);
10594 status = torture_createdel_recv(subreq);
10595 if (!NT_STATUS_IS_OK(status)){
10596 DEBUG(10, ("torture_createdel_recv returned %s\n",
10597 nt_errstr(status)));
10598 TALLOC_FREE(subreq);
10599 tevent_req_nterror(req, status);
10603 for (i=0; i<num_parallel; i++) {
10604 if (subreq == state->reqs[i]) {
10608 if (i == num_parallel) {
10609 DEBUG(10, ("received something we did not send\n"));
10610 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
10613 TALLOC_FREE(state->reqs[i]);
10615 if (state->sent >= state->num_files) {
10616 tevent_req_done(req);
10620 name = talloc_asprintf(state, "%s%8.8d", state->base_name,
10622 if (tevent_req_nomem(name, req)) {
10625 state->reqs[i] = torture_createdel_send(state->reqs, state->ev,
10627 if (tevent_req_nomem(state->reqs[i], req)) {
10630 name = talloc_move(state->reqs[i], &name);
10631 tevent_req_set_callback(state->reqs[i], torture_createdels_done, req);
10635 static NTSTATUS torture_createdels_recv(struct tevent_req *req)
10637 return tevent_req_simple_recv_ntstatus(req);
10640 struct swallow_notify_state {
10641 struct tevent_context *ev;
10642 struct cli_state *cli;
10644 uint32_t completion_filter;
10646 bool (*fn)(uint32_t action, const char *name, void *priv);
10650 static void swallow_notify_done(struct tevent_req *subreq);
10652 static struct tevent_req *swallow_notify_send(TALLOC_CTX *mem_ctx,
10653 struct tevent_context *ev,
10654 struct cli_state *cli,
10656 uint32_t completion_filter,
10658 bool (*fn)(uint32_t action,
10663 struct tevent_req *req, *subreq;
10664 struct swallow_notify_state *state;
10666 req = tevent_req_create(mem_ctx, &state,
10667 struct swallow_notify_state);
10673 state->fnum = fnum;
10674 state->completion_filter = completion_filter;
10675 state->recursive = recursive;
10677 state->priv = priv;
10679 subreq = cli_notify_send(state, state->ev, state->cli, state->fnum,
10680 0xffff, state->completion_filter,
10682 if (tevent_req_nomem(subreq, req)) {
10683 return tevent_req_post(req, ev);
10685 tevent_req_set_callback(subreq, swallow_notify_done, req);
10689 static void swallow_notify_done(struct tevent_req *subreq)
10691 struct tevent_req *req = tevent_req_callback_data(
10692 subreq, struct tevent_req);
10693 struct swallow_notify_state *state = tevent_req_data(
10694 req, struct swallow_notify_state);
10696 uint32_t i, num_changes;
10697 struct notify_change *changes;
10699 status = cli_notify_recv(subreq, state, &num_changes, &changes);
10700 TALLOC_FREE(subreq);
10701 if (!NT_STATUS_IS_OK(status)) {
10702 DEBUG(10, ("cli_notify_recv returned %s\n",
10703 nt_errstr(status)));
10704 tevent_req_nterror(req, status);
10708 for (i=0; i<num_changes; i++) {
10709 state->fn(changes[i].action, changes[i].name, state->priv);
10711 TALLOC_FREE(changes);
10713 subreq = cli_notify_send(state, state->ev, state->cli, state->fnum,
10714 0xffff, state->completion_filter,
10716 if (tevent_req_nomem(subreq, req)) {
10719 tevent_req_set_callback(subreq, swallow_notify_done, req);
10722 static bool print_notifies(uint32_t action, const char *name, void *priv)
10724 if (DEBUGLEVEL > 5) {
10725 d_printf("%d %s\n", (int)action, name);
10730 static void notify_bench_done(struct tevent_req *req)
10732 int *num_finished = (int *)tevent_req_callback_data_void(req);
10733 *num_finished += 1;
10736 static bool run_notify_bench(int dummy)
10738 const char *dname = "\\notify-bench";
10739 struct tevent_context *ev;
10742 struct tevent_req *req1;
10743 struct tevent_req *req2 = NULL;
10744 int i, num_unc_names;
10745 int num_finished = 0;
10747 printf("starting notify-bench test\n");
10749 if (use_multishare_conn) {
10751 unc_list = file_lines_load(multishare_conn_fname,
10752 &num_unc_names, 0, NULL);
10753 if (!unc_list || num_unc_names <= 0) {
10754 d_printf("Failed to load unc names list from '%s'\n",
10755 multishare_conn_fname);
10758 TALLOC_FREE(unc_list);
10763 ev = samba_tevent_context_init(talloc_tos());
10765 d_printf("tevent_context_init failed\n");
10769 for (i=0; i<num_unc_names; i++) {
10770 struct cli_state *cli;
10773 base_fname = talloc_asprintf(talloc_tos(), "%s\\file%3.3d.",
10775 if (base_fname == NULL) {
10779 if (!torture_open_connection(&cli, i)) {
10783 status = cli_ntcreate(cli, dname, 0,
10784 MAXIMUM_ALLOWED_ACCESS,
10785 0, FILE_SHARE_READ|FILE_SHARE_WRITE|
10787 FILE_OPEN_IF, FILE_DIRECTORY_FILE, 0,
10790 if (!NT_STATUS_IS_OK(status)) {
10791 d_printf("Could not create %s: %s\n", dname,
10792 nt_errstr(status));
10796 req1 = swallow_notify_send(talloc_tos(), ev, cli, dnum,
10797 FILE_NOTIFY_CHANGE_FILE_NAME |
10798 FILE_NOTIFY_CHANGE_DIR_NAME |
10799 FILE_NOTIFY_CHANGE_ATTRIBUTES |
10800 FILE_NOTIFY_CHANGE_LAST_WRITE,
10801 false, print_notifies, NULL);
10802 if (req1 == NULL) {
10803 d_printf("Could not create notify request\n");
10807 req2 = torture_createdels_send(talloc_tos(), ev, cli,
10808 base_fname, 10, torture_numops);
10809 if (req2 == NULL) {
10810 d_printf("Could not create createdels request\n");
10813 TALLOC_FREE(base_fname);
10815 tevent_req_set_callback(req2, notify_bench_done,
10819 while (num_finished < num_unc_names) {
10821 ret = tevent_loop_once(ev);
10823 d_printf("tevent_loop_once failed\n");
10828 if (!tevent_req_poll(req2, ev)) {
10829 d_printf("tevent_req_poll failed\n");
10832 status = torture_createdels_recv(req2);
10833 d_printf("torture_createdels_recv returned %s\n", nt_errstr(status));
10838 static bool run_mangle1(int dummy)
10840 struct cli_state *cli;
10841 const char *fname = "this_is_a_long_fname_to_be_mangled.txt";
10845 time_t change_time, access_time, write_time;
10849 printf("starting mangle1 test\n");
10850 if (!torture_open_connection(&cli, 0)) {
10854 smbXcli_conn_set_sockopt(cli->conn, sockops);
10856 status = cli_ntcreate(cli, fname, 0, GENERIC_ALL_ACCESS|DELETE_ACCESS,
10857 FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
10858 0, 0, &fnum, NULL);
10859 if (!NT_STATUS_IS_OK(status)) {
10860 d_printf("open %s failed: %s\n", fname, nt_errstr(status));
10863 cli_close(cli, fnum);
10865 status = cli_qpathinfo_alt_name(cli, fname, alt_name);
10866 if (!NT_STATUS_IS_OK(status)) {
10867 d_printf("cli_qpathinfo_alt_name failed: %s\n",
10868 nt_errstr(status));
10871 d_printf("alt_name: %s\n", alt_name);
10873 status = cli_openx(cli, alt_name, O_RDONLY, DENY_NONE, &fnum);
10874 if (!NT_STATUS_IS_OK(status)) {
10875 d_printf("cli_openx(%s) failed: %s\n", alt_name,
10876 nt_errstr(status));
10879 cli_close(cli, fnum);
10881 status = cli_qpathinfo1(cli, alt_name, &change_time, &access_time,
10882 &write_time, &size, &attr);
10883 if (!NT_STATUS_IS_OK(status)) {
10884 d_printf("cli_qpathinfo1(%s) failed: %s\n", alt_name,
10885 nt_errstr(status));
10892 static NTSTATUS mangle_illegal_list_shortname_fn(struct file_info *f,
10896 if (f->short_name == NULL) {
10897 return NT_STATUS_OK;
10900 if (strlen(f->short_name) == 0) {
10901 return NT_STATUS_OK;
10904 printf("unexpected shortname: %s\n", f->short_name);
10906 return NT_STATUS_OBJECT_NAME_INVALID;
10909 static NTSTATUS mangle_illegal_list_name_fn(struct file_info *f,
10913 char *name = state;
10915 printf("name: %s\n", f->name);
10916 fstrcpy(name, f->name);
10917 return NT_STATUS_OK;
10920 static bool run_mangle_illegal(int dummy)
10922 struct cli_state *cli = NULL;
10923 struct cli_state *cli_posix = NULL;
10924 const char *fname = "\\MANGLE_ILLEGAL\\this_is_a_long_fname_to_be_mangled.txt";
10925 const char *illegal_fname = "MANGLE_ILLEGAL/foo:bar";
10926 char *mangled_path = NULL;
10932 printf("starting mangle-illegal test\n");
10934 if (!torture_open_connection(&cli, 0)) {
10938 smbXcli_conn_set_sockopt(cli->conn, sockops);
10940 if (!torture_open_connection(&cli_posix, 0)) {
10944 smbXcli_conn_set_sockopt(cli_posix->conn, sockops);
10946 status = torture_setup_unix_extensions(cli_posix);
10947 if (!NT_STATUS_IS_OK(status)) {
10951 cli_rmdir(cli, "\\MANGLE_ILLEGAL");
10952 status = cli_mkdir(cli, "\\MANGLE_ILLEGAL");
10953 if (!NT_STATUS_IS_OK(status)) {
10954 printf("mkdir1 failed : %s\n", nt_errstr(status));
10959 * Create a file with illegal NTFS characters and test that we
10960 * get a usable mangled name
10963 cli_setatr(cli_posix, illegal_fname, 0, 0);
10964 cli_posix_unlink(cli_posix, illegal_fname);
10966 status = cli_posix_open(cli_posix, illegal_fname, O_RDWR|O_CREAT|O_EXCL,
10968 if (!NT_STATUS_IS_OK(status)) {
10969 printf("POSIX create of %s failed (%s)\n",
10970 illegal_fname, nt_errstr(status));
10974 status = cli_close(cli_posix, fnum);
10975 if (!NT_STATUS_IS_OK(status)) {
10976 printf("close failed (%s)\n", nt_errstr(status));
10980 status = cli_list(cli, "\\MANGLE_ILLEGAL\\*", 0, mangle_illegal_list_name_fn, &name);
10981 if (!NT_STATUS_IS_OK(status)) {
10982 d_printf("cli_list failed: %s\n", nt_errstr(status));
10986 mangled_path = talloc_asprintf(talloc_tos(), "\\MANGLE_ILLEGAL\\%s", name);
10987 if (mangled_path == NULL) {
10991 status = cli_openx(cli, mangled_path, O_RDONLY, DENY_NONE, &fnum);
10992 if (!NT_STATUS_IS_OK(status)) {
10993 d_printf("cli_openx(%s) failed: %s\n", mangled_path, nt_errstr(status));
10994 TALLOC_FREE(mangled_path);
10997 TALLOC_FREE(mangled_path);
10998 cli_close(cli, fnum);
11000 cli_setatr(cli_posix, illegal_fname, 0, 0);
11001 cli_posix_unlink(cli_posix, illegal_fname);
11004 * Create a file with a long name and check that we got *no* short name.
11007 status = cli_ntcreate(cli, fname, 0, GENERIC_ALL_ACCESS|DELETE_ACCESS,
11008 FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
11009 0, 0, &fnum, NULL);
11010 if (!NT_STATUS_IS_OK(status)) {
11011 d_printf("open %s failed: %s\n", fname, nt_errstr(status));
11014 cli_close(cli, fnum);
11016 status = cli_list(cli, fname, 0, mangle_illegal_list_shortname_fn, &alt_name);
11017 if (!NT_STATUS_IS_OK(status)) {
11018 d_printf("cli_list failed\n");
11022 cli_unlink(cli, fname, 0);
11023 cli_rmdir(cli, "\\MANGLE_ILLEGAL");
11025 if (!torture_close_connection(cli_posix)) {
11029 if (!torture_close_connection(cli)) {
11036 static size_t null_source(uint8_t *buf, size_t n, void *priv)
11038 size_t *to_pull = (size_t *)priv;
11039 size_t thistime = *to_pull;
11041 thistime = MIN(thistime, n);
11042 if (thistime == 0) {
11046 memset(buf, 0, thistime);
11047 *to_pull -= thistime;
11051 static bool run_windows_write(int dummy)
11053 struct cli_state *cli1;
11057 const char *fname = "\\writetest.txt";
11058 struct timeval start_time;
11063 printf("starting windows_write test\n");
11064 if (!torture_open_connection(&cli1, 0)) {
11068 status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
11069 if (!NT_STATUS_IS_OK(status)) {
11070 printf("open failed (%s)\n", nt_errstr(status));
11074 smbXcli_conn_set_sockopt(cli1->conn, sockops);
11076 start_time = timeval_current();
11078 for (i=0; i<torture_numops; i++) {
11080 off_t start = i * torture_blocksize;
11081 size_t to_pull = torture_blocksize - 1;
11083 status = cli_writeall(cli1, fnum, 0, &c,
11084 start + torture_blocksize - 1, 1, NULL);
11085 if (!NT_STATUS_IS_OK(status)) {
11086 printf("cli_write failed: %s\n", nt_errstr(status));
11090 status = cli_push(cli1, fnum, 0, i * torture_blocksize, torture_blocksize,
11091 null_source, &to_pull);
11092 if (!NT_STATUS_IS_OK(status)) {
11093 printf("cli_push returned: %s\n", nt_errstr(status));
11098 seconds = timeval_elapsed(&start_time);
11099 kbytes = (double)torture_blocksize * torture_numops;
11102 printf("Wrote %d kbytes in %.2f seconds: %d kb/sec\n", (int)kbytes,
11103 (double)seconds, (int)(kbytes/seconds));
11107 cli_close(cli1, fnum);
11108 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
11109 torture_close_connection(cli1);
11113 static size_t calc_expected_return(struct cli_state *cli, size_t len_requested)
11115 size_t max_pdu = 0x1FFFF;
11117 if (cli->server_posix_capabilities & CIFS_UNIX_LARGE_READ_CAP) {
11118 max_pdu = 0xFFFFFF;
11121 if (smb1cli_conn_signing_is_active(cli->conn)) {
11125 if (smb1cli_conn_encryption_on(cli->conn)) {
11126 max_pdu = CLI_BUFFER_SIZE;
11129 if ((len_requested & 0xFFFF0000) == 0xFFFF0000) {
11130 len_requested &= 0xFFFF;
11133 return MIN(len_requested,
11134 max_pdu - (MIN_SMB_SIZE + VWV(12) + 1 /* padding byte */));
11137 static bool check_read_call(struct cli_state *cli,
11140 size_t len_requested)
11143 struct tevent_req *subreq = NULL;
11144 ssize_t len_read = 0;
11145 size_t len_expected = 0;
11146 struct tevent_context *ev = NULL;
11148 ev = samba_tevent_context_init(talloc_tos());
11153 subreq = cli_read_andx_send(talloc_tos(),
11160 if (!tevent_req_poll_ntstatus(subreq, ev, &status)) {
11164 status = cli_read_andx_recv(subreq, &len_read, &buf);
11165 if (!NT_STATUS_IS_OK(status)) {
11166 d_printf("cli_read_andx_recv failed: %s\n", nt_errstr(status));
11170 TALLOC_FREE(subreq);
11173 len_expected = calc_expected_return(cli, len_requested);
11175 if (len_expected > 0x10000 && len_read == 0x10000) {
11176 /* Windows servers only return a max of 0x10000,
11177 doesn't matter if you set CAP_LARGE_READX in
11178 the client sessionsetupX call or not. */
11179 d_printf("Windows server - returned 0x10000 on a read of 0x%x\n",
11180 (unsigned int)len_requested);
11181 } else if (len_read != len_expected) {
11182 d_printf("read of 0x%x failed: got 0x%x, expected 0x%x\n",
11183 (unsigned int)len_requested,
11184 (unsigned int)len_read,
11185 (unsigned int)len_expected);
11188 d_printf("Correct read reply.\n");
11194 /* Test large readX variants. */
11195 static bool large_readx_tests(struct cli_state *cli,
11199 /* A read of 0xFFFF0001 should *always* return 1 byte. */
11200 if (check_read_call(cli, fnum, buf, 0xFFFF0001) == false) {
11203 /* A read of 0x10000 should return 0x10000 bytes. */
11204 if (check_read_call(cli, fnum, buf, 0x10000) == false) {
11207 /* A read of 0x10000 should return 0x10001 bytes. */
11208 if (check_read_call(cli, fnum, buf, 0x10001) == false) {
11211 /* A read of 0x1FFFF - (MIN_SMB_SIZE + VWV(12) should return
11212 the requested number of bytes. */
11213 if (check_read_call(cli, fnum, buf, 0x1FFFF - (MIN_SMB_SIZE + VWV(12))) == false) {
11216 /* A read of 1MB should return 1MB bytes (on Samba). */
11217 if (check_read_call(cli, fnum, buf, 0x100000) == false) {
11221 if (check_read_call(cli, fnum, buf, 0x20001) == false) {
11224 if (check_read_call(cli, fnum, buf, 0x22000001) == false) {
11227 if (check_read_call(cli, fnum, buf, 0xFFFE0001) == false) {
11233 static bool run_large_readx(int dummy)
11235 uint8_t *buf = NULL;
11236 struct cli_state *cli1 = NULL;
11237 struct cli_state *cli2 = NULL;
11238 bool correct = false;
11239 const char *fname = "\\large_readx.dat";
11241 uint16_t fnum1 = UINT16_MAX;
11242 uint32_t normal_caps = 0;
11243 size_t file_size = 20*1024*1024;
11244 TALLOC_CTX *frame = talloc_stackframe();
11248 enum smb_signing_setting signing_setting;
11249 enum protocol_types protocol;
11253 .signing_setting = SMB_SIGNING_IF_REQUIRED,
11254 .protocol = PROTOCOL_NT1,
11256 .name = "NT1 - SIGNING_REQUIRED",
11257 .signing_setting = SMB_SIGNING_REQUIRED,
11258 .protocol = PROTOCOL_NT1,
11262 printf("starting large_readx test\n");
11264 if (!torture_open_connection(&cli1, 0)) {
11268 normal_caps = smb1cli_conn_capabilities(cli1->conn);
11270 if (!(normal_caps & CAP_LARGE_READX)) {
11271 d_printf("Server doesn't have CAP_LARGE_READX 0x%x\n",
11272 (unsigned int)normal_caps);
11276 /* Create a file of size 4MB. */
11277 status = cli_ntcreate(cli1, fname, 0, GENERIC_ALL_ACCESS,
11278 FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
11279 0, 0, &fnum1, NULL);
11281 if (!NT_STATUS_IS_OK(status)) {
11282 d_printf("open %s failed: %s\n", fname, nt_errstr(status));
11286 /* Write file_size bytes. */
11287 buf = talloc_zero_array(frame, uint8_t, file_size);
11292 status = cli_writeall(cli1,
11299 if (!NT_STATUS_IS_OK(status)) {
11300 d_printf("cli_writeall failed: %s\n", nt_errstr(status));
11304 status = cli_close(cli1, fnum1);
11305 if (!NT_STATUS_IS_OK(status)) {
11306 d_printf("cli_close failed: %s\n", nt_errstr(status));
11310 fnum1 = UINT16_MAX;
11312 for (i=0; i < ARRAY_SIZE(runs); i++) {
11313 enum smb_signing_setting saved_signing_setting = signing_state;
11314 uint16_t fnum2 = -1;
11317 (runs[i].signing_setting == SMB_SIGNING_REQUIRED))
11319 d_printf("skip[%u] - %s\n", (unsigned)i, runs[i].name);
11323 d_printf("run[%u] - %s\n", (unsigned)i, runs[i].name);
11325 signing_state = runs[i].signing_setting;
11326 cli2 = open_nbt_connection();
11327 signing_state = saved_signing_setting;
11328 if (cli2 == NULL) {
11332 status = smbXcli_negprot(cli2->conn,
11336 if (!NT_STATUS_IS_OK(status)) {
11340 status = cli_session_setup_creds(cli2, torture_creds);
11341 if (!NT_STATUS_IS_OK(status)) {
11345 status = cli_tree_connect(cli2,
11349 if (!NT_STATUS_IS_OK(status)) {
11353 cli_set_timeout(cli2, 120000); /* set a really long timeout (2 minutes) */
11355 normal_caps = smb1cli_conn_capabilities(cli2->conn);
11357 if (!(normal_caps & CAP_LARGE_READX)) {
11358 d_printf("Server doesn't have CAP_LARGE_READX 0x%x\n",
11359 (unsigned int)normal_caps);
11364 if (force_cli_encryption(cli2, share) == false) {
11367 } else if (SERVER_HAS_UNIX_CIFS(cli2)) {
11368 uint16_t major, minor;
11369 uint32_t caplow, caphigh;
11371 status = cli_unix_extensions_version(cli2,
11373 &caplow, &caphigh);
11374 if (!NT_STATUS_IS_OK(status)) {
11379 status = cli_ntcreate(cli2, fname, 0, FILE_READ_DATA,
11380 FILE_ATTRIBUTE_NORMAL, 0, FILE_OPEN,
11381 0, 0, &fnum2, NULL);
11382 if (!NT_STATUS_IS_OK(status)) {
11383 d_printf("Second open %s failed: %s\n", fname, nt_errstr(status));
11387 /* All reads must return less than file_size bytes. */
11388 if (!large_readx_tests(cli2, fnum2, buf)) {
11392 status = cli_close(cli2, fnum2);
11393 if (!NT_STATUS_IS_OK(status)) {
11394 d_printf("cli_close failed: %s\n", nt_errstr(status));
11399 if (!torture_close_connection(cli2)) {
11406 printf("Success on large_readx test\n");
11411 if (!torture_close_connection(cli2)) {
11417 if (fnum1 != UINT16_MAX) {
11418 status = cli_close(cli1, fnum1);
11419 if (!NT_STATUS_IS_OK(status)) {
11420 d_printf("cli_close failed: %s\n", nt_errstr(status));
11422 fnum1 = UINT16_MAX;
11425 status = cli_unlink(cli1, fname,
11426 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
11427 if (!NT_STATUS_IS_OK(status)) {
11428 printf("unlink failed (%s)\n", nt_errstr(status));
11431 if (!torture_close_connection(cli1)) {
11436 TALLOC_FREE(frame);
11438 printf("finished large_readx test\n");
11442 static NTSTATUS msdfs_attribute_list_fn(struct file_info *finfo,
11444 void *private_data)
11446 uint32_t *p_attr = (uint32_t *)private_data;
11448 if (strequal(finfo->name, test_filename)) {
11449 *p_attr = finfo->attr;
11452 return NT_STATUS_OK;
11455 static bool run_msdfs_attribute(int dummy)
11457 static struct cli_state *cli;
11458 bool correct = false;
11462 printf("Starting MSDFS-ATTRIBUTE test\n");
11464 if (test_filename == NULL || test_filename[0] == '\0') {
11465 printf("MSDFS-ATTRIBUTE test "
11466 "needs -f filename-of-msdfs-link\n");
11471 * NB. We use torture_open_connection_flags() not
11472 * torture_open_connection() as the latter forces
11475 if (!torture_open_connection_flags(&cli, 0, 0)) {
11479 smbXcli_conn_set_sockopt(cli->conn, sockops);
11481 status = cli_list(cli,
11483 FILE_ATTRIBUTE_DIRECTORY,
11484 msdfs_attribute_list_fn,
11487 if (!NT_STATUS_IS_OK(status)) {
11488 printf("cli_list failed with %s\n",
11489 nt_errstr(status));
11492 if ((attr & FILE_ATTRIBUTE_REPARSE_POINT) == 0) {
11493 printf("file %s should have "
11494 "FILE_ATTRIBUTE_REPARSE_POINT set. attr = 0x%x\n",
11496 (unsigned int)attr);
11500 if ((attr & FILE_ATTRIBUTE_DIRECTORY) == 0) {
11501 printf("file %s should have "
11502 "FILE_ATTRIBUTE_DIRECTORY set. attr = 0x%x\n",
11504 (unsigned int)attr);
11512 torture_close_connection(cli);
11516 static bool run_cli_echo(int dummy)
11518 struct cli_state *cli;
11521 printf("starting cli_echo test\n");
11522 if (!torture_open_connection(&cli, 0)) {
11525 smbXcli_conn_set_sockopt(cli->conn, sockops);
11527 status = cli_echo(cli, 5, data_blob_const("hello", 5));
11529 d_printf("cli_echo returned %s\n", nt_errstr(status));
11531 torture_close_connection(cli);
11532 return NT_STATUS_IS_OK(status);
11535 static int splice_status(off_t written, void *priv)
11540 static bool run_cli_splice(int dummy)
11542 uint8_t *buf = NULL;
11543 struct cli_state *cli1 = NULL;
11544 bool correct = false;
11545 const char *fname_src = "\\splice_src.dat";
11546 const char *fname_dst = "\\splice_dst.dat";
11548 uint16_t fnum1 = UINT16_MAX;
11549 uint16_t fnum2 = UINT16_MAX;
11550 size_t file_size = 2*1024*1024;
11551 size_t splice_size = 1*1024*1024 + 713;
11552 uint8_t digest1[16], digest2[16];
11555 TALLOC_CTX *frame = talloc_stackframe();
11557 printf("starting cli_splice test\n");
11559 if (!torture_open_connection(&cli1, 0)) {
11563 cli_unlink(cli1, fname_src,
11564 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
11565 cli_unlink(cli1, fname_dst,
11566 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
11568 /* Create a file */
11569 status = cli_ntcreate(cli1, fname_src, 0, GENERIC_ALL_ACCESS,
11570 FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
11571 0, 0, &fnum1, NULL);
11573 if (!NT_STATUS_IS_OK(status)) {
11574 d_printf("open %s failed: %s\n", fname_src, nt_errstr(status));
11578 /* Write file_size bytes - must be bigger than splice_size. */
11579 buf = talloc_zero_array(frame, uint8_t, file_size);
11581 d_printf("talloc_fail\n");
11585 /* Fill it with random numbers. */
11586 generate_random_buffer(buf, file_size);
11588 /* MD5 the first 1MB + 713 bytes. */
11589 gnutls_hash_fast(GNUTLS_DIG_MD5,
11594 status = cli_writeall(cli1,
11601 if (!NT_STATUS_IS_OK(status)) {
11602 d_printf("cli_writeall failed: %s\n", nt_errstr(status));
11606 status = cli_ntcreate(cli1, fname_dst, 0, GENERIC_ALL_ACCESS,
11607 FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
11608 0, 0, &fnum2, NULL);
11610 if (!NT_STATUS_IS_OK(status)) {
11611 d_printf("open %s failed: %s\n", fname_dst, nt_errstr(status));
11615 /* Now splice 1MB + 713 bytes. */
11616 status = cli_splice(cli1,
11627 if (!NT_STATUS_IS_OK(status)) {
11628 d_printf("cli_splice failed: %s\n", nt_errstr(status));
11632 /* Clear the old buffer. */
11633 memset(buf, '\0', file_size);
11635 /* Read the new file. */
11636 status = cli_read(cli1, fnum2, (char *)buf, 0, splice_size, &nread);
11637 if (!NT_STATUS_IS_OK(status)) {
11638 d_printf("cli_read failed: %s\n", nt_errstr(status));
11641 if (nread != splice_size) {
11642 d_printf("bad read of 0x%x, should be 0x%x\n",
11643 (unsigned int)nread,
11644 (unsigned int)splice_size);
11648 /* MD5 the first 1MB + 713 bytes. */
11649 gnutls_hash_fast(GNUTLS_DIG_MD5,
11654 /* Must be the same. */
11655 if (memcmp(digest1, digest2, 16) != 0) {
11656 d_printf("bad MD5 compare\n");
11661 printf("Success on cli_splice test\n");
11666 if (fnum1 != UINT16_MAX) {
11667 cli_close(cli1, fnum1);
11669 if (fnum2 != UINT16_MAX) {
11670 cli_close(cli1, fnum2);
11673 cli_unlink(cli1, fname_src,
11674 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
11675 cli_unlink(cli1, fname_dst,
11676 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
11678 if (!torture_close_connection(cli1)) {
11683 TALLOC_FREE(frame);
11687 static bool run_uid_regression_test(int dummy)
11689 static struct cli_state *cli;
11692 bool correct = True;
11693 struct smbXcli_tcon *tcon_copy = NULL;
11696 printf("starting uid regression test\n");
11698 if (!torture_open_connection(&cli, 0)) {
11702 smbXcli_conn_set_sockopt(cli->conn, sockops);
11704 /* Ok - now save then logoff our current user. */
11705 old_vuid = cli_state_get_uid(cli);
11707 status = cli_ulogoff(cli);
11708 if (!NT_STATUS_IS_OK(status)) {
11709 d_printf("(%s) cli_ulogoff failed: %s\n",
11710 __location__, nt_errstr(status));
11715 cli_state_set_uid(cli, old_vuid);
11717 /* Try an operation. */
11718 status = cli_mkdir(cli, "\\uid_reg_test");
11719 if (NT_STATUS_IS_OK(status)) {
11720 d_printf("(%s) cli_mkdir succeeded\n",
11725 /* Should be bad uid. */
11726 if (!check_error(__LINE__, status, ERRSRV, ERRbaduid,
11727 NT_STATUS_USER_SESSION_DELETED)) {
11733 old_cnum = cli_state_get_tid(cli);
11735 * This is an SMB1-only test.
11736 * Copy the tcon, not "save/restore".
11738 * In SMB1 the cli_tdis() below frees
11739 * cli->smb1.tcon so we need a copy
11740 * of the struct to put back for the
11741 * second tdis call with invalid vuid.
11743 * This is a test-only hack. Real client code
11744 * uses cli_state_save_tcon()/cli_state_restore_tcon().
11746 tcon_copy = smbXcli_tcon_copy(cli, cli->smb1.tcon);
11747 if (tcon_copy == NULL) {
11752 /* Now try a SMBtdis with the invalid vuid set to zero. */
11753 cli_state_set_uid(cli, 0);
11755 /* This should succeed. */
11756 status = cli_tdis(cli);
11758 if (NT_STATUS_IS_OK(status)) {
11759 d_printf("First tdis with invalid vuid should succeed.\n");
11761 d_printf("First tdis failed (%s)\n", nt_errstr(status));
11763 cli->smb1.tcon = tcon_copy;
11767 cli->smb1.tcon = tcon_copy;
11768 cli_state_set_uid(cli, old_vuid);
11769 cli_state_set_tid(cli, old_cnum);
11771 /* This should fail. */
11772 status = cli_tdis(cli);
11773 if (NT_STATUS_IS_OK(status)) {
11774 d_printf("Second tdis with invalid vuid should fail - succeeded instead !.\n");
11778 /* Should be bad tid. */
11779 if (!check_error(__LINE__, status, ERRSRV, ERRinvnid,
11780 NT_STATUS_NETWORK_NAME_DELETED)) {
11786 cli_rmdir(cli, "\\uid_reg_test");
11795 static const char *illegal_chars = "*\\/?<>|\":";
11796 static char force_shortname_chars[] = " +,.[];=\177";
11798 static NTSTATUS shortname_del_fn(struct file_info *finfo,
11799 const char *mask, void *state)
11801 struct cli_state *pcli = (struct cli_state *)state;
11803 NTSTATUS status = NT_STATUS_OK;
11805 slprintf(fname, sizeof(fname), "\\shortname\\%s", finfo->name);
11807 if (strcmp(finfo->name, ".") == 0 || strcmp(finfo->name, "..") == 0)
11808 return NT_STATUS_OK;
11810 if (finfo->attr & FILE_ATTRIBUTE_DIRECTORY) {
11811 status = cli_rmdir(pcli, fname);
11812 if (!NT_STATUS_IS_OK(status)) {
11813 printf("del_fn: failed to rmdir %s\n,", fname );
11816 status = cli_unlink(pcli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
11817 if (!NT_STATUS_IS_OK(status)) {
11818 printf("del_fn: failed to unlink %s\n,", fname );
11830 static NTSTATUS shortname_list_fn(struct file_info *finfo,
11831 const char *name, void *state)
11833 struct sn_state *s = (struct sn_state *)state;
11837 printf("shortname list: i = %d, name = |%s|, shortname = |%s|\n",
11838 i, finfo->name, finfo->short_name);
11841 if (strchr(force_shortname_chars, i)) {
11842 if (!finfo->short_name) {
11843 /* Shortname not created when it should be. */
11844 d_printf("(%s) ERROR: Shortname was not created for file %s containing %d\n",
11845 __location__, finfo->name, i);
11848 } else if (finfo->short_name){
11849 /* Shortname created when it should not be. */
11850 d_printf("(%s) ERROR: Shortname %s was created for file %s\n",
11851 __location__, finfo->short_name, finfo->name);
11855 return NT_STATUS_OK;
11858 static bool run_shortname_test(int dummy)
11860 static struct cli_state *cli;
11861 bool correct = True;
11867 printf("starting shortname test\n");
11869 if (!torture_open_connection(&cli, 0)) {
11873 smbXcli_conn_set_sockopt(cli->conn, sockops);
11875 cli_list(cli, "\\shortname\\*", 0, shortname_del_fn, cli);
11876 cli_list(cli, "\\shortname\\*", FILE_ATTRIBUTE_DIRECTORY, shortname_del_fn, cli);
11877 cli_rmdir(cli, "\\shortname");
11879 status = cli_mkdir(cli, "\\shortname");
11880 if (!NT_STATUS_IS_OK(status)) {
11881 d_printf("(%s) cli_mkdir of \\shortname failed: %s\n",
11882 __location__, nt_errstr(status));
11887 if (strlcpy(fname, "\\shortname\\", sizeof(fname)) >= sizeof(fname)) {
11891 if (strlcat(fname, "test .txt", sizeof(fname)) >= sizeof(fname)) {
11898 for (i = 32; i < 128; i++) {
11899 uint16_t fnum = (uint16_t)-1;
11903 if (strchr(illegal_chars, i)) {
11908 status = cli_ntcreate(cli, fname, 0, GENERIC_ALL_ACCESS, FILE_ATTRIBUTE_NORMAL,
11909 FILE_SHARE_READ|FILE_SHARE_WRITE,
11910 FILE_OVERWRITE_IF, 0, 0, &fnum, NULL);
11911 if (!NT_STATUS_IS_OK(status)) {
11912 d_printf("(%s) cli_nt_create of %s failed: %s\n",
11913 __location__, fname, nt_errstr(status));
11917 cli_close(cli, fnum);
11920 status = cli_list(cli, "\\shortname\\test*.*", 0,
11921 shortname_list_fn, &s);
11922 if (s.matched != 1) {
11923 d_printf("(%s) failed to list %s: %s\n",
11924 __location__, fname, nt_errstr(status));
11929 status = cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
11930 if (!NT_STATUS_IS_OK(status)) {
11931 d_printf("(%s) failed to delete %s: %s\n",
11932 __location__, fname, nt_errstr(status));
11945 cli_list(cli, "\\shortname\\*", 0, shortname_del_fn, cli);
11946 cli_list(cli, "\\shortname\\*", FILE_ATTRIBUTE_DIRECTORY, shortname_del_fn, cli);
11947 cli_rmdir(cli, "\\shortname");
11948 torture_close_connection(cli);
11952 TLDAPRC callback_code;
11954 static void pagedsearch_cb(struct tevent_req *req)
11957 struct tldap_message *msg;
11960 rc = tldap_search_paged_recv(req, talloc_tos(), &msg);
11961 if (!TLDAP_RC_IS_SUCCESS(rc)) {
11962 d_printf("tldap_search_paged_recv failed: %s\n",
11963 tldap_rc2string(rc));
11964 callback_code = rc;
11967 if (tldap_msg_type(msg) != TLDAP_RES_SEARCH_ENTRY) {
11971 if (!tldap_entry_dn(msg, &dn)) {
11972 d_printf("tldap_entry_dn failed\n");
11975 d_printf("%s\n", dn);
11979 enum tldap_extended_val {
11986 * Construct an extended dn control with either no value, 0 or 1
11988 * No value and 0 are equivalent (non-hyphenated GUID)
11989 * 1 has the hyphenated GUID
11991 static struct tldap_control *
11992 tldap_build_extended_control(enum tldap_extended_val val)
11994 struct tldap_control empty_control;
11995 struct asn1_data *data;
11997 ZERO_STRUCT(empty_control);
11999 if (val != EXTENDED_NONE) {
12000 data = asn1_init(talloc_tos(), ASN1_MAX_TREE_DEPTH);
12006 if (!asn1_push_tag(data, ASN1_SEQUENCE(0))) {
12010 if (!asn1_write_Integer(data, (int)val)) {
12014 if (!asn1_pop_tag(data)) {
12018 if (!asn1_blob(data, &empty_control.value)) {
12023 empty_control.oid = "1.2.840.113556.1.4.529";
12024 empty_control.critical = true;
12026 return tldap_add_control(talloc_tos(), NULL, 0, &empty_control);
12030 static bool tldap_test_dn_guid_format(struct tldap_context *ld, const char *basedn,
12031 enum tldap_extended_val control_val)
12033 struct tldap_control *control = tldap_build_extended_control(control_val);
12035 struct tldap_message **msg;
12038 rc = tldap_search(ld, basedn, TLDAP_SCOPE_BASE,
12039 "(objectClass=*)", NULL, 0, 0,
12041 0, 0, 0, 0, talloc_tos(), &msg);
12042 if (!TLDAP_RC_IS_SUCCESS(rc)) {
12043 d_printf("tldap_search for domain DN failed: %s\n",
12044 tldap_errstr(talloc_tos(), ld, rc));
12048 if (!tldap_entry_dn(msg[0], &dn)) {
12049 d_printf("tldap_search domain DN fetch failed: %s\n",
12050 tldap_errstr(talloc_tos(), ld, rc));
12054 d_printf("%s\n", dn);
12057 uint32_t time_mid, time_hi_and_version;
12058 uint32_t clock_seq[2];
12062 switch (control_val) {
12063 case EXTENDED_NONE:
12064 case EXTENDED_ZERO:
12066 * When reading GUIDs with hyphens, scanf will treat
12067 * hyphen as a hex character (and counts as part of the
12068 * width). This creates leftover GUID string which we
12069 * check will for with 'next' and closing '>'.
12071 if (12 == sscanf(dn, "<GUID=%08x%04x%04x%02x%02x%02x%02x%02x%02x%02x%02x>%c",
12072 &time_low, &time_mid,
12073 &time_hi_and_version, &clock_seq[0],
12074 &clock_seq[1], &node[0], &node[1],
12075 &node[2], &node[3], &node[4],
12076 &node[5], &next)) {
12077 /* This GUID is good */
12079 d_printf("GUID format in control (no hyphens) doesn't match output\n");
12085 if (12 == sscanf(dn,
12086 "<GUID=%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x>%c",
12087 &time_low, &time_mid,
12088 &time_hi_and_version, &clock_seq[0],
12089 &clock_seq[1], &node[0], &node[1],
12090 &node[2], &node[3], &node[4],
12091 &node[5], &next)) {
12092 /* This GUID is good */
12094 d_printf("GUID format in control (with hyphens) doesn't match output\n");
12107 static bool run_tldap(int dummy)
12109 struct tldap_context *ld;
12113 struct sockaddr_storage addr;
12114 struct tevent_context *ev;
12115 struct tevent_req *req;
12117 const char *filter;
12119 if (!resolve_name(host, &addr, 0, false)) {
12120 d_printf("could not find host %s\n", host);
12123 status = open_socket_out(&addr, 389, 9999, &fd);
12124 if (!NT_STATUS_IS_OK(status)) {
12125 d_printf("open_socket_out failed: %s\n", nt_errstr(status));
12129 ld = tldap_context_create(talloc_tos(), fd);
12132 d_printf("tldap_context_create failed\n");
12136 rc = tldap_fetch_rootdse(ld);
12137 if (!TLDAP_RC_IS_SUCCESS(rc)) {
12138 d_printf("tldap_fetch_rootdse failed: %s\n",
12139 tldap_errstr(talloc_tos(), ld, rc));
12143 basedn = tldap_talloc_single_attribute(
12144 tldap_rootdse(ld), "defaultNamingContext", talloc_tos());
12145 if (basedn == NULL) {
12146 d_printf("no defaultNamingContext\n");
12149 d_printf("defaultNamingContext: %s\n", basedn);
12151 ev = samba_tevent_context_init(talloc_tos());
12153 d_printf("tevent_context_init failed\n");
12157 rc = tldap_gensec_bind(ld, torture_creds, "ldap", host, NULL,
12158 loadparm_init_s3(talloc_tos(),
12159 loadparm_s3_helpers()),
12160 GENSEC_FEATURE_SIGN | GENSEC_FEATURE_SEAL);
12162 if (!TLDAP_RC_IS_SUCCESS(rc)) {
12163 d_printf("tldap_gensec_bind failed\n");
12167 callback_code = TLDAP_SUCCESS;
12169 req = tldap_search_paged_send(talloc_tos(), ev, ld, basedn,
12170 TLDAP_SCOPE_SUB, "(objectclass=*)",
12172 NULL, 0, NULL, 0, 0, 0, 0, 5);
12174 d_printf("tldap_search_paged_send failed\n");
12177 tevent_req_set_callback(req, pagedsearch_cb, NULL);
12179 tevent_req_poll(req, ev);
12183 rc = callback_code;
12185 if (!TLDAP_RC_IS_SUCCESS(rc)) {
12186 d_printf("tldap_search with paging failed: %s\n",
12187 tldap_errstr(talloc_tos(), ld, rc));
12191 /* test search filters against rootDSE */
12192 filter = "(&(|(name=samba)(nextRid<=10000000)(usnChanged>=10)(samba~=ambas)(!(name=s*m*a)))"
12193 "(|(name:=samba)(name:dn:2.5.13.5:=samba)(:dn:2.5.13.5:=samba)(!(name=*samba))))";
12195 rc = tldap_search(ld, "", TLDAP_SCOPE_BASE, filter,
12196 NULL, 0, 0, NULL, 0, NULL, 0, 0, 0, 0,
12197 talloc_tos(), NULL);
12198 if (!TLDAP_RC_IS_SUCCESS(rc)) {
12199 d_printf("tldap_search with complex filter failed: %s\n",
12200 tldap_errstr(talloc_tos(), ld, rc));
12205 * Tests to check for regression of:
12207 * https://bugzilla.samba.org/show_bug.cgi?id=14029
12209 * TLDAP used here to pick apart the original string DN (with GUID)
12211 if (!tldap_test_dn_guid_format(ld, basedn, EXTENDED_NONE)) {
12212 d_printf("tldap_search with extended dn (no val) failed: %s\n",
12213 tldap_errstr(talloc_tos(), ld, rc));
12216 if (!tldap_test_dn_guid_format(ld, basedn, EXTENDED_ZERO)) {
12217 d_printf("tldap_search with extended dn (0) failed: %s\n",
12218 tldap_errstr(talloc_tos(), ld, rc));
12221 if (!tldap_test_dn_guid_format(ld, basedn, EXTENDED_ONE)) {
12222 d_printf("tldap_search with extended dn (1) failed: %s\n",
12223 tldap_errstr(talloc_tos(), ld, rc));
12231 /* Torture test to ensure no regression of :
12232 https://bugzilla.samba.org/show_bug.cgi?id=7084
12235 static bool run_dir_createtime(int dummy)
12237 struct cli_state *cli;
12238 const char *dname = "\\testdir_createtime";
12239 const char *fname = "\\testdir_createtime\\testfile";
12241 struct timespec create_time;
12242 struct timespec create_time1;
12247 if (!torture_open_connection(&cli, 0)) {
12251 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
12252 /* Ensure ino is zero, SMB2 gets a real one. */
12255 /* Ensure ino is -1, SMB1 never gets a real one. */
12256 ino = (uint64_t)-1;
12259 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
12260 cli_rmdir(cli, dname);
12262 status = cli_mkdir(cli, dname);
12263 if (!NT_STATUS_IS_OK(status)) {
12264 printf("mkdir failed: %s\n", nt_errstr(status));
12268 status = cli_qpathinfo2(cli, dname, &create_time, NULL, NULL, NULL,
12270 if (!NT_STATUS_IS_OK(status)) {
12271 printf("cli_qpathinfo2 returned %s\n",
12272 nt_errstr(status));
12276 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
12277 /* SMB2 should always return an inode. */
12279 printf("SMB2 bad inode (0)\n");
12283 /* SMB1 must always return zero here. */
12285 printf("SMB1 bad inode (!0)\n");
12290 /* Sleep 3 seconds, then create a file. */
12293 status = cli_openx(cli, fname, O_RDWR | O_CREAT | O_EXCL,
12295 if (!NT_STATUS_IS_OK(status)) {
12296 printf("cli_openx failed: %s\n", nt_errstr(status));
12300 status = cli_qpathinfo2(cli, dname, &create_time1, NULL, NULL, NULL,
12302 if (!NT_STATUS_IS_OK(status)) {
12303 printf("cli_qpathinfo2 (2) returned %s\n",
12304 nt_errstr(status));
12308 if (timespec_compare(&create_time1, &create_time)) {
12309 printf("run_dir_createtime: create time was updated (error)\n");
12311 printf("run_dir_createtime: create time was not updated (correct)\n");
12317 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
12318 cli_rmdir(cli, dname);
12319 if (!torture_close_connection(cli)) {
12326 static bool run_streamerror(int dummy)
12328 struct cli_state *cli;
12329 const char *dname = "\\testdir_streamerror";
12330 const char *streamname =
12331 "testdir_streamerror:{4c8cc155-6c1e-11d1-8e41-00c04fb9386d}:$DATA";
12333 time_t change_time, access_time, write_time;
12339 if (!torture_open_connection(&cli, 0)) {
12343 cli_unlink(cli, "\\testdir_streamerror\\*", FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
12344 cli_rmdir(cli, dname);
12346 status = cli_mkdir(cli, dname);
12347 if (!NT_STATUS_IS_OK(status)) {
12348 printf("mkdir failed: %s\n", nt_errstr(status));
12352 status = cli_qpathinfo1(cli, streamname, &change_time, &access_time,
12353 &write_time, &size, &attr);
12354 if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
12355 printf("pathinfo returned %s, expected "
12356 "NT_STATUS_OBJECT_NAME_NOT_FOUND\n",
12357 nt_errstr(status));
12361 status = cli_ntcreate(cli, streamname, 0x16,
12362 FILE_READ_DATA|FILE_READ_EA|
12363 FILE_READ_ATTRIBUTES|READ_CONTROL_ACCESS,
12364 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ,
12365 FILE_OPEN, 0, 0, &fnum, NULL);
12367 if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
12368 printf("ntcreate returned %s, expected "
12369 "NT_STATUS_OBJECT_NAME_NOT_FOUND\n",
12370 nt_errstr(status));
12375 cli_rmdir(cli, dname);
12379 struct pidtest_state {
12385 static void pid_echo_done(struct tevent_req *subreq);
12387 static struct tevent_req *pid_echo_send(TALLOC_CTX *mem_ctx,
12388 struct tevent_context *ev,
12389 struct cli_state *cli)
12391 struct tevent_req *req, *subreq;
12392 struct pidtest_state *state;
12394 req = tevent_req_create(mem_ctx, &state, struct pidtest_state);
12399 SSVAL(state->vwv, 0, 1);
12400 state->data = data_blob_const("hello", 5);
12402 subreq = smb1cli_req_send(state,
12406 0, 0, /* *_flags */
12407 0, 0, /* *_flags2 */
12409 0xDEADBEEF, /* pid */
12411 NULL, /* session */
12412 ARRAY_SIZE(state->vwv), state->vwv,
12413 state->data.length, state->data.data);
12415 if (tevent_req_nomem(subreq, req)) {
12416 return tevent_req_post(req, ev);
12418 tevent_req_set_callback(subreq, pid_echo_done, req);
12422 static void pid_echo_done(struct tevent_req *subreq)
12424 struct tevent_req *req = tevent_req_callback_data(
12425 subreq, struct tevent_req);
12426 struct pidtest_state *state = tevent_req_data(
12427 req, struct pidtest_state);
12429 uint32_t num_bytes;
12430 uint8_t *bytes = NULL;
12431 struct iovec *recv_iov = NULL;
12432 uint8_t *phdr = NULL;
12433 uint16_t pidlow = 0;
12434 uint16_t pidhigh = 0;
12435 struct smb1cli_req_expected_response expected[] = {
12437 .status = NT_STATUS_OK,
12442 status = smb1cli_req_recv(subreq, state,
12447 NULL, /* pvwv_offset */
12450 NULL, /* pbytes_offset */
12452 expected, ARRAY_SIZE(expected));
12454 TALLOC_FREE(subreq);
12456 if (!NT_STATUS_IS_OK(status)) {
12457 tevent_req_nterror(req, status);
12461 if (num_bytes != state->data.length) {
12462 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
12466 if (memcmp(bytes, state->data.data, num_bytes) != 0) {
12467 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
12471 /* Check pid low/high == DEADBEEF */
12472 pidlow = SVAL(phdr, HDR_PID);
12473 if (pidlow != 0xBEEF){
12474 printf("Incorrect pidlow 0x%x, should be 0xBEEF\n",
12475 (unsigned int)pidlow);
12476 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
12479 pidhigh = SVAL(phdr, HDR_PIDHIGH);
12480 if (pidhigh != 0xDEAD){
12481 printf("Incorrect pidhigh 0x%x, should be 0xDEAD\n",
12482 (unsigned int)pidhigh);
12483 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
12487 tevent_req_done(req);
12490 static NTSTATUS pid_echo_recv(struct tevent_req *req)
12492 return tevent_req_simple_recv_ntstatus(req);
12495 static bool run_pidhigh(int dummy)
12497 bool success = false;
12498 struct cli_state *cli = NULL;
12500 struct tevent_context *ev = NULL;
12501 struct tevent_req *req = NULL;
12502 TALLOC_CTX *frame = talloc_stackframe();
12504 printf("starting pid high test\n");
12505 if (!torture_open_connection(&cli, 0)) {
12508 smbXcli_conn_set_sockopt(cli->conn, sockops);
12510 ev = samba_tevent_context_init(frame);
12515 req = pid_echo_send(frame, ev, cli);
12520 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
12524 status = pid_echo_recv(req);
12525 if (NT_STATUS_IS_OK(status)) {
12526 printf("pid high test ok\n");
12532 TALLOC_FREE(frame);
12533 torture_close_connection(cli);
12538 Test Windows open on a bad POSIX symlink.
12540 static bool run_symlink_open_test(int dummy)
12542 static struct cli_state *cli;
12543 const char *fname = "non_existant_file";
12544 const char *sname = "dangling_symlink";
12545 uint16_t fnum = (uint16_t)-1;
12546 bool correct = false;
12548 TALLOC_CTX *frame = NULL;
12550 frame = talloc_stackframe();
12552 printf("Starting Windows bad symlink open test\n");
12554 if (!torture_open_connection(&cli, 0)) {
12555 TALLOC_FREE(frame);
12559 smbXcli_conn_set_sockopt(cli->conn, sockops);
12561 status = torture_setup_unix_extensions(cli);
12562 if (!NT_STATUS_IS_OK(status)) {
12563 TALLOC_FREE(frame);
12567 /* Ensure nothing exists. */
12568 cli_setatr(cli, fname, 0, 0);
12569 cli_posix_unlink(cli, fname);
12570 cli_setatr(cli, sname, 0, 0);
12571 cli_posix_unlink(cli, sname);
12573 /* Create a symlink pointing nowhere. */
12574 status = cli_posix_symlink(cli, fname, sname);
12575 if (!NT_STATUS_IS_OK(status)) {
12576 printf("cli_posix_symlink of %s -> %s failed (%s)\n",
12579 nt_errstr(status));
12583 /* Now ensure that a Windows open doesn't hang. */
12584 status = cli_ntcreate(cli,
12587 FILE_READ_DATA|FILE_WRITE_DATA,
12589 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
12597 * We get either NT_STATUS_OBJECT_NAME_NOT_FOUND or
12598 * NT_STATUS_OBJECT_PATH_NOT_FOUND depending on if
12599 * we use O_NOFOLLOW on the server or not.
12601 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND) ||
12602 NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_PATH_NOT_FOUND))
12606 printf("cli_ntcreate of %s returned %s - should return"
12607 " either (%s) or (%s)\n",
12610 nt_errstr(NT_STATUS_OBJECT_NAME_NOT_FOUND),
12611 nt_errstr(NT_STATUS_OBJECT_PATH_NOT_FOUND));
12619 if (fnum != (uint16_t)-1) {
12620 cli_close(cli, fnum);
12621 fnum = (uint16_t)-1;
12624 cli_setatr(cli, sname, 0, 0);
12625 cli_posix_unlink(cli, sname);
12626 cli_setatr(cli, fname, 0, 0);
12627 cli_posix_unlink(cli, fname);
12629 if (!torture_close_connection(cli)) {
12633 TALLOC_FREE(frame);
12637 static NTSTATUS smb1_wild_mangle_list_fn(struct file_info *finfo,
12641 char **mangled_name_return = (char **)state;
12642 bool is_mangled = strchr(finfo->name, '~');
12645 *mangled_name_return = talloc_strdup(NULL, finfo->name);
12646 if (*mangled_name_return == NULL) {
12647 return NT_STATUS_NO_MEMORY;
12650 return NT_STATUS_OK;
12653 static bool run_smb1_wild_mangle_unlink_test(int dummy)
12655 static struct cli_state *cli_posix = NULL;
12656 static struct cli_state *cli = NULL;
12657 uint16_t fnum = (uint16_t)-1;
12658 bool correct = false;
12659 const char *dname = "smb1_wild_mangle_unlink";
12660 const char *aname = "smb1_wild_mangle_unlink/a";
12661 const char *star_name = "smb1_wild_mangle_unlink/*";
12662 char *windows_unlink_name = NULL;
12663 char *mangled_name = NULL;
12666 printf("Starting SMB1 wild mangle unlink test\n");
12668 /* Open a Windows connection. */
12669 if (!torture_open_connection(&cli, 0)) {
12673 smbXcli_conn_set_sockopt(cli->conn, sockops);
12675 /* Open a POSIX connection. */
12676 if (!torture_open_connection(&cli_posix, 0)) {
12680 smbXcli_conn_set_sockopt(cli_posix->conn, sockops);
12682 status = torture_setup_unix_extensions(cli_posix);
12683 if (!NT_STATUS_IS_OK(status)) {
12684 printf("server doesn't support POSIX\n");
12691 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
12692 cli_rmdir(cli, dname);
12695 * Create two files - 'a' and '*'.
12696 * We need POSIX extensions for this as '*'
12697 * is not a valid Windows name.
12700 status = cli_mkdir(cli, dname);
12701 if (!NT_STATUS_IS_OK(status)) {
12702 printf("cli_mkdir of %s returned %s\n",
12704 nt_errstr(status));
12708 status = cli_posix_open(cli_posix,
12710 O_RDWR|O_CREAT|O_EXCL,
12713 if (!NT_STATUS_IS_OK(status)) {
12714 printf("cli_posix_open (create) of %s returned %s\n",
12716 nt_errstr(status));
12719 status = cli_close(cli_posix, fnum);
12720 if (!NT_STATUS_IS_OK(status)) {
12723 status = cli_posix_open(cli_posix,
12725 O_RDWR|O_CREAT|O_EXCL,
12728 if (!NT_STATUS_IS_OK(status)) {
12729 printf("cli_posix_open (create) of %s returned %s\n",
12731 nt_errstr(status));
12734 status = cli_close(cli_posix, fnum);
12735 if (!NT_STATUS_IS_OK(status)) {
12739 status = cli_list(cli,
12742 smb1_wild_mangle_list_fn,
12744 if (!NT_STATUS_IS_OK(status)) {
12745 printf("cli_list of %s returned %s\n",
12747 nt_errstr(status));
12751 if (mangled_name == NULL) {
12755 printf("mangled_name = %s\n",
12759 * Try a Windows unlink with the mangled name.
12760 * This should *NOT* unlink the 'a' name.
12763 windows_unlink_name = talloc_asprintf(cli_posix,
12768 status = cli_unlink(cli, windows_unlink_name, 0);
12769 if (!NT_STATUS_IS_OK(status)) {
12770 printf("cli_unlink of %s returned %s\n",
12771 windows_unlink_name,
12772 nt_errstr(status));
12776 /* Does 'a' still exist ? */
12777 status = cli_posix_open(cli_posix,
12782 if (!NT_STATUS_IS_OK(status)) {
12783 printf("cli_posix_open O_RNONLY of %s returned %s\n",
12785 nt_errstr(status));
12789 status = cli_close(cli_posix, fnum);
12790 if (!NT_STATUS_IS_OK(status)) {
12798 TALLOC_FREE(windows_unlink_name);
12799 TALLOC_FREE(mangled_name);
12804 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
12805 cli_rmdir(cli, dname);
12806 torture_close_connection(cli);
12809 if (cli_posix != NULL) {
12810 torture_close_connection(cli_posix);
12816 static bool run_smb1_wild_mangle_rename_test(int dummy)
12818 static struct cli_state *cli_posix = NULL;
12819 static struct cli_state *cli = NULL;
12820 uint16_t fnum = (uint16_t)-1;
12821 bool correct = false;
12822 const char *dname = "smb1_wild_mangle_rename";
12823 const char *fooname = "smb1_wild_mangle_rename/foo";
12824 const char *foostar_name = "smb1_wild_mangle_rename/fo*";
12825 const char *wild_name = "smb1_wild_mangle_rename/*";
12826 char *windows_rename_src = NULL;
12827 const char *windows_rename_dst = "smb1_wild_mangle_rename\\ba*";
12828 char *mangled_name = NULL;
12831 printf("Starting SMB1 wild mangle rename test\n");
12833 if (!torture_open_connection(&cli_posix, 0)) {
12837 smbXcli_conn_set_sockopt(cli_posix->conn, sockops);
12839 status = torture_setup_unix_extensions(cli_posix);
12840 if (!NT_STATUS_IS_OK(status)) {
12841 printf("server doesn't support POSIX\n");
12845 /* Open a Windows connection. */
12846 if (!torture_open_connection(&cli, 0)) {
12850 smbXcli_conn_set_sockopt(cli->conn, sockops);
12852 /* Ensure we start from fresh. */
12855 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
12856 cli_posix_rmdir(cli_posix, dname);
12859 * Create two files - 'foo' and 'fo*'.
12860 * We need POSIX extensions for this as 'fo*'
12861 * is not a valid Windows name.
12864 status = cli_posix_mkdir(cli_posix, dname, 0770);
12865 if (!NT_STATUS_IS_OK(status)) {
12866 printf("cli_posix_mkdir of %s returned %s\n",
12868 nt_errstr(status));
12872 status = cli_posix_open(cli_posix,
12874 O_RDWR|O_CREAT|O_EXCL,
12877 if (!NT_STATUS_IS_OK(status)) {
12878 printf("cli_posix_open (create) of %s returned %s\n",
12880 nt_errstr(status));
12883 status = cli_close(cli_posix, fnum);
12884 if (!NT_STATUS_IS_OK(status)) {
12887 status = cli_posix_open(cli_posix,
12889 O_RDWR|O_CREAT|O_EXCL,
12892 if (!NT_STATUS_IS_OK(status)) {
12893 printf("cli_posix_open (create) of %s returned %s\n",
12895 nt_errstr(status));
12898 status = cli_close(cli_posix, fnum);
12899 if (!NT_STATUS_IS_OK(status)) {
12904 * Get the mangled name. We can re-use the
12905 * previous smb1_wild_mangle_list_fn for this.
12908 status = cli_list(cli,
12911 smb1_wild_mangle_list_fn,
12913 if (!NT_STATUS_IS_OK(status)) {
12914 printf("cli_list of %s returned %s\n",
12916 nt_errstr(status));
12920 if (mangled_name == NULL) {
12924 printf("mangled_name = %s\n",
12928 * Try a Windows rename with the mangled name.
12929 * This should *NOT* rename the 'foo' name.
12932 windows_rename_src = talloc_asprintf(cli_posix,
12937 status = cli_rename(cli,
12938 windows_rename_src,
12939 windows_rename_dst,
12941 if (!NT_STATUS_IS_OK(status)) {
12942 printf("cli_rename of %s -> %s returned %s\n",
12943 windows_rename_src,
12944 windows_rename_dst,
12945 nt_errstr(status));
12949 /* Does 'foo' still exist ? */
12950 status = cli_posix_open(cli_posix,
12955 if (!NT_STATUS_IS_OK(status)) {
12956 printf("cli_posix_open O_RNONLY of %s returned %s\n",
12958 nt_errstr(status));
12962 status = cli_close(cli_posix, fnum);
12963 if (!NT_STATUS_IS_OK(status)) {
12971 TALLOC_FREE(mangled_name);
12972 TALLOC_FREE(windows_rename_src);
12977 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
12978 torture_close_connection(cli);
12981 cli_posix_rmdir(cli_posix, dname);
12982 torture_close_connection(cli_posix);
12988 * Only testing minimal time strings, as the others
12989 * need (locale-dependent) guessing at what strftime does and
12990 * even may differ in builds.
12992 static bool timesubst_test(void)
12994 TALLOC_CTX *ctx = NULL;
12995 /* Sa 23. Dez 04:33:20 CET 2017 */
12996 const struct timeval tv = { 1514000000, 123 };
12997 const char* expect_minimal = "20171223_033320";
12998 const char* expect_minus = "20171223_033320_000123";
13000 char *env_tz, *orig_tz = NULL;
13001 bool result = true;
13003 ctx = talloc_new(NULL);
13005 env_tz = getenv("TZ");
13007 orig_tz = talloc_strdup(ctx, env_tz);
13009 setenv("TZ", "UTC", 1);
13011 s = minimal_timeval_string(ctx, &tv, false);
13013 if(!s || strcmp(s, expect_minimal)) {
13014 printf("minimal_timeval_string(ctx, tv, false) returned [%s], expected "
13015 "[%s]\n", s ? s : "<nil>", expect_minimal);
13019 s = minimal_timeval_string(ctx, &tv, true);
13020 if(!s || strcmp(s, expect_minus)) {
13021 printf("minimal_timeval_string(ctx, tv, true) returned [%s], expected "
13022 "[%s]\n", s ? s : "<nil>", expect_minus);
13028 setenv("TZ", orig_tz, 1);
13035 static bool run_local_substitute(int dummy)
13039 ok &= subst_test("%U", "bla", "", -1, -1, "bla");
13040 ok &= subst_test("%u%U", "bla", "", -1, -1, "blabla");
13041 ok &= subst_test("%g", "", "", -1, -1, "NO_GROUP");
13042 ok &= subst_test("%G", "", "", -1, -1, "NO_GROUP");
13043 ok &= subst_test("%g", "", "", -1, 0, gidtoname(0));
13044 ok &= subst_test("%G", "", "", -1, 0, gidtoname(0));
13045 ok &= subst_test("%D%u", "u", "dom", -1, 0, "domu");
13046 ok &= subst_test("%i %I", "", "", -1, -1, "0.0.0.0 0.0.0.0");
13047 ok &= subst_test("%j %J", "", "", -1, -1, "0_0_0_0 0_0_0_0");
13048 /* Substitution depends on current time, so better test the underlying
13049 formatting function. At least covers %t. */
13050 ok &= timesubst_test();
13052 /* Different captialization rules in sub_basic... */
13054 ok &= (strcmp(talloc_sub_basic(talloc_tos(), "BLA", "dom", "%U%D"),
13060 static bool run_local_base64(int dummy)
13065 for (i=1; i<2000; i++) {
13066 DATA_BLOB blob1, blob2;
13069 blob1.data = talloc_array(talloc_tos(), uint8_t, i);
13071 generate_random_buffer(blob1.data, blob1.length);
13073 b64 = base64_encode_data_blob(talloc_tos(), blob1);
13075 d_fprintf(stderr, "base64_encode_data_blob failed "
13076 "for %d bytes\n", i);
13079 blob2 = base64_decode_data_blob(b64);
13082 if (data_blob_cmp(&blob1, &blob2)) {
13083 d_fprintf(stderr, "data_blob_cmp failed for %d "
13087 TALLOC_FREE(blob1.data);
13088 data_blob_free(&blob2);
13093 static void parse_fn(const struct gencache_timeout *t,
13095 void *private_data)
13100 static bool run_local_gencache(int dummy)
13106 struct memcache *mem;
13109 mem = memcache_init(NULL, 0);
13111 d_printf("%s: memcache_init failed\n", __location__);
13114 memcache_set_global(mem);
13116 if (!gencache_set("foo", "bar", time(NULL) + 1000)) {
13117 d_printf("%s: gencache_set() failed\n", __location__);
13121 if (!gencache_get("foo", NULL, NULL, NULL)) {
13122 d_printf("%s: gencache_get() failed\n", __location__);
13126 for (i=0; i<1000000; i++) {
13127 gencache_parse("foo", parse_fn, NULL);
13130 if (!gencache_get("foo", talloc_tos(), &val, &tm)) {
13131 d_printf("%s: gencache_get() failed\n", __location__);
13136 if (!gencache_get("foo", talloc_tos(), &val, &tm)) {
13137 d_printf("%s: gencache_get() failed\n", __location__);
13141 if (strcmp(val, "bar") != 0) {
13142 d_printf("%s: gencache_get() returned %s, expected %s\n",
13143 __location__, val, "bar");
13150 if (!gencache_del("foo")) {
13151 d_printf("%s: gencache_del() failed\n", __location__);
13154 if (gencache_del("foo")) {
13155 d_printf("%s: second gencache_del() succeeded\n",
13160 if (gencache_get("foo", talloc_tos(), &val, &tm)) {
13161 d_printf("%s: gencache_get() on deleted entry "
13162 "succeeded\n", __location__);
13166 blob = data_blob_string_const_null("bar");
13167 tm = time(NULL) + 60;
13169 if (!gencache_set_data_blob("foo", blob, tm)) {
13170 d_printf("%s: gencache_set_data_blob() failed\n", __location__);
13174 if (!gencache_get_data_blob("foo", talloc_tos(), &blob, NULL, NULL)) {
13175 d_printf("%s: gencache_get_data_blob() failed\n", __location__);
13179 if (strcmp((const char *)blob.data, "bar") != 0) {
13180 d_printf("%s: gencache_get_data_blob() returned %s, expected %s\n",
13181 __location__, (const char *)blob.data, "bar");
13182 data_blob_free(&blob);
13186 data_blob_free(&blob);
13188 if (!gencache_del("foo")) {
13189 d_printf("%s: gencache_del() failed\n", __location__);
13192 if (gencache_del("foo")) {
13193 d_printf("%s: second gencache_del() succeeded\n",
13198 if (gencache_get_data_blob("foo", talloc_tos(), &blob, NULL, NULL)) {
13199 d_printf("%s: gencache_get_data_blob() on deleted entry "
13200 "succeeded\n", __location__);
13205 blob.data = (uint8_t *)&v;
13206 blob.length = sizeof(v);
13208 if (!gencache_set_data_blob("blob", blob, tm)) {
13209 d_printf("%s: gencache_set_data_blob() failed\n",
13213 if (gencache_get("blob", talloc_tos(), &val, &tm)) {
13214 d_printf("%s: gencache_get succeeded\n", __location__);
13221 static bool rbt_testflags(struct db_context *db, const char *key,
13226 struct db_record *rec;
13228 rec = dbwrap_fetch_locked(db, db, string_tdb_data(key));
13230 d_fprintf(stderr, "fetch_locked failed\n");
13234 status = dbwrap_record_store(rec, string_tdb_data(value), TDB_MODIFY);
13235 if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
13236 d_fprintf(stderr, "store TDB_MODIFY unexpected status: %s\n",
13237 nt_errstr(status));
13241 status = dbwrap_record_store(rec, string_tdb_data("overwriteme"),
13243 if (!NT_STATUS_IS_OK(status)) {
13244 d_fprintf(stderr, "store TDB_INSERT failed: %s\n",
13245 nt_errstr(status));
13249 status = dbwrap_record_store(rec, string_tdb_data(value), TDB_INSERT);
13250 if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_COLLISION)) {
13251 d_fprintf(stderr, "store TDB_INSERT unexpected status: %s\n",
13252 nt_errstr(status));
13256 status = dbwrap_record_store(rec, string_tdb_data(value), TDB_MODIFY);
13257 if (!NT_STATUS_IS_OK(status)) {
13258 d_fprintf(stderr, "store TDB_MODIFY failed: %s\n",
13259 nt_errstr(status));
13269 static bool rbt_testval(struct db_context *db, const char *key,
13272 struct db_record *rec;
13273 TDB_DATA data = string_tdb_data(value);
13278 rec = dbwrap_fetch_locked(db, db, string_tdb_data(key));
13280 d_fprintf(stderr, "fetch_locked failed\n");
13283 status = dbwrap_record_store(rec, data, 0);
13284 if (!NT_STATUS_IS_OK(status)) {
13285 d_fprintf(stderr, "store failed: %s\n", nt_errstr(status));
13290 rec = dbwrap_fetch_locked(db, db, string_tdb_data(key));
13292 d_fprintf(stderr, "second fetch_locked failed\n");
13296 dbvalue = dbwrap_record_get_value(rec);
13297 if ((dbvalue.dsize != data.dsize)
13298 || (memcmp(dbvalue.dptr, data.dptr, data.dsize) != 0)) {
13299 d_fprintf(stderr, "Got wrong data back\n");
13309 static int local_rbtree_traverse_read(struct db_record *rec, void *private_data)
13311 int *count2 = (int *)private_data;
13316 static int local_rbtree_traverse_delete(struct db_record *rec, void *private_data)
13318 int *count2 = (int *)private_data;
13320 dbwrap_record_delete(rec);
13324 static bool run_local_rbtree(int dummy)
13326 struct db_context *db;
13333 db = db_open_rbt(NULL);
13336 d_fprintf(stderr, "db_open_rbt failed\n");
13340 if (!rbt_testflags(db, "firstkey", "firstval")) {
13344 for (i = 0; i < 999; i++) {
13345 char key[sizeof("key-9223372036854775807")];
13346 char value[sizeof("value-9223372036854775807")];
13348 snprintf(key, sizeof(key), "key%ld", random());
13349 snprintf(value, sizeof(value) ,"value%ld", random());
13351 if (!rbt_testval(db, key, value)) {
13355 snprintf(value, sizeof(value) ,"value%ld", random());
13357 if (!rbt_testval(db, key, value)) {
13363 count = 0; count2 = 0;
13364 status = dbwrap_traverse_read(db, local_rbtree_traverse_read,
13366 printf("%s: read1: %d %d, %s\n", __func__, count, count2, nt_errstr(status));
13367 if ((count != count2) || (count != 1000)) {
13370 count = 0; count2 = 0;
13371 status = dbwrap_traverse(db, local_rbtree_traverse_delete,
13373 printf("%s: delete: %d %d, %s\n", __func__, count, count2, nt_errstr(status));
13374 if ((count != count2) || (count != 1000)) {
13377 count = 0; count2 = 0;
13378 status = dbwrap_traverse_read(db, local_rbtree_traverse_read,
13380 printf("%s: read2: %d %d, %s\n", __func__, count, count2, nt_errstr(status));
13381 if ((count != count2) || (count != 0)) {
13392 local test for character set functions
13394 This is a very simple test for the functionality in convert_string_error()
13396 static bool run_local_convert_string(int dummy)
13398 TALLOC_CTX *tmp_ctx = talloc_new(NULL);
13399 const char *test_strings[2] = { "March", "M\303\244rz" };
13403 for (i=0; i<2; i++) {
13404 const char *str = test_strings[i];
13405 int len = strlen(str);
13406 size_t converted_size;
13409 memset(dst, 'X', sizeof(dst));
13411 /* first try with real source length */
13412 ret = convert_string_error(CH_UNIX, CH_UTF8,
13417 d_fprintf(stderr, "Failed to convert '%s' to CH_DISPLAY\n", str);
13421 if (converted_size != len) {
13422 d_fprintf(stderr, "Converted size of '%s' should be %d - got %d\n",
13423 str, len, (int)converted_size);
13427 if (strncmp(str, dst, converted_size) != 0) {
13428 d_fprintf(stderr, "Expected '%s' to match '%s'\n", str, dst);
13432 if (strlen(str) != converted_size) {
13433 d_fprintf(stderr, "Expected '%s' length %d - got %d\n", str,
13434 (int)strlen(str), (int)converted_size);
13438 if (dst[converted_size] != 'X') {
13439 d_fprintf(stderr, "Expected no termination of '%s'\n", dst);
13443 /* now with srclen==-1, this causes the nul to be
13445 ret = convert_string_error(CH_UNIX, CH_UTF8,
13450 d_fprintf(stderr, "Failed to convert '%s' to CH_DISPLAY\n", str);
13454 if (converted_size != len+1) {
13455 d_fprintf(stderr, "Converted size of '%s' should be %d - got %d\n",
13456 str, len, (int)converted_size);
13460 if (strncmp(str, dst, converted_size) != 0) {
13461 d_fprintf(stderr, "Expected '%s' to match '%s'\n", str, dst);
13465 if (len+1 != converted_size) {
13466 d_fprintf(stderr, "Expected '%s' length %d - got %d\n", str,
13467 len+1, (int)converted_size);
13471 if (dst[converted_size] != 'X') {
13472 d_fprintf(stderr, "Expected no termination of '%s'\n", dst);
13479 TALLOC_FREE(tmp_ctx);
13482 TALLOC_FREE(tmp_ctx);
13486 static bool run_local_string_to_sid(int dummy) {
13487 struct dom_sid sid;
13489 if (string_to_sid(&sid, "S--1-5-32-545")) {
13490 printf("allowing S--1-5-32-545\n");
13493 if (string_to_sid(&sid, "S-1-5-32-+545")) {
13494 printf("allowing S-1-5-32-+545\n");
13497 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")) {
13498 printf("allowing S-1-2-3-4-5-6-7-8-9-0-1-2-3-4-5-6-7-8-9-0\n");
13501 if (string_to_sid(&sid, "S-1-5-32-545-abc")) {
13502 printf("allowing S-1-5-32-545-abc\n");
13505 if (string_to_sid(&sid, "S-300-5-32-545")) {
13506 printf("allowing S-300-5-32-545\n");
13509 if (string_to_sid(&sid, "S-1-0xfffffffffffffe-32-545")) {
13510 printf("allowing S-1-0xfffffffffffffe-32-545\n");
13513 if (string_to_sid(&sid, "S-1-0xffffffffffff-5294967297-545")) {
13514 printf("allowing S-1-0xffffffffffff-5294967297-545\n");
13517 if (!string_to_sid(&sid, "S-1-0xfffffffffffe-32-545")) {
13518 printf("could not parse S-1-0xfffffffffffe-32-545\n");
13521 if (!string_to_sid(&sid, "S-1-5-32-545")) {
13522 printf("could not parse S-1-5-32-545\n");
13525 if (!dom_sid_equal(&sid, &global_sid_Builtin_Users)) {
13526 struct dom_sid_buf buf;
13527 printf("mis-parsed S-1-5-32-545 as %s\n",
13528 dom_sid_str_buf(&sid, &buf));
13534 static bool sid_to_string_test(const char *expected) {
13537 struct dom_sid sid;
13539 if (!string_to_sid(&sid, expected)) {
13540 printf("could not parse %s\n", expected);
13544 str = dom_sid_string(NULL, &sid);
13545 if (strcmp(str, expected)) {
13546 printf("Comparison failed (%s != %s)\n", str, expected);
13553 static bool run_local_sid_to_string(int dummy) {
13554 if (!sid_to_string_test("S-1-0xffffffffffff-1-1-1-1-1-1-1-1-1-1-1-1"))
13556 if (!sid_to_string_test("S-1-545"))
13558 if (!sid_to_string_test("S-255-3840-1-1-1-1"))
13563 static bool run_local_binary_to_sid(int dummy) {
13565 struct dom_sid *sid = talloc(NULL, struct dom_sid);
13566 static const uint8_t good_binary_sid[] = {
13567 0x1, /* revision number */
13568 15, /* num auths */
13569 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, /* id_auth */
13570 0x1, 0x1, 0x1, 0x1, /* auth[0] */
13571 0x1, 0x1, 0x1, 0x1, /* auth[1] */
13572 0x1, 0x1, 0x1, 0x1, /* auth[2] */
13573 0x1, 0x1, 0x1, 0x1, /* auth[3] */
13574 0x1, 0x1, 0x1, 0x1, /* auth[4] */
13575 0x1, 0x1, 0x1, 0x1, /* auth[5] */
13576 0x1, 0x1, 0x1, 0x1, /* auth[6] */
13577 0x1, 0x1, 0x1, 0x1, /* auth[7] */
13578 0x1, 0x1, 0x1, 0x1, /* auth[8] */
13579 0x1, 0x1, 0x1, 0x1, /* auth[9] */
13580 0x1, 0x1, 0x1, 0x1, /* auth[10] */
13581 0x1, 0x1, 0x1, 0x1, /* auth[11] */
13582 0x1, 0x1, 0x1, 0x1, /* auth[12] */
13583 0x1, 0x1, 0x1, 0x1, /* auth[13] */
13584 0x1, 0x1, 0x1, 0x1, /* auth[14] */
13587 static const uint8_t long_binary_sid[] = {
13588 0x1, /* revision number */
13589 15, /* num auths */
13590 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, /* id_auth */
13591 0x1, 0x1, 0x1, 0x1, /* auth[0] */
13592 0x1, 0x1, 0x1, 0x1, /* auth[1] */
13593 0x1, 0x1, 0x1, 0x1, /* auth[2] */
13594 0x1, 0x1, 0x1, 0x1, /* auth[3] */
13595 0x1, 0x1, 0x1, 0x1, /* auth[4] */
13596 0x1, 0x1, 0x1, 0x1, /* auth[5] */
13597 0x1, 0x1, 0x1, 0x1, /* auth[6] */
13598 0x1, 0x1, 0x1, 0x1, /* auth[7] */
13599 0x1, 0x1, 0x1, 0x1, /* auth[8] */
13600 0x1, 0x1, 0x1, 0x1, /* auth[9] */
13601 0x1, 0x1, 0x1, 0x1, /* auth[10] */
13602 0x1, 0x1, 0x1, 0x1, /* auth[11] */
13603 0x1, 0x1, 0x1, 0x1, /* auth[12] */
13604 0x1, 0x1, 0x1, 0x1, /* auth[13] */
13605 0x1, 0x1, 0x1, 0x1, /* auth[14] */
13606 0x1, 0x1, 0x1, 0x1, /* auth[15] */
13607 0x1, 0x1, 0x1, 0x1, /* auth[16] */
13608 0x1, 0x1, 0x1, 0x1, /* auth[17] */
13611 static const uint8_t long_binary_sid2[] = {
13612 0x1, /* revision number */
13613 32, /* num auths */
13614 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, /* id_auth */
13615 0x1, 0x1, 0x1, 0x1, /* auth[0] */
13616 0x1, 0x1, 0x1, 0x1, /* auth[1] */
13617 0x1, 0x1, 0x1, 0x1, /* auth[2] */
13618 0x1, 0x1, 0x1, 0x1, /* auth[3] */
13619 0x1, 0x1, 0x1, 0x1, /* auth[4] */
13620 0x1, 0x1, 0x1, 0x1, /* auth[5] */
13621 0x1, 0x1, 0x1, 0x1, /* auth[6] */
13622 0x1, 0x1, 0x1, 0x1, /* auth[7] */
13623 0x1, 0x1, 0x1, 0x1, /* auth[8] */
13624 0x1, 0x1, 0x1, 0x1, /* auth[9] */
13625 0x1, 0x1, 0x1, 0x1, /* auth[10] */
13626 0x1, 0x1, 0x1, 0x1, /* auth[11] */
13627 0x1, 0x1, 0x1, 0x1, /* auth[12] */
13628 0x1, 0x1, 0x1, 0x1, /* auth[13] */
13629 0x1, 0x1, 0x1, 0x1, /* auth[14] */
13630 0x1, 0x1, 0x1, 0x1, /* auth[15] */
13631 0x1, 0x1, 0x1, 0x1, /* auth[16] */
13632 0x1, 0x1, 0x1, 0x1, /* auth[17] */
13633 0x1, 0x1, 0x1, 0x1, /* auth[18] */
13634 0x1, 0x1, 0x1, 0x1, /* auth[19] */
13635 0x1, 0x1, 0x1, 0x1, /* auth[20] */
13636 0x1, 0x1, 0x1, 0x1, /* auth[21] */
13637 0x1, 0x1, 0x1, 0x1, /* auth[22] */
13638 0x1, 0x1, 0x1, 0x1, /* auth[23] */
13639 0x1, 0x1, 0x1, 0x1, /* auth[24] */
13640 0x1, 0x1, 0x1, 0x1, /* auth[25] */
13641 0x1, 0x1, 0x1, 0x1, /* auth[26] */
13642 0x1, 0x1, 0x1, 0x1, /* auth[27] */
13643 0x1, 0x1, 0x1, 0x1, /* auth[28] */
13644 0x1, 0x1, 0x1, 0x1, /* auth[29] */
13645 0x1, 0x1, 0x1, 0x1, /* auth[30] */
13646 0x1, 0x1, 0x1, 0x1, /* auth[31] */
13649 ret = sid_parse(good_binary_sid, sizeof(good_binary_sid), sid);
13653 ret = sid_parse(long_binary_sid2, sizeof(long_binary_sid2), sid);
13657 ret = sid_parse(long_binary_sid, sizeof(long_binary_sid), sid);
13664 /* Split a path name into filename and stream name components. Canonicalise
13665 * such that an implicit $DATA token is always explicit.
13667 * The "specification" of this function can be found in the
13668 * run_local_stream_name() function in torture.c, I've tried those
13669 * combinations against a W2k3 server.
13672 static NTSTATUS split_ntfs_stream_name(TALLOC_CTX *mem_ctx, const char *fname,
13673 char **pbase, char **pstream)
13676 char *stream = NULL;
13677 char *sname; /* stream name */
13678 const char *stype; /* stream type */
13680 DEBUG(10, ("split_ntfs_stream_name called for [%s]\n", fname));
13682 sname = strchr_m(fname, ':');
13684 if (sname == NULL) {
13685 if (pbase != NULL) {
13686 base = talloc_strdup(mem_ctx, fname);
13687 NT_STATUS_HAVE_NO_MEMORY(base);
13692 if (pbase != NULL) {
13693 base = talloc_strndup(mem_ctx, fname, PTR_DIFF(sname, fname));
13694 NT_STATUS_HAVE_NO_MEMORY(base);
13699 stype = strchr_m(sname, ':');
13701 if (stype == NULL) {
13702 sname = talloc_strdup(mem_ctx, sname);
13706 if (strcasecmp_m(stype, ":$DATA") != 0) {
13708 * If there is an explicit stream type, so far we only
13709 * allow $DATA. Is there anything else allowed? -- vl
13711 DEBUG(10, ("[%s] is an invalid stream type\n", stype));
13713 return NT_STATUS_OBJECT_NAME_INVALID;
13715 sname = talloc_strndup(mem_ctx, sname, PTR_DIFF(stype, sname));
13719 if (sname == NULL) {
13721 return NT_STATUS_NO_MEMORY;
13724 if (sname[0] == '\0') {
13726 * no stream name, so no stream
13731 if (pstream != NULL) {
13732 stream = talloc_asprintf(mem_ctx, "%s:%s", sname, stype);
13733 if (stream == NULL) {
13734 TALLOC_FREE(sname);
13736 return NT_STATUS_NO_MEMORY;
13739 * upper-case the type field
13741 (void)strupper_m(strchr_m(stream, ':')+1);
13745 if (pbase != NULL) {
13748 if (pstream != NULL) {
13751 return NT_STATUS_OK;
13754 static bool test_stream_name(const char *fname, const char *expected_base,
13755 const char *expected_stream,
13756 NTSTATUS expected_status)
13760 char *stream = NULL;
13762 status = split_ntfs_stream_name(talloc_tos(), fname, &base, &stream);
13763 if (!NT_STATUS_EQUAL(status, expected_status)) {
13767 if (!NT_STATUS_IS_OK(status)) {
13771 if (base == NULL) goto error;
13773 if (strcmp(expected_base, base) != 0) goto error;
13775 if ((expected_stream != NULL) && (stream == NULL)) goto error;
13776 if ((expected_stream == NULL) && (stream != NULL)) goto error;
13778 if ((stream != NULL) && (strcmp(expected_stream, stream) != 0))
13782 TALLOC_FREE(stream);
13786 d_fprintf(stderr, "Do test_stream(%s, %s, %s, %s)\n",
13787 fname, expected_base ? expected_base : "<NULL>",
13788 expected_stream ? expected_stream : "<NULL>",
13789 nt_errstr(expected_status));
13790 d_fprintf(stderr, "-> base=%s, stream=%s, status=%s\n",
13791 base ? base : "<NULL>", stream ? stream : "<NULL>",
13792 nt_errstr(status));
13794 TALLOC_FREE(stream);
13798 static bool run_local_stream_name(int dummy)
13802 ret &= test_stream_name(
13803 "bla", "bla", NULL, NT_STATUS_OK);
13804 ret &= test_stream_name(
13805 "bla::$DATA", "bla", NULL, NT_STATUS_OK);
13806 ret &= test_stream_name(
13807 "bla:blub:", "bla", NULL, NT_STATUS_OBJECT_NAME_INVALID);
13808 ret &= test_stream_name(
13809 "bla::", NULL, NULL, NT_STATUS_OBJECT_NAME_INVALID);
13810 ret &= test_stream_name(
13811 "bla::123", "bla", NULL, NT_STATUS_OBJECT_NAME_INVALID);
13812 ret &= test_stream_name(
13813 "bla:$DATA", "bla", "$DATA:$DATA", NT_STATUS_OK);
13814 ret &= test_stream_name(
13815 "bla:x:$DATA", "bla", "x:$DATA", NT_STATUS_OK);
13816 ret &= test_stream_name(
13817 "bla:x", "bla", "x:$DATA", NT_STATUS_OK);
13822 static bool data_blob_equal(DATA_BLOB a, DATA_BLOB b)
13824 if (a.length != b.length) {
13825 printf("a.length=%d != b.length=%d\n",
13826 (int)a.length, (int)b.length);
13829 if (memcmp(a.data, b.data, a.length) != 0) {
13830 printf("a.data and b.data differ\n");
13836 static bool run_local_memcache(int dummy)
13838 struct memcache *cache;
13839 DATA_BLOB k1, k2, k3, k4, k5;
13843 TALLOC_CTX *mem_ctx;
13849 size_t size1, size2;
13852 mem_ctx = talloc_init("foo");
13853 if (mem_ctx == NULL) {
13857 /* STAT_CACHE TESTS */
13859 cache = memcache_init(NULL, sizeof(void *) == 8 ? 200 : 100);
13861 if (cache == NULL) {
13862 printf("memcache_init failed\n");
13866 d1 = data_blob_const("d1", 2);
13867 d3 = data_blob_const("d3", 2);
13869 k1 = data_blob_const("d1", 2);
13870 k2 = data_blob_const("d2", 2);
13871 k3 = data_blob_const("d3", 2);
13872 k4 = data_blob_const("d4", 2);
13873 k5 = data_blob_const("d5", 2);
13875 memcache_add(cache, STAT_CACHE, k1, d1);
13877 if (!memcache_lookup(cache, STAT_CACHE, k1, &v1)) {
13878 printf("could not find k1\n");
13881 if (!data_blob_equal(d1, v1)) {
13885 memcache_add(cache, STAT_CACHE, k1, d3);
13887 if (!memcache_lookup(cache, STAT_CACHE, k1, &v3)) {
13888 printf("could not find replaced k1\n");
13891 if (!data_blob_equal(d3, v3)) {
13895 TALLOC_FREE(cache);
13897 /* GETWD_CACHE TESTS */
13898 str1 = talloc_strdup(mem_ctx, "string1");
13899 if (str1 == NULL) {
13902 ptr2 = str1; /* Keep an alias for comparison. */
13904 str2 = talloc_strdup(mem_ctx, "string2");
13905 if (str2 == NULL) {
13909 cache = memcache_init(NULL, sizeof(void *) == 8 ? 200 : 100);
13910 if (cache == NULL) {
13911 printf("memcache_init failed\n");
13915 memcache_add_talloc(cache, GETWD_CACHE, k2, &str1);
13916 /* str1 == NULL now. */
13917 ptr1 = memcache_lookup_talloc(cache, GETWD_CACHE, k2);
13918 if (ptr1 == NULL) {
13919 printf("could not find k2\n");
13922 if (ptr1 != ptr2) {
13923 printf("fetch of k2 got wrong string\n");
13927 /* Add a blob to ensure k2 gets purged. */
13928 d3 = data_blob_talloc_zero(mem_ctx, 180);
13929 memcache_add(cache, STAT_CACHE, k3, d3);
13931 ptr2 = memcache_lookup_talloc(cache, GETWD_CACHE, k2);
13932 if (ptr2 != NULL) {
13933 printf("Did find k2, should have been purged\n");
13938 * Test that talloc size also is accounted in memcache and
13939 * causes purge of other object.
13942 str1 = talloc_zero_size(mem_ctx, 100);
13943 str2 = talloc_zero_size(mem_ctx, 100);
13945 memcache_add_talloc(cache, GETWD_CACHE, k4, &str1);
13946 memcache_add_talloc(cache, GETWD_CACHE, k5, &str1);
13948 ptr3 = memcache_lookup_talloc(cache, GETWD_CACHE, k4);
13949 if (ptr3 != NULL) {
13950 printf("Did find k4, should have been purged\n");
13955 * Test that adding a duplicate non-talloced
13956 * key/value on top of a talloced key/value takes account
13957 * of the talloc_freed value size.
13959 TALLOC_FREE(cache);
13960 TALLOC_FREE(mem_ctx);
13962 mem_ctx = talloc_init("key_replace");
13963 if (mem_ctx == NULL) {
13967 cache = memcache_init(NULL, sizeof(void *) == 8 ? 200 : 100);
13968 if (cache == NULL) {
13973 * Add a 100 byte talloced string. This will
13974 * store a (4 or 8 byte) pointer and record the
13975 * total talloced size.
13977 str1 = talloc_zero_size(mem_ctx, 100);
13978 memcache_add_talloc(cache, GETWD_CACHE, k4, &str1);
13980 * Now overwrite with a small talloced
13981 * value. This should fit in the existing size
13982 * and the total talloced size should be removed
13983 * from the cache size.
13985 str1 = talloc_zero_size(mem_ctx, 2);
13986 memcache_add_talloc(cache, GETWD_CACHE, k4, &str1);
13988 * Now store a 20 byte string. If the
13989 * total talloced size wasn't accounted for
13990 * and removed in the overwrite, then this
13993 str2 = talloc_zero_size(mem_ctx, 20);
13994 memcache_add_talloc(cache, GETWD_CACHE, k5, &str2);
13996 ptr3 = memcache_lookup_talloc(cache, GETWD_CACHE, k4);
13997 if (ptr3 == NULL) {
13998 printf("Did not find k4, should not have been purged\n");
14002 TALLOC_FREE(cache);
14003 TALLOC_FREE(mem_ctx);
14005 mem_ctx = talloc_init("foo");
14006 if (mem_ctx == NULL) {
14010 cache = memcache_init(NULL, 0);
14011 if (cache == NULL) {
14015 str1 = talloc_strdup(mem_ctx, "string1");
14016 if (str1 == NULL) {
14019 str2 = talloc_strdup(mem_ctx, "string2");
14020 if (str2 == NULL) {
14023 memcache_add_talloc(cache, SINGLETON_CACHE_TALLOC,
14024 data_blob_string_const("torture"), &str1);
14025 size1 = talloc_total_size(cache);
14027 memcache_add_talloc(cache, SINGLETON_CACHE_TALLOC,
14028 data_blob_string_const("torture"), &str2);
14029 size2 = talloc_total_size(cache);
14031 printf("size1=%d, size2=%d\n", (int)size1, (int)size2);
14033 if (size2 > size1) {
14034 printf("memcache leaks memory!\n");
14040 TALLOC_FREE(cache);
14044 static void wbclient_done(struct tevent_req *req)
14047 struct winbindd_response *wb_resp;
14048 int *i = (int *)tevent_req_callback_data_void(req);
14050 wbc_err = wb_trans_recv(req, req, &wb_resp);
14053 d_printf("wb_trans_recv %d returned %s\n", *i, wbcErrorString(wbc_err));
14056 static bool run_wbclient_multi_ping(int dummy)
14058 struct tevent_context *ev;
14059 struct wb_context **wb_ctx;
14060 struct winbindd_request wb_req;
14061 bool result = false;
14064 BlockSignals(True, SIGPIPE);
14066 ev = tevent_context_init(talloc_tos());
14071 wb_ctx = talloc_array(ev, struct wb_context *, torture_nprocs);
14072 if (wb_ctx == NULL) {
14076 ZERO_STRUCT(wb_req);
14077 wb_req.cmd = WINBINDD_PING;
14079 d_printf("torture_nprocs=%d, numops=%d\n", (int)torture_nprocs, (int)torture_numops);
14081 for (i=0; i<torture_nprocs; i++) {
14082 wb_ctx[i] = wb_context_init(ev, NULL);
14083 if (wb_ctx[i] == NULL) {
14086 for (j=0; j<torture_numops; j++) {
14087 struct tevent_req *req;
14088 req = wb_trans_send(ev, ev, wb_ctx[i],
14089 (j % 2) == 0, &wb_req);
14093 tevent_req_set_callback(req, wbclient_done, &i);
14099 while (i < torture_nprocs * torture_numops) {
14100 tevent_loop_once(ev);
14109 static bool dbtrans_inc(struct db_context *db)
14111 struct db_record *rec;
14117 rec = dbwrap_fetch_locked(db, db, string_term_tdb_data("transtest"));
14119 printf(__location__ "fetch_lock failed\n");
14123 value = dbwrap_record_get_value(rec);
14125 if (value.dsize != sizeof(uint32_t)) {
14126 printf(__location__ "value.dsize = %d\n",
14131 memcpy(&val, value.dptr, sizeof(val));
14134 status = dbwrap_record_store(
14135 rec, make_tdb_data((uint8_t *)&val, sizeof(val)), 0);
14136 if (!NT_STATUS_IS_OK(status)) {
14137 printf(__location__ "store failed: %s\n",
14138 nt_errstr(status));
14148 static bool run_local_dbtrans(int dummy)
14150 struct db_context *db;
14151 struct db_record *rec;
14157 db = db_open(talloc_tos(), "transtest.tdb", 0, TDB_DEFAULT,
14158 O_RDWR|O_CREAT, 0600, DBWRAP_LOCK_ORDER_1,
14161 printf("Could not open transtest.db\n");
14165 res = dbwrap_transaction_start(db);
14167 printf(__location__ "transaction_start failed\n");
14171 rec = dbwrap_fetch_locked(db, db, string_term_tdb_data("transtest"));
14173 printf(__location__ "fetch_lock failed\n");
14177 value = dbwrap_record_get_value(rec);
14179 if (value.dptr == NULL) {
14181 status = dbwrap_record_store(
14182 rec, make_tdb_data((uint8_t *)&initial,
14185 if (!NT_STATUS_IS_OK(status)) {
14186 printf(__location__ "store returned %s\n",
14187 nt_errstr(status));
14194 res = dbwrap_transaction_commit(db);
14196 printf(__location__ "transaction_commit failed\n");
14201 uint32_t val, val2;
14204 res = dbwrap_transaction_start(db);
14206 printf(__location__ "transaction_start failed\n");
14210 status = dbwrap_fetch_uint32_bystring(db, "transtest", &val);
14211 if (!NT_STATUS_IS_OK(status)) {
14212 printf(__location__ "dbwrap_fetch_uint32 failed: %s\n",
14213 nt_errstr(status));
14217 for (i=0; i<10; i++) {
14218 if (!dbtrans_inc(db)) {
14223 status = dbwrap_fetch_uint32_bystring(db, "transtest", &val2);
14224 if (!NT_STATUS_IS_OK(status)) {
14225 printf(__location__ "dbwrap_fetch_uint32 failed: %s\n",
14226 nt_errstr(status));
14230 if (val2 != val + 10) {
14231 printf(__location__ "val=%d, val2=%d\n",
14232 (int)val, (int)val2);
14236 printf("val2=%d\r", val2);
14238 res = dbwrap_transaction_commit(db);
14240 printf(__location__ "transaction_commit failed\n");
14250 * Just a dummy test to be run under a debugger. There's no real way
14251 * to inspect the tevent_poll specific function from outside of
14255 static bool run_local_tevent_poll(int dummy)
14257 struct tevent_context *ev;
14258 struct tevent_fd *fd1, *fd2;
14259 bool result = false;
14261 ev = tevent_context_init_byname(NULL, "poll");
14263 d_fprintf(stderr, "tevent_context_init_byname failed\n");
14267 fd1 = tevent_add_fd(ev, ev, 2, 0, NULL, NULL);
14269 d_fprintf(stderr, "tevent_add_fd failed\n");
14272 fd2 = tevent_add_fd(ev, ev, 3, 0, NULL, NULL);
14274 d_fprintf(stderr, "tevent_add_fd failed\n");
14279 fd2 = tevent_add_fd(ev, ev, 1, 0, NULL, NULL);
14281 d_fprintf(stderr, "tevent_add_fd failed\n");
14291 static bool run_local_hex_encode_buf(int dummy)
14297 for (i=0; i<sizeof(src); i++) {
14300 hex_encode_buf(buf, src, sizeof(src));
14301 if (strcmp(buf, "0001020304050607") != 0) {
14304 hex_encode_buf(buf, NULL, 0);
14305 if (buf[0] != '\0') {
14311 static const char *remove_duplicate_addrs2_test_strings_vector[] = {
14333 "1001:1111:1111:1000:0:1111:1111:1111",
14342 static const char *remove_duplicate_addrs2_test_strings_result[] = {
14356 "1001:1111:1111:1000:0:1111:1111:1111"
14359 static bool run_local_remove_duplicate_addrs2(int dummy)
14361 struct samba_sockaddr test_vector[28];
14364 /* Construct the sockaddr_storage test vector. */
14365 for (i = 0; i < 28; i++) {
14366 struct addrinfo hints;
14367 struct addrinfo *res = NULL;
14370 memset(&hints, '\0', sizeof(hints));
14371 hints.ai_flags = AI_NUMERICHOST;
14372 ret = getaddrinfo(remove_duplicate_addrs2_test_strings_vector[i],
14377 fprintf(stderr, "getaddrinfo failed on [%s]\n",
14378 remove_duplicate_addrs2_test_strings_vector[i]);
14381 memset(&test_vector[i], '\0', sizeof(test_vector[i]));
14382 memcpy(&test_vector[i].u.ss,
14388 count = remove_duplicate_addrs2(test_vector, i);
14391 fprintf(stderr, "count wrong (%zu) should be 14\n",
14396 for (i = 0; i < count; i++) {
14397 char addr[INET6_ADDRSTRLEN];
14399 print_sockaddr(addr, sizeof(addr), &test_vector[i].u.ss);
14401 if (strcmp(addr, remove_duplicate_addrs2_test_strings_result[i]) != 0) {
14402 fprintf(stderr, "mismatch on [%zu] [%s] [%s]\n",
14405 remove_duplicate_addrs2_test_strings_result[i]);
14410 printf("run_local_remove_duplicate_addrs2: success\n");
14414 static bool run_local_tdb_opener(int dummy)
14420 t = tdb_open("test.tdb", 1000, TDB_CLEAR_IF_FIRST,
14421 O_RDWR|O_CREAT, 0755);
14423 perror("tdb_open failed");
14434 static bool run_local_tdb_writer(int dummy)
14440 t = tdb_open("test.tdb", 1000, 0, O_RDWR|O_CREAT, 0755);
14442 perror("tdb_open failed");
14446 val.dptr = (uint8_t *)&v;
14447 val.dsize = sizeof(v);
14453 ret = tdb_store(t, val, val, 0);
14455 printf("%s\n", tdb_errorstr(t));
14460 data = tdb_fetch(t, val);
14461 if (data.dptr != NULL) {
14462 SAFE_FREE(data.dptr);
14468 static bool run_local_canonicalize_path(int dummy)
14470 const char *src[] = {
14477 ".././././../../../boo",
14489 "/foo/bar/../baz/",
14490 "////////////////",
14491 "/////////./././././.",
14492 "/./.././../.boo/../baz",
14493 "/a/component/path",
14494 "/a/component/path/",
14495 "/a/component/path/..",
14496 "/a/component/../path/",
14497 "///a/./././///component/../////path/",
14500 const char *dst[] = {
14523 "/a/component/path",
14524 "/a/component/path",
14532 for (i = 0; src[i] != NULL; i++) {
14533 char *d = canonicalize_absolute_path(talloc_tos(), src[i]);
14535 perror("talloc fail\n");
14538 if (strcmp(d, dst[i]) != 0) {
14540 "canonicalize mismatch %s -> %s != %s",
14541 src[i], d, dst[i]);
14549 static bool run_ign_bad_negprot(int dummy)
14551 struct tevent_context *ev;
14552 struct tevent_req *req;
14553 struct smbXcli_conn *conn;
14554 struct sockaddr_storage ss;
14559 printf("starting ignore bad negprot\n");
14561 ok = resolve_name(host, &ss, 0x20, true);
14563 d_fprintf(stderr, "Could not resolve name %s\n", host);
14567 status = open_socket_out(&ss, 445, 10000, &fd);
14568 if (!NT_STATUS_IS_OK(status)) {
14569 d_fprintf(stderr, "open_socket_out failed: %s\n",
14570 nt_errstr(status));
14574 conn = smbXcli_conn_create(talloc_tos(), fd, host, SMB_SIGNING_OFF, 0,
14576 if (conn == NULL) {
14577 d_fprintf(stderr, "smbXcli_conn_create failed\n");
14581 status = smbXcli_negprot(conn, 0, PROTOCOL_CORE, PROTOCOL_CORE);
14582 if (NT_STATUS_IS_OK(status)) {
14583 d_fprintf(stderr, "smbXcli_negprot succeeded!\n");
14587 ev = samba_tevent_context_init(talloc_tos());
14589 d_fprintf(stderr, "samba_tevent_context_init failed\n");
14593 req = smb1cli_session_setup_nt1_send(
14594 ev, ev, conn, 0, getpid(), NULL, 65503, 2, 1, 0, "", "",
14595 data_blob_null, data_blob_null, 0x40,
14596 "Windows 2000 2195", "Windows 2000 5.0");
14598 d_fprintf(stderr, "smb1cli_session_setup_nt1_send failed\n");
14602 ok = tevent_req_poll_ntstatus(req, ev, &status);
14604 d_fprintf(stderr, "tevent_req_poll failed\n");
14608 status = smb1cli_session_setup_nt1_recv(req, NULL, NULL, NULL, NULL,
14610 if (!NT_STATUS_EQUAL(status, NT_STATUS_CONNECTION_RESET)) {
14611 d_fprintf(stderr, "smb1cli_session_setup_nt1_recv returned "
14612 "%s, expected NT_STATUS_CONNECTION_RESET\n",
14613 nt_errstr(status));
14619 printf("starting ignore bad negprot\n");
14624 static double create_procs(bool (*fn)(int), bool *result)
14627 volatile pid_t *child_status;
14628 volatile bool *child_status_out;
14631 struct timeval start;
14635 child_status = (volatile pid_t *)anonymous_shared_allocate(sizeof(pid_t)*torture_nprocs);
14636 if (!child_status) {
14637 printf("Failed to setup shared memory\n");
14641 child_status_out = (volatile bool *)anonymous_shared_allocate(sizeof(bool)*torture_nprocs);
14642 if (!child_status_out) {
14643 printf("Failed to setup result status shared memory\n");
14647 for (i = 0; i < torture_nprocs; i++) {
14648 child_status[i] = 0;
14649 child_status_out[i] = True;
14652 start = timeval_current();
14654 for (i=0;i<torture_nprocs;i++) {
14657 pid_t mypid = getpid();
14658 sys_srandom(((int)mypid) ^ ((int)time(NULL)));
14660 slprintf(myname,sizeof(myname),"CLIENT%d", i);
14663 if (torture_open_connection(¤t_cli, i)) break;
14664 if (tries-- == 0) {
14665 printf("pid %d failed to start\n", (int)getpid());
14671 child_status[i] = getpid();
14673 while (child_status[i] && timeval_elapsed(&start) < 5) smb_msleep(2);
14675 child_status_out[i] = fn(i);
14682 for (i=0;i<torture_nprocs;i++) {
14683 if (child_status[i]) synccount++;
14685 if (synccount == torture_nprocs) break;
14687 } while (timeval_elapsed(&start) < 30);
14689 if (synccount != torture_nprocs) {
14690 printf("FAILED TO START %d CLIENTS (started %d)\n", torture_nprocs, synccount);
14692 return timeval_elapsed(&start);
14695 /* start the client load */
14696 start = timeval_current();
14698 for (i=0;i<torture_nprocs;i++) {
14699 child_status[i] = 0;
14702 printf("%d clients started\n", torture_nprocs);
14704 for (i=0;i<torture_nprocs;i++) {
14705 while (waitpid(0, &status, 0) == -1 && errno == EINTR) /* noop */ ;
14710 for (i=0;i<torture_nprocs;i++) {
14711 if (!child_status_out[i]) {
14715 return timeval_elapsed(&start);
14718 #define FLAG_MULTIPROC 1
14724 } torture_ops[] = {
14727 .fn = run_fdpasstest,
14731 .fn = run_locktest1,
14735 .fn = run_locktest2,
14739 .fn = run_locktest3,
14743 .fn = run_locktest4,
14747 .fn = run_locktest5,
14751 .fn = run_locktest6,
14755 .fn = run_locktest7,
14759 .fn = run_locktest8,
14763 .fn = run_locktest9a,
14767 .fn = run_locktest9b,
14771 .fn = run_locktest10,
14775 .fn = run_locktest11,
14779 .fn = run_locktest12,
14783 .fn = run_locktest13,
14787 .fn = run_unlinktest,
14791 .fn = run_browsetest,
14795 .fn = run_attrtest,
14799 .fn = run_trans2test,
14803 .fn = run_maxfidtest,
14804 .flags = FLAG_MULTIPROC,
14809 .flags = FLAG_MULTIPROC,
14812 .name = "RANDOMIPC",
14813 .fn = run_randomipc,
14816 .name = "NEGNOWAIT",
14817 .fn = run_negprot_nowait,
14839 #ifdef HAVE_KERNEL_OPLOCKS_LINUX
14851 .fn = run_dirtest1,
14854 .name = "DIR-CREATETIME",
14855 .fn = run_dir_createtime,
14859 .fn = torture_denytest1,
14863 .fn = torture_denytest2,
14867 .fn = run_tcon_test,
14871 .fn = run_tcon_devtype_test,
14875 .fn = run_readwritetest,
14879 .fn = run_readwritemulti,
14880 .flags = FLAG_MULTIPROC
14884 .fn = run_readwritelarge,
14887 .name = "RW-SIGNING",
14888 .fn = run_readwritelarge_signtest,
14892 .fn = run_opentest,
14896 .fn = run_simple_posix_open_test,
14899 .name = "POSIX-APPEND",
14900 .fn = run_posix_append,
14903 .name = "POSIX-SYMLINK-ACL",
14904 .fn = run_acl_symlink_test,
14907 .name = "POSIX-SYMLINK-EA",
14908 .fn = run_ea_symlink_test,
14911 .name = "POSIX-STREAM-DELETE",
14912 .fn = run_posix_stream_delete,
14915 .name = "POSIX-OFD-LOCK",
14916 .fn = run_posix_ofd_lock_test,
14919 .name = "POSIX-BLOCKING-LOCK",
14920 .fn = run_posix_blocking_lock,
14923 .name = "POSIX-MKDIR",
14924 .fn = run_posix_mkdir_test,
14927 .name = "POSIX-ACL-OPLOCK",
14928 .fn = run_posix_acl_oplock_test,
14931 .name = "POSIX-ACL-SHAREROOT",
14932 .fn = run_posix_acl_shareroot_test,
14935 .name = "POSIX-LS-WILDCARD",
14936 .fn = run_posix_ls_wildcard_test,
14939 .name = "POSIX-LS-SINGLE",
14940 .fn = run_posix_ls_single_test,
14943 .name = "POSIX-READLINK",
14944 .fn = run_posix_readlink_test,
14947 .name = "POSIX-STAT",
14948 .fn = run_posix_stat_test,
14951 .name = "POSIX-SYMLINK-PARENT",
14952 .fn = run_posix_symlink_parent_test,
14955 .name = "POSIX-SYMLINK-CHMOD",
14956 .fn = run_posix_symlink_chmod_test,
14959 .name = "POSIX-DIR-DEFAULT-ACL",
14960 .fn = run_posix_dir_default_acl_test,
14963 .name = "WINDOWS-BAD-SYMLINK",
14964 .fn = run_symlink_open_test,
14967 .name = "SMB1-WILD-MANGLE-UNLINK",
14968 .fn = run_smb1_wild_mangle_unlink_test,
14971 .name = "SMB1-WILD-MANGLE-RENAME",
14972 .fn = run_smb1_wild_mangle_rename_test,
14975 .name = "CASE-INSENSITIVE-CREATE",
14976 .fn = run_case_insensitive_create,
14979 .name = "ASYNC-ECHO",
14980 .fn = run_async_echo,
14983 .name = "UID-REGRESSION-TEST",
14984 .fn = run_uid_regression_test,
14987 .name = "SHORTNAME-TEST",
14988 .fn = run_shortname_test,
14991 .name = "ADDRCHANGE",
14992 .fn = run_addrchange,
14996 .name = "OPENATTR",
14997 .fn = run_openattrtest,
15009 .name = "RENAME-ACCESS",
15010 .fn = run_rename_access,
15013 .name = "OWNER-RIGHTS",
15014 .fn = run_owner_rights,
15018 .fn = run_deletetest,
15021 .name = "DELETE-STREAM",
15022 .fn = run_delete_stream,
15025 .name = "DELETE-PRINT",
15026 .fn = run_delete_print_test,
15029 .name = "WILDDELETE",
15030 .fn = run_wild_deletetest,
15033 .name = "DELETE-LN",
15034 .fn = run_deletetest_ln,
15037 .name = "PROPERTIES",
15038 .fn = run_properties,
15042 .fn = torture_mangle,
15049 .name = "MANGLE-ILLEGAL",
15050 .fn = run_mangle_illegal,
15057 .name = "TRANS2SCAN",
15058 .fn = torture_trans2_scan,
15061 .name = "NTTRANSSCAN",
15062 .fn = torture_nttrans_scan,
15066 .fn = torture_utable,
15069 .name = "CASETABLE",
15070 .fn = torture_casetable,
15073 .name = "ERRMAPEXTRACT",
15074 .fn = run_error_map_extract,
15077 .name = "PIPE_NUMBER",
15078 .fn = run_pipe_number,
15082 .fn = run_tcon2_test,
15086 .fn = torture_ioctl_test,
15090 .fn = torture_chkpath_test,
15094 .fn = run_fdsesstest,
15101 .name = "SESSSETUP_BENCH",
15102 .fn = run_sesssetup_bench,
15117 .name = "WINDOWS-WRITE",
15118 .fn = run_windows_write,
15121 .name = "LARGE_READX",
15122 .fn = run_large_readx,
15125 .name = "MSDFS-ATTRIBUTE",
15126 .fn = run_msdfs_attribute,
15129 .name = "NTTRANS-CREATE",
15130 .fn = run_nttrans_create,
15133 .name = "NTTRANS-FSCTL",
15134 .fn = run_nttrans_fsctl,
15137 .name = "CLI_ECHO",
15138 .fn = run_cli_echo,
15141 .name = "CLI_SPLICE",
15142 .fn = run_cli_splice,
15149 .name = "STREAMERROR",
15150 .fn = run_streamerror,
15153 .name = "NOTIFY-BENCH",
15154 .fn = run_notify_bench,
15157 .name = "NOTIFY-BENCH2",
15158 .fn = run_notify_bench2,
15161 .name = "NOTIFY-BENCH3",
15162 .fn = run_notify_bench3,
15165 .name = "BAD-NBT-SESSION",
15166 .fn = run_bad_nbt_session,
15169 .name = "IGN-BAD-NEGPROT",
15170 .fn = run_ign_bad_negprot,
15173 .name = "SMB-ANY-CONNECT",
15174 .fn = run_smb_any_connect,
15177 .name = "NOTIFY-ONLINE",
15178 .fn = run_notify_online,
15181 .name = "SMB2-BASIC",
15182 .fn = run_smb2_basic,
15185 .name = "SMB2-NEGPROT",
15186 .fn = run_smb2_negprot,
15189 .name = "SMB2-ANONYMOUS",
15190 .fn = run_smb2_anonymous,
15193 .name = "SMB2-SESSION-RECONNECT",
15194 .fn = run_smb2_session_reconnect,
15197 .name = "SMB2-TCON-DEPENDENCE",
15198 .fn = run_smb2_tcon_dependence,
15201 .name = "SMB2-MULTI-CHANNEL",
15202 .fn = run_smb2_multi_channel,
15205 .name = "SMB2-SESSION-REAUTH",
15206 .fn = run_smb2_session_reauth,
15209 .name = "SMB2-FTRUNCATE",
15210 .fn = run_smb2_ftruncate,
15213 .name = "SMB2-DIR-FSYNC",
15214 .fn = run_smb2_dir_fsync,
15217 .name = "SMB2-PATH-SLASH",
15218 .fn = run_smb2_path_slash,
15221 .name = "SMB1-SYSTEM-SECURITY",
15222 .fn = run_smb1_system_security,
15225 .name = "SMB2-SACL",
15226 .fn = run_smb2_sacl,
15229 .name = "SMB2-QUOTA1",
15230 .fn = run_smb2_quota1,
15233 .name = "SMB2-STREAM-ACL",
15234 .fn = run_smb2_stream_acl,
15237 .name = "CLEANUP1",
15238 .fn = run_cleanup1,
15241 .name = "CLEANUP2",
15242 .fn = run_cleanup2,
15245 .name = "CLEANUP4",
15246 .fn = run_cleanup4,
15249 .name = "OPLOCK-CANCEL",
15250 .fn = run_oplock_cancel,
15257 .name = "LOCAL-SUBSTITUTE",
15258 .fn = run_local_substitute,
15261 .name = "LOCAL-GENCACHE",
15262 .fn = run_local_gencache,
15265 .name = "LOCAL-DBWRAP-WATCH1",
15266 .fn = run_dbwrap_watch1,
15269 .name = "LOCAL-DBWRAP-WATCH2",
15270 .fn = run_dbwrap_watch2,
15273 .name = "LOCAL-DBWRAP-WATCH3",
15274 .fn = run_dbwrap_watch3,
15277 .name = "LOCAL-DBWRAP-WATCH4",
15278 .fn = run_dbwrap_watch4,
15281 .name = "LOCAL-DBWRAP-DO-LOCKED1",
15282 .fn = run_dbwrap_do_locked1,
15285 .name = "LOCAL-MESSAGING-READ1",
15286 .fn = run_messaging_read1,
15289 .name = "LOCAL-MESSAGING-READ2",
15290 .fn = run_messaging_read2,
15293 .name = "LOCAL-MESSAGING-READ3",
15294 .fn = run_messaging_read3,
15297 .name = "LOCAL-MESSAGING-READ4",
15298 .fn = run_messaging_read4,
15301 .name = "LOCAL-MESSAGING-FDPASS1",
15302 .fn = run_messaging_fdpass1,
15305 .name = "LOCAL-MESSAGING-FDPASS2",
15306 .fn = run_messaging_fdpass2,
15309 .name = "LOCAL-MESSAGING-FDPASS2a",
15310 .fn = run_messaging_fdpass2a,
15313 .name = "LOCAL-MESSAGING-FDPASS2b",
15314 .fn = run_messaging_fdpass2b,
15317 .name = "LOCAL-MESSAGING-SEND-ALL",
15318 .fn = run_messaging_send_all,
15321 .name = "LOCAL-BASE64",
15322 .fn = run_local_base64,
15325 .name = "LOCAL-RBTREE",
15326 .fn = run_local_rbtree,
15329 .name = "LOCAL-MEMCACHE",
15330 .fn = run_local_memcache,
15333 .name = "LOCAL-STREAM-NAME",
15334 .fn = run_local_stream_name,
15337 .name = "WBCLIENT-MULTI-PING",
15338 .fn = run_wbclient_multi_ping,
15341 .name = "LOCAL-string_to_sid",
15342 .fn = run_local_string_to_sid,
15345 .name = "LOCAL-sid_to_string",
15346 .fn = run_local_sid_to_string,
15349 .name = "LOCAL-binary_to_sid",
15350 .fn = run_local_binary_to_sid,
15353 .name = "LOCAL-DBTRANS",
15354 .fn = run_local_dbtrans,
15357 .name = "LOCAL-TEVENT-POLL",
15358 .fn = run_local_tevent_poll,
15361 .name = "LOCAL-CONVERT-STRING",
15362 .fn = run_local_convert_string,
15365 .name = "LOCAL-CONV-AUTH-INFO",
15366 .fn = run_local_conv_auth_info,
15369 .name = "LOCAL-hex_encode_buf",
15370 .fn = run_local_hex_encode_buf,
15373 .name = "LOCAL-IDMAP-TDB-COMMON",
15374 .fn = run_idmap_tdb_common_test,
15377 .name = "LOCAL-remove_duplicate_addrs2",
15378 .fn = run_local_remove_duplicate_addrs2,
15381 .name = "local-tdb-opener",
15382 .fn = run_local_tdb_opener,
15385 .name = "local-tdb-writer",
15386 .fn = run_local_tdb_writer,
15389 .name = "LOCAL-DBWRAP-CTDB1",
15390 .fn = run_local_dbwrap_ctdb1,
15393 .name = "LOCAL-BENCH-PTHREADPOOL",
15394 .fn = run_bench_pthreadpool,
15397 .name = "LOCAL-PTHREADPOOL-TEVENT",
15398 .fn = run_pthreadpool_tevent,
15401 .name = "LOCAL-G-LOCK1",
15405 .name = "LOCAL-G-LOCK2",
15409 .name = "LOCAL-G-LOCK3",
15413 .name = "LOCAL-G-LOCK4",
15417 .name = "LOCAL-G-LOCK4A",
15418 .fn = run_g_lock4a,
15421 .name = "LOCAL-G-LOCK5",
15425 .name = "LOCAL-G-LOCK6",
15429 .name = "LOCAL-G-LOCK7",
15433 .name = "LOCAL-G-LOCK8",
15437 .name = "LOCAL-G-LOCK-PING-PONG",
15438 .fn = run_g_lock_ping_pong,
15441 .name = "LOCAL-CANONICALIZE-PATH",
15442 .fn = run_local_canonicalize_path,
15445 .name = "LOCAL-NAMEMAP-CACHE1",
15446 .fn = run_local_namemap_cache1,
15449 .name = "LOCAL-IDMAP-CACHE1",
15450 .fn = run_local_idmap_cache1,
15453 .name = "qpathinfo-bufsize",
15454 .fn = run_qpathinfo_bufsize,
15457 .name = "hide-new-files-timeout",
15458 .fn = run_hidenewfiles,
15460 #ifdef CLUSTER_SUPPORT
15462 .name = "ctdbd-conn1",
15463 .fn = run_ctdbd_conn1,
15467 .name = "readdir-timestamp",
15468 .fn = run_readdir_timestamp,
15475 /****************************************************************************
15476 run a specified test or "ALL"
15477 ****************************************************************************/
15478 static bool run_test(const char *name)
15481 bool result = True;
15482 bool found = False;
15485 if (strequal(name,"ALL")) {
15486 for (i=0;torture_ops[i].name;i++) {
15487 run_test(torture_ops[i].name);
15492 for (i=0;torture_ops[i].name;i++) {
15493 fstr_sprintf(randomfname, "\\XX%x",
15494 (unsigned)random());
15496 if (strequal(name, torture_ops[i].name)) {
15498 printf("Running %s\n", name);
15499 if (torture_ops[i].flags & FLAG_MULTIPROC) {
15500 t = create_procs(torture_ops[i].fn, &result);
15503 printf("TEST %s FAILED!\n", name);
15506 struct timeval start;
15507 start = timeval_current();
15508 if (!torture_ops[i].fn(0)) {
15510 printf("TEST %s FAILED!\n", name);
15512 t = timeval_elapsed(&start);
15514 printf("%s took %g secs\n\n", name, t);
15519 printf("Did not find a test named %s\n", name);
15527 static void usage(void)
15531 printf("WARNING samba4 test suite is much more complete nowadays.\n");
15532 printf("Please use samba4 torture.\n\n");
15534 printf("Usage: smbtorture //server/share <options> TEST1 TEST2 ...\n");
15536 printf("\t-d debuglevel\n");
15537 printf("\t-U user%%pass\n");
15538 printf("\t-k use kerberos\n");
15539 printf("\t-N numprocs\n");
15540 printf("\t-n my_netbios_name\n");
15541 printf("\t-W workgroup\n");
15542 printf("\t-o num_operations\n");
15543 printf("\t-O socket_options\n");
15544 printf("\t-m maximum protocol\n");
15545 printf("\t-L use oplocks\n");
15546 printf("\t-c CLIENT.TXT specify client load file for NBENCH\n");
15547 printf("\t-A showall\n");
15548 printf("\t-p port\n");
15549 printf("\t-s seed\n");
15550 printf("\t-b unclist_filename specify multiple shares for multiple connections\n");
15551 printf("\t-f filename filename to test\n");
15552 printf("\t-e encrypt\n");
15555 printf("tests are:");
15556 for (i=0;torture_ops[i].name;i++) {
15557 printf(" %s", torture_ops[i].name);
15561 printf("default test is ALL\n");
15566 /****************************************************************************
15568 ****************************************************************************/
15569 int main(int argc,char *argv[])
15575 bool correct = True;
15576 TALLOC_CTX *frame = talloc_stackframe();
15577 int seed = time(NULL);
15579 #ifdef HAVE_SETBUFFER
15580 setbuffer(stdout, NULL, 0);
15583 setup_logging("smbtorture", DEBUG_STDOUT);
15588 if (is_default_dyn_CONFIGFILE()) {
15589 if(getenv("SMB_CONF_PATH")) {
15590 set_dyn_CONFIGFILE(getenv("SMB_CONF_PATH"));
15593 lp_load_global(get_dyn_CONFIGFILE());
15600 for(p = argv[1]; *p; p++)
15604 if (strncmp(argv[1], "//", 2)) {
15608 fstrcpy(host, &argv[1][2]);
15609 p = strchr_m(&host[2],'/');
15614 fstrcpy(share, p+1);
15616 fstrcpy(myname, get_myname(talloc_tos()));
15618 fprintf(stderr, "Failed to get my hostname.\n");
15622 if (*username == 0 && getenv("LOGNAME")) {
15623 fstrcpy(username,getenv("LOGNAME"));
15629 fstrcpy(workgroup, lp_workgroup());
15631 while ((opt = getopt(argc, argv, "p:hW:U:n:N:O:o:m:Ll:d:Aec:ks:b:B:f:"))
15635 port_to_use = atoi(optarg);
15638 seed = atoi(optarg);
15641 fstrcpy(workgroup,optarg);
15644 lp_set_cmdline("client max protocol", optarg);
15647 torture_nprocs = atoi(optarg);
15650 torture_numops = atoi(optarg);
15653 lp_set_cmdline("log level", optarg);
15659 use_oplocks = True;
15662 local_path = optarg;
15665 torture_showall = True;
15668 fstrcpy(myname, optarg);
15671 client_txt = optarg;
15678 use_kerberos = True;
15680 d_printf("No kerberos support compiled in\n");
15686 fstrcpy(username,optarg);
15687 p = strchr_m(username,'%');
15690 fstrcpy(password, p+1);
15695 fstrcpy(multishare_conn_fname, optarg);
15696 use_multishare_conn = True;
15699 torture_blocksize = atoi(optarg);
15702 test_filename = SMB_STRDUP(optarg);
15705 printf("Unknown option %c (%d)\n", (char)opt, opt);
15710 d_printf("using seed %d\n", seed);
15714 if(use_kerberos && !gotuser) gotpass = True;
15717 char pwd[256] = {0};
15720 rc = samba_getpass("Password:", pwd, sizeof(pwd), false, false);
15722 fstrcpy(password, pwd);
15727 printf("host=%s share=%s user=%s myname=%s\n",
15728 host, share, username, myname);
15730 torture_creds = cli_session_creds_init(frame,
15736 false, /* fallback_after_kerberos */
15737 false, /* use_ccache */
15738 false); /* password_is_nt_hash */
15739 if (torture_creds == NULL) {
15740 d_printf("cli_session_creds_init() failed.\n");
15744 if (argc == optind) {
15745 correct = run_test("ALL");
15747 for (i=optind;i<argc;i++) {
15748 if (!run_test(argv[i])) {
15754 TALLOC_FREE(frame);