2 Unix SMB/CIFS implementation.
4 Copyright (C) Andrew Tridgell 1997-1998
5 Copyright (C) Jeremy Allison 2009
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program. If not, see <http://www.gnu.org/licenses/>.
22 #include "system/shmem.h"
23 #include "libsmb/namequery.h"
24 #include "wbc_async.h"
25 #include "torture/proto.h"
26 #include "libcli/security/security.h"
28 #include "tldap_util.h"
29 #include "tldap_gensec_bind.h"
30 #include "../librpc/gen_ndr/svcctl.h"
31 #include "../lib/util/memcache.h"
32 #include "nsswitch/winbind_client.h"
33 #include "dbwrap/dbwrap.h"
34 #include "dbwrap/dbwrap_open.h"
35 #include "dbwrap/dbwrap_rbt.h"
36 #include "async_smb.h"
37 #include "libsmb/libsmb.h"
38 #include "libsmb/clirap.h"
40 #include "libsmb/nmblib.h"
41 #include "../lib/util/tevent_ntstatus.h"
43 #include "../libcli/smb/read_smb.h"
44 #include "../libcli/smb/smbXcli_base.h"
45 #include "lib/util/sys_rw_data.h"
46 #include "lib/util/base64.h"
47 #include "lib/util/time.h"
48 #include "lib/gencache.h"
49 #include "lib/util/sys_rw.h"
50 #include "lib/util/asn1.h"
51 #include "lib/param/param.h"
52 #include "auth/gensec/gensec.h"
53 #include "lib/util/string_wrappers.h"
54 #include "source3/lib/substitute.h"
56 #include <gnutls/gnutls.h>
57 #include <gnutls/crypto.h>
62 fstring host, workgroup, share, password, username, myname;
63 struct cli_credentials *torture_creds;
64 static const char *sockops="TCP_NODELAY";
66 static int port_to_use=0;
67 int torture_numops=100;
68 int torture_blocksize=1024*1024;
69 static int procnum; /* records process count number when forking */
70 static struct cli_state *current_cli;
71 static fstring randomfname;
72 static bool use_oplocks;
73 static bool use_level_II_oplocks;
74 static const char *client_txt = "client_oplocks.txt";
75 static bool disable_spnego;
76 static bool use_kerberos;
77 static bool force_dos_errors;
78 static fstring multishare_conn_fname;
79 static bool use_multishare_conn = False;
80 static bool do_encrypt;
81 static const char *local_path = NULL;
82 static enum smb_signing_setting signing_state = SMB_SIGNING_DEFAULT;
85 bool torture_showall = False;
87 static double create_procs(bool (*fn)(int), bool *result);
89 /********************************************************************
90 Ensure a connection is encrypted.
91 ********************************************************************/
93 static bool force_cli_encryption(struct cli_state *c,
94 const char *sharename)
96 uint16_t major, minor;
97 uint32_t caplow, caphigh;
100 if (!SERVER_HAS_UNIX_CIFS(c)) {
101 d_printf("Encryption required and "
102 "server that doesn't support "
103 "UNIX extensions - failing connect\n");
107 status = cli_unix_extensions_version(c, &major, &minor, &caplow,
109 if (!NT_STATUS_IS_OK(status)) {
110 d_printf("Encryption required and "
111 "can't get UNIX CIFS extensions "
112 "version from server: %s\n", nt_errstr(status));
116 if (!(caplow & CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP)) {
117 d_printf("Encryption required and "
118 "share %s doesn't support "
119 "encryption.\n", sharename);
123 status = cli_smb1_setup_encryption(c, torture_creds);
124 if (!NT_STATUS_IS_OK(status)) {
125 d_printf("Encryption required and "
126 "setup failed with error %s.\n",
135 static struct cli_state *open_nbt_connection(void)
141 if (disable_spnego) {
142 flags |= CLI_FULL_CONNECTION_DONT_SPNEGO;
146 flags |= CLI_FULL_CONNECTION_OPLOCKS;
149 if (use_level_II_oplocks) {
150 flags |= CLI_FULL_CONNECTION_LEVEL_II_OPLOCKS;
153 if (force_dos_errors) {
154 flags |= CLI_FULL_CONNECTION_FORCE_DOS_ERRORS;
157 status = cli_connect_nb(host, NULL, port_to_use, 0x20, myname,
158 signing_state, flags, &c);
159 if (!NT_STATUS_IS_OK(status)) {
160 printf("Failed to connect with %s. Error %s\n", host, nt_errstr(status) );
164 cli_set_timeout(c, 120000); /* set a really long timeout (2 minutes) */
169 /****************************************************************************
170 Send a corrupt session request. See rfc1002.txt 4.3 and 4.3.2.
171 ****************************************************************************/
173 static bool cli_bad_session_request(int fd,
174 struct nmb_name *calling, struct nmb_name *called)
183 uint8_t message_type;
185 struct tevent_context *ev;
186 struct tevent_req *req;
188 frame = talloc_stackframe();
190 iov[0].iov_base = len_buf;
191 iov[0].iov_len = sizeof(len_buf);
193 /* put in the destination name */
195 iov[1].iov_base = name_mangle(talloc_tos(), called->name,
197 if (iov[1].iov_base == NULL) {
200 iov[1].iov_len = name_len((unsigned char *)iov[1].iov_base,
201 talloc_get_size(iov[1].iov_base));
205 iov[2].iov_base = name_mangle(talloc_tos(), calling->name,
207 if (iov[2].iov_base == NULL) {
210 iov[2].iov_len = name_len((unsigned char *)iov[2].iov_base,
211 talloc_get_size(iov[2].iov_base));
213 /* Deliberately corrupt the name len (first byte) */
214 *((uint8_t *)iov[2].iov_base) = 100;
216 /* send a session request (RFC 1002) */
217 /* setup the packet length
218 * Remove four bytes from the length count, since the length
219 * field in the NBT Session Service header counts the number
220 * of bytes which follow. The cli_send_smb() function knows
221 * about this and accounts for those four bytes.
225 _smb_setlen(len_buf, iov[1].iov_len + iov[2].iov_len);
226 SCVAL(len_buf,0,0x81);
228 len = write_data_iov(fd, iov, 3);
233 ev = samba_tevent_context_init(frame);
237 req = read_smb_send(frame, ev, fd);
241 if (!tevent_req_poll(req, ev)) {
244 len = read_smb_recv(req, talloc_tos(), &inbuf, &err);
251 message_type = CVAL(inbuf, 0);
252 if (message_type != 0x83) {
253 d_fprintf(stderr, "Expected msg type 0x83, got 0x%2.2x\n",
258 if (smb_len(inbuf) != 1) {
259 d_fprintf(stderr, "Expected smb_len 1, got %d\n",
260 (int)smb_len(inbuf));
264 error = CVAL(inbuf, 4);
266 d_fprintf(stderr, "Expected error 0x82, got %d\n",
277 /* Insert a NULL at the first separator of the given path and return a pointer
278 * to the remainder of the string.
281 terminate_path_at_separator(char * path)
289 if ((p = strchr_m(path, '/'))) {
294 if ((p = strchr_m(path, '\\'))) {
304 parse a //server/share type UNC name
306 bool smbcli_parse_unc(const char *unc_name, TALLOC_CTX *mem_ctx,
307 char **hostname, char **sharename)
311 *hostname = *sharename = NULL;
313 if (strncmp(unc_name, "\\\\", 2) &&
314 strncmp(unc_name, "//", 2)) {
318 *hostname = talloc_strdup(mem_ctx, &unc_name[2]);
319 p = terminate_path_at_separator(*hostname);
322 *sharename = talloc_strdup(mem_ctx, p);
323 terminate_path_at_separator(*sharename);
326 if (*hostname && *sharename) {
330 TALLOC_FREE(*hostname);
331 TALLOC_FREE(*sharename);
335 static bool torture_open_connection_share(struct cli_state **c,
336 const char *hostname,
337 const char *sharename,
342 status = cli_full_connection_creds(c,
351 if (!NT_STATUS_IS_OK(status)) {
352 printf("failed to open share connection: //%s/%s port:%d - %s\n",
353 hostname, sharename, port_to_use, nt_errstr(status));
357 cli_set_timeout(*c, 120000); /* set a really long timeout (2 minutes) */
360 return force_cli_encryption(*c,
366 bool torture_open_connection_flags(struct cli_state **c, int conn_index, int flags)
368 char **unc_list = NULL;
369 int num_unc_names = 0;
372 if (use_multishare_conn==True) {
374 unc_list = file_lines_load(multishare_conn_fname, &num_unc_names, 0, NULL);
375 if (!unc_list || num_unc_names <= 0) {
376 printf("Failed to load unc names list from '%s'\n", multishare_conn_fname);
380 if (!smbcli_parse_unc(unc_list[conn_index % num_unc_names],
382 printf("Failed to parse UNC name %s\n",
383 unc_list[conn_index % num_unc_names]);
384 TALLOC_FREE(unc_list);
388 result = torture_open_connection_share(c, h, s, flags);
390 /* h, s were copied earlier */
391 TALLOC_FREE(unc_list);
395 return torture_open_connection_share(c, host, share, flags);
398 bool torture_open_connection(struct cli_state **c, int conn_index)
400 int flags = CLI_FULL_CONNECTION_FORCE_SMB1;
403 flags |= CLI_FULL_CONNECTION_OPLOCKS;
405 if (use_level_II_oplocks) {
406 flags |= CLI_FULL_CONNECTION_LEVEL_II_OPLOCKS;
409 return torture_open_connection_flags(c, conn_index, flags);
412 bool torture_init_connection(struct cli_state **pcli)
414 struct cli_state *cli;
416 cli = open_nbt_connection();
425 bool torture_cli_session_setup2(struct cli_state *cli, uint16_t *new_vuid)
427 uint16_t old_vuid = cli_state_get_uid(cli);
431 cli_state_set_uid(cli, 0);
432 status = cli_session_setup_creds(cli, torture_creds);
433 ret = NT_STATUS_IS_OK(status);
434 *new_vuid = cli_state_get_uid(cli);
435 cli_state_set_uid(cli, old_vuid);
440 bool torture_close_connection(struct cli_state *c)
445 status = cli_tdis(c);
446 if (!NT_STATUS_IS_OK(status)) {
447 printf("tdis failed (%s)\n", nt_errstr(status));
456 void torture_conn_set_sockopt(struct cli_state *cli)
458 smbXcli_conn_set_sockopt(cli->conn, sockops);
461 static NTSTATUS torture_delete_fn(struct file_info *finfo,
466 char *filename = NULL;
467 char *dirname = NULL;
469 TALLOC_CTX *frame = talloc_stackframe();
470 struct cli_state *cli = (struct cli_state *)state;
472 if (ISDOT(finfo->name) || ISDOTDOT(finfo->name)) {
477 dirname = talloc_strdup(frame, pattern);
478 if (dirname == NULL) {
480 return NT_STATUS_NO_MEMORY;
482 p = strrchr_m(dirname, '\\');
484 /* Remove the terminating '\' */
487 if (dirname[0] != '\0') {
488 filename = talloc_asprintf(frame,
493 filename = talloc_asprintf(frame,
497 if (filename == NULL) {
499 return NT_STATUS_NO_MEMORY;
501 if (finfo->attr & FILE_ATTRIBUTE_DIRECTORY) {
502 char *subdirname = talloc_asprintf(frame,
505 if (subdirname == NULL) {
507 return NT_STATUS_NO_MEMORY;
509 status = cli_list(cli,
511 FILE_ATTRIBUTE_DIRECTORY |
512 FILE_ATTRIBUTE_HIDDEN |
513 FILE_ATTRIBUTE_SYSTEM,
516 if (NT_STATUS_IS_OK(status)) {
517 printf("torture_delete_fn: cli_list "
518 "of %s failed (%s)\n",
524 status = cli_rmdir(cli, filename);
526 status = cli_unlink(cli,
528 FILE_ATTRIBUTE_SYSTEM |
529 FILE_ATTRIBUTE_HIDDEN);
531 if (!NT_STATUS_IS_OK(status)) {
532 if (finfo->attr & FILE_ATTRIBUTE_DIRECTORY) {
533 printf("torture_delete_fn: cli_rmdir"
534 " of %s failed (%s)\n",
538 printf("torture_delete_fn: cli_unlink"
539 " of %s failed (%s)\n",
548 void torture_deltree(struct cli_state *cli, const char *dname)
553 /* It might be a file */
554 (void)cli_unlink(cli,
556 FILE_ATTRIBUTE_SYSTEM |
557 FILE_ATTRIBUTE_HIDDEN);
559 mask = talloc_asprintf(cli,
563 printf("torture_deltree: talloc_asprintf failed\n");
567 status = cli_list(cli,
569 FILE_ATTRIBUTE_DIRECTORY |
570 FILE_ATTRIBUTE_HIDDEN|
571 FILE_ATTRIBUTE_SYSTEM,
574 if (!NT_STATUS_IS_OK(status)) {
575 printf("torture_deltree: cli_list of %s failed (%s)\n",
580 status = cli_rmdir(cli, dname);
581 if (!NT_STATUS_IS_OK(status)) {
582 printf("torture_deltree: cli_rmdir of %s failed (%s)\n",
588 /* check if the server produced the expected dos or nt error code */
589 static bool check_both_error(int line, NTSTATUS status,
590 uint8_t eclass, uint32_t ecode, NTSTATUS nterr)
592 if (NT_STATUS_IS_DOS(status)) {
596 /* Check DOS error */
597 cclass = NT_STATUS_DOS_CLASS(status);
598 num = NT_STATUS_DOS_CODE(status);
600 if (eclass != cclass || ecode != num) {
601 printf("unexpected error code class=%d code=%d\n",
602 (int)cclass, (int)num);
603 printf(" expected %d/%d %s (line=%d)\n",
604 (int)eclass, (int)ecode, nt_errstr(nterr), line);
609 if (!NT_STATUS_EQUAL(nterr, status)) {
610 printf("unexpected error code %s\n",
612 printf(" expected %s (line=%d)\n",
613 nt_errstr(nterr), line);
622 /* check if the server produced the expected error code */
623 static bool check_error(int line, NTSTATUS status,
624 uint8_t eclass, uint32_t ecode, NTSTATUS nterr)
626 if (NT_STATUS_IS_DOS(status)) {
630 /* Check DOS error */
632 cclass = NT_STATUS_DOS_CLASS(status);
633 num = NT_STATUS_DOS_CODE(status);
635 if (eclass != cclass || ecode != num) {
636 printf("unexpected error code class=%d code=%d\n",
637 (int)cclass, (int)num);
638 printf(" expected %d/%d %s (line=%d)\n",
639 (int)eclass, (int)ecode, nt_errstr(nterr),
647 if (NT_STATUS_V(nterr) != NT_STATUS_V(status)) {
648 printf("unexpected error code %s\n",
650 printf(" expected %s (line=%d)\n", nt_errstr(nterr),
660 static bool wait_lock(struct cli_state *c, int fnum, uint32_t offset, uint32_t len)
664 status = cli_lock32(c, fnum, offset, len, -1, WRITE_LOCK);
666 while (!NT_STATUS_IS_OK(status)) {
667 if (!check_both_error(__LINE__, status, ERRDOS,
668 ERRlock, NT_STATUS_LOCK_NOT_GRANTED)) {
672 status = cli_lock32(c, fnum, offset, len, -1, WRITE_LOCK);
679 static bool rw_torture(struct cli_state *c)
681 const char *lockfname = "\\torture.lck";
685 pid_t pid2, pid = getpid();
692 memset(buf, '\0', sizeof(buf));
694 status = cli_openx(c, lockfname, O_RDWR | O_CREAT | O_EXCL,
696 if (!NT_STATUS_IS_OK(status)) {
697 status = cli_openx(c, lockfname, O_RDWR, DENY_NONE, &fnum2);
699 if (!NT_STATUS_IS_OK(status)) {
700 printf("open of %s failed (%s)\n",
701 lockfname, nt_errstr(status));
705 for (i=0;i<torture_numops;i++) {
706 unsigned n = (unsigned)sys_random()%10;
709 printf("%d\r", i); fflush(stdout);
711 slprintf(fname, sizeof(fstring) - 1, "\\torture.%u", n);
713 if (!wait_lock(c, fnum2, n*sizeof(int), sizeof(int))) {
717 status = cli_openx(c, fname, O_RDWR | O_CREAT | O_TRUNC,
719 if (!NT_STATUS_IS_OK(status)) {
720 printf("open failed (%s)\n", nt_errstr(status));
725 status = cli_writeall(c, fnum, 0, (uint8_t *)&pid, 0,
727 if (!NT_STATUS_IS_OK(status)) {
728 printf("write failed (%s)\n", nt_errstr(status));
733 status = cli_writeall(c, fnum, 0, (uint8_t *)buf,
734 sizeof(pid)+(j*sizeof(buf)),
736 if (!NT_STATUS_IS_OK(status)) {
737 printf("write failed (%s)\n",
745 status = cli_read(c, fnum, (char *)&pid2, 0, sizeof(pid),
747 if (!NT_STATUS_IS_OK(status)) {
748 printf("read failed (%s)\n", nt_errstr(status));
750 } else if (nread != sizeof(pid)) {
751 printf("read/write compare failed: "
752 "recv %ld req %ld\n", (unsigned long)nread,
753 (unsigned long)sizeof(pid));
758 printf("data corruption!\n");
762 status = cli_close(c, fnum);
763 if (!NT_STATUS_IS_OK(status)) {
764 printf("close failed (%s)\n", nt_errstr(status));
768 status = cli_unlink(c, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
769 if (!NT_STATUS_IS_OK(status)) {
770 printf("unlink failed (%s)\n", nt_errstr(status));
774 status = cli_unlock(c, fnum2, n*sizeof(int), sizeof(int));
775 if (!NT_STATUS_IS_OK(status)) {
776 printf("unlock failed (%s)\n", nt_errstr(status));
782 cli_unlink(c, lockfname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
789 static bool run_torture(int dummy)
791 struct cli_state *cli;
796 smbXcli_conn_set_sockopt(cli->conn, sockops);
798 ret = rw_torture(cli);
800 if (!torture_close_connection(cli)) {
807 static bool rw_torture3(struct cli_state *c, char *lockfname)
809 uint16_t fnum = (uint16_t)-1;
814 unsigned countprev = 0;
817 NTSTATUS status = NT_STATUS_OK;
820 for (i = 0; i < sizeof(buf); i += sizeof(uint32_t))
822 SIVAL(buf, i, sys_random());
829 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
830 if (!NT_STATUS_IS_OK(status)) {
831 printf("unlink failed (%s) (normal, this file should "
832 "not exist)\n", nt_errstr(status));
835 status = cli_openx(c, lockfname, O_RDWR | O_CREAT | O_EXCL,
837 if (!NT_STATUS_IS_OK(status)) {
838 printf("first open read/write of %s failed (%s)\n",
839 lockfname, nt_errstr(status));
845 for (i = 0; i < 500 && fnum == (uint16_t)-1; i++)
847 status = cli_openx(c, lockfname, O_RDONLY,
849 if (NT_STATUS_IS_OK(status)) {
854 if (!NT_STATUS_IS_OK(status)) {
855 printf("second open read-only of %s failed (%s)\n",
856 lockfname, nt_errstr(status));
862 for (count = 0; count < sizeof(buf); count += sent)
864 if (count >= countprev) {
865 printf("%d %8d\r", i, count);
868 countprev += (sizeof(buf) / 20);
873 sent = ((unsigned)sys_random()%(20))+ 1;
874 if (sent > sizeof(buf) - count)
876 sent = sizeof(buf) - count;
879 status = cli_writeall(c, fnum, 0, (uint8_t *)buf+count,
881 if (!NT_STATUS_IS_OK(status)) {
882 printf("write failed (%s)\n",
889 status = cli_read(c, fnum, buf_rd+count, count,
890 sizeof(buf)-count, &sent);
891 if(!NT_STATUS_IS_OK(status)) {
892 printf("read failed offset:%d size:%ld (%s)\n",
893 count, (unsigned long)sizeof(buf)-count,
897 } else if (sent > 0) {
898 if (memcmp(buf_rd+count, buf+count, sent) != 0)
900 printf("read/write compare failed\n");
901 printf("offset: %d req %ld recvd %ld\n", count, (unsigned long)sizeof(buf)-count, (unsigned long)sent);
910 status = cli_close(c, fnum);
911 if (!NT_STATUS_IS_OK(status)) {
912 printf("close failed (%s)\n", nt_errstr(status));
919 static bool rw_torture2(struct cli_state *c1, struct cli_state *c2)
921 const char *lockfname = "\\torture2.lck";
931 status = cli_unlink(c1, lockfname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
932 if (!NT_STATUS_IS_OK(status)) {
933 printf("unlink failed (%s) (normal, this file should not exist)\n", nt_errstr(status));
936 status = cli_openx(c1, lockfname, O_RDWR | O_CREAT | O_EXCL,
938 if (!NT_STATUS_IS_OK(status)) {
939 printf("first open read/write of %s failed (%s)\n",
940 lockfname, nt_errstr(status));
944 status = cli_openx(c2, lockfname, O_RDONLY, DENY_NONE, &fnum2);
945 if (!NT_STATUS_IS_OK(status)) {
946 printf("second open read-only of %s failed (%s)\n",
947 lockfname, nt_errstr(status));
948 cli_close(c1, fnum1);
952 for (i = 0; i < torture_numops; i++)
954 size_t buf_size = ((unsigned)sys_random()%(sizeof(buf)-1))+ 1;
956 printf("%d\r", i); fflush(stdout);
959 generate_random_buffer((unsigned char *)buf, buf_size);
961 status = cli_writeall(c1, fnum1, 0, (uint8_t *)buf, 0,
963 if (!NT_STATUS_IS_OK(status)) {
964 printf("write failed (%s)\n", nt_errstr(status));
969 status = cli_read(c2, fnum2, buf_rd, 0, buf_size, &bytes_read);
970 if(!NT_STATUS_IS_OK(status)) {
971 printf("read failed (%s)\n", nt_errstr(status));
974 } else if (bytes_read != buf_size) {
975 printf("read failed\n");
976 printf("read %ld, expected %ld\n",
977 (unsigned long)bytes_read,
978 (unsigned long)buf_size);
983 if (memcmp(buf_rd, buf, buf_size) != 0)
985 printf("read/write compare failed\n");
991 status = cli_close(c2, fnum2);
992 if (!NT_STATUS_IS_OK(status)) {
993 printf("close failed (%s)\n", nt_errstr(status));
997 status = cli_close(c1, fnum1);
998 if (!NT_STATUS_IS_OK(status)) {
999 printf("close failed (%s)\n", nt_errstr(status));
1003 status = cli_unlink(c1, lockfname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1004 if (!NT_STATUS_IS_OK(status)) {
1005 printf("unlink failed (%s)\n", nt_errstr(status));
1012 static bool run_readwritetest(int dummy)
1014 struct cli_state *cli1, *cli2;
1015 bool test1, test2 = False;
1017 if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
1020 smbXcli_conn_set_sockopt(cli1->conn, sockops);
1021 smbXcli_conn_set_sockopt(cli2->conn, sockops);
1023 printf("starting readwritetest\n");
1025 test1 = rw_torture2(cli1, cli2);
1026 printf("Passed readwritetest v1: %s\n", BOOLSTR(test1));
1029 test2 = rw_torture2(cli1, cli1);
1030 printf("Passed readwritetest v2: %s\n", BOOLSTR(test2));
1033 if (!torture_close_connection(cli1)) {
1037 if (!torture_close_connection(cli2)) {
1041 return (test1 && test2);
1044 static bool run_readwritemulti(int dummy)
1046 struct cli_state *cli;
1051 smbXcli_conn_set_sockopt(cli->conn, sockops);
1053 printf("run_readwritemulti: fname %s\n", randomfname);
1054 test = rw_torture3(cli, randomfname);
1056 if (!torture_close_connection(cli)) {
1063 static bool run_readwritelarge_internal(void)
1065 static struct cli_state *cli1;
1067 const char *lockfname = "\\large.dat";
1070 bool correct = True;
1073 if (!torture_open_connection(&cli1, 0)) {
1076 smbXcli_conn_set_sockopt(cli1->conn, sockops);
1077 memset(buf,'\0',sizeof(buf));
1079 printf("starting readwritelarge_internal\n");
1081 cli_unlink(cli1, lockfname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1083 status = cli_openx(cli1, lockfname, O_RDWR | O_CREAT | O_EXCL,
1085 if (!NT_STATUS_IS_OK(status)) {
1086 printf("open read/write of %s failed (%s)\n", lockfname, nt_errstr(status));
1090 cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 0, sizeof(buf), NULL);
1092 status = cli_qfileinfo_basic(cli1, fnum1, NULL, &fsize, NULL, NULL,
1094 if (!NT_STATUS_IS_OK(status)) {
1095 printf("qfileinfo failed (%s)\n", nt_errstr(status));
1099 if (fsize == sizeof(buf))
1100 printf("readwritelarge_internal test 1 succeeded (size = %lx)\n",
1101 (unsigned long)fsize);
1103 printf("readwritelarge_internal test 1 failed (size = %lx)\n",
1104 (unsigned long)fsize);
1108 status = cli_close(cli1, fnum1);
1109 if (!NT_STATUS_IS_OK(status)) {
1110 printf("close failed (%s)\n", nt_errstr(status));
1114 status = cli_unlink(cli1, lockfname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1115 if (!NT_STATUS_IS_OK(status)) {
1116 printf("unlink failed (%s)\n", nt_errstr(status));
1120 status = cli_openx(cli1, lockfname, O_RDWR | O_CREAT | O_EXCL,
1122 if (!NT_STATUS_IS_OK(status)) {
1123 printf("open read/write of %s failed (%s)\n", lockfname, nt_errstr(status));
1127 cli_smbwrite(cli1, fnum1, buf, 0, sizeof(buf), NULL);
1129 status = cli_qfileinfo_basic(cli1, fnum1, NULL, &fsize, NULL, NULL,
1131 if (!NT_STATUS_IS_OK(status)) {
1132 printf("qfileinfo failed (%s)\n", nt_errstr(status));
1136 if (fsize == sizeof(buf))
1137 printf("readwritelarge_internal test 2 succeeded (size = %lx)\n",
1138 (unsigned long)fsize);
1140 printf("readwritelarge_internal test 2 failed (size = %lx)\n",
1141 (unsigned long)fsize);
1145 status = cli_close(cli1, fnum1);
1146 if (!NT_STATUS_IS_OK(status)) {
1147 printf("close failed (%s)\n", nt_errstr(status));
1151 if (!torture_close_connection(cli1)) {
1157 static bool run_readwritelarge(int dummy)
1159 return run_readwritelarge_internal();
1162 static bool run_readwritelarge_signtest(int dummy)
1165 signing_state = SMB_SIGNING_REQUIRED;
1166 ret = run_readwritelarge_internal();
1167 signing_state = SMB_SIGNING_DEFAULT;
1174 #define ival(s) strtol(s, NULL, 0)
1176 /* run a test that simulates an approximate netbench client load */
1177 static bool run_netbench(int client)
1179 struct cli_state *cli;
1184 const char *params[20];
1185 bool correct = True;
1191 smbXcli_conn_set_sockopt(cli->conn, sockops);
1195 slprintf(cname,sizeof(cname)-1, "client%d", client);
1197 f = fopen(client_txt, "r");
1204 while (fgets(line, sizeof(line)-1, f)) {
1208 line[strlen(line)-1] = 0;
1210 /* printf("[%d] %s\n", line_count, line); */
1212 all_string_sub(line,"client1", cname, sizeof(line));
1214 /* parse the command parameters */
1215 params[0] = strtok_r(line, " ", &saveptr);
1217 while (params[i]) params[++i] = strtok_r(NULL, " ", &saveptr);
1221 if (i < 2) continue;
1223 if (!strncmp(params[0],"SMB", 3)) {
1224 printf("ERROR: You are using a dbench 1 load file\n");
1228 if (!strcmp(params[0],"NTCreateX")) {
1229 nb_createx(params[1], ival(params[2]), ival(params[3]),
1231 } else if (!strcmp(params[0],"Close")) {
1232 nb_close(ival(params[1]));
1233 } else if (!strcmp(params[0],"Rename")) {
1234 nb_rename(params[1], params[2]);
1235 } else if (!strcmp(params[0],"Unlink")) {
1236 nb_unlink(params[1]);
1237 } else if (!strcmp(params[0],"Deltree")) {
1238 nb_deltree(params[1]);
1239 } else if (!strcmp(params[0],"Rmdir")) {
1240 nb_rmdir(params[1]);
1241 } else if (!strcmp(params[0],"QUERY_PATH_INFORMATION")) {
1242 nb_qpathinfo(params[1]);
1243 } else if (!strcmp(params[0],"QUERY_FILE_INFORMATION")) {
1244 nb_qfileinfo(ival(params[1]));
1245 } else if (!strcmp(params[0],"QUERY_FS_INFORMATION")) {
1246 nb_qfsinfo(ival(params[1]));
1247 } else if (!strcmp(params[0],"FIND_FIRST")) {
1248 nb_findfirst(params[1]);
1249 } else if (!strcmp(params[0],"WriteX")) {
1250 nb_writex(ival(params[1]),
1251 ival(params[2]), ival(params[3]), ival(params[4]));
1252 } else if (!strcmp(params[0],"ReadX")) {
1253 nb_readx(ival(params[1]),
1254 ival(params[2]), ival(params[3]), ival(params[4]));
1255 } else if (!strcmp(params[0],"Flush")) {
1256 nb_flush(ival(params[1]));
1258 printf("Unknown operation %s\n", params[0]);
1266 if (!torture_close_connection(cli)) {
1274 /* run a test that simulates an approximate netbench client load */
1275 static bool run_nbench(int dummy)
1278 bool correct = True;
1280 nbio_shmem(torture_nprocs);
1284 signal(SIGALRM, nb_alarm);
1286 t = create_procs(run_netbench, &correct);
1289 printf("\nThroughput %g MB/sec\n",
1290 1.0e-6 * nbio_total() / t);
1296 This test checks for two things:
1298 1) correct support for retaining locks over a close (ie. the server
1299 must not use posix semantics)
1300 2) support for lock timeouts
1302 static bool run_locktest1(int dummy)
1304 struct cli_state *cli1, *cli2;
1305 const char *fname = "\\lockt1.lck";
1306 uint16_t fnum1, fnum2, fnum3;
1308 unsigned lock_timeout;
1311 if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
1314 smbXcli_conn_set_sockopt(cli1->conn, sockops);
1315 smbXcli_conn_set_sockopt(cli2->conn, sockops);
1317 printf("starting locktest1\n");
1319 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1321 status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
1323 if (!NT_STATUS_IS_OK(status)) {
1324 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
1328 status = cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum2);
1329 if (!NT_STATUS_IS_OK(status)) {
1330 printf("open2 of %s failed (%s)\n", fname, nt_errstr(status));
1334 status = cli_openx(cli2, fname, O_RDWR, DENY_NONE, &fnum3);
1335 if (!NT_STATUS_IS_OK(status)) {
1336 printf("open3 of %s failed (%s)\n", fname, nt_errstr(status));
1340 status = cli_lock32(cli1, fnum1, 0, 4, 0, WRITE_LOCK);
1341 if (!NT_STATUS_IS_OK(status)) {
1342 printf("lock1 failed (%s)\n", nt_errstr(status));
1346 status = cli_lock32(cli2, fnum3, 0, 4, 0, WRITE_LOCK);
1347 if (NT_STATUS_IS_OK(status)) {
1348 printf("lock2 succeeded! This is a locking bug\n");
1351 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1352 NT_STATUS_LOCK_NOT_GRANTED)) {
1357 lock_timeout = (1 + (random() % 20));
1358 printf("Testing lock timeout with timeout=%u\n", lock_timeout);
1360 status = cli_lock32(cli2, fnum3, 0, 4, lock_timeout * 1000, WRITE_LOCK);
1361 if (NT_STATUS_IS_OK(status)) {
1362 printf("lock3 succeeded! This is a locking bug\n");
1365 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1366 NT_STATUS_FILE_LOCK_CONFLICT)) {
1372 if (ABS(t2 - t1) < lock_timeout-1) {
1373 printf("error: This server appears not to support timed lock requests\n");
1376 printf("server slept for %u seconds for a %u second timeout\n",
1377 (unsigned int)(t2-t1), lock_timeout);
1379 status = cli_close(cli1, fnum2);
1380 if (!NT_STATUS_IS_OK(status)) {
1381 printf("close1 failed (%s)\n", nt_errstr(status));
1385 status = cli_lock32(cli2, fnum3, 0, 4, 0, WRITE_LOCK);
1386 if (NT_STATUS_IS_OK(status)) {
1387 printf("lock4 succeeded! This is a locking bug\n");
1390 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1391 NT_STATUS_FILE_LOCK_CONFLICT)) {
1396 status = cli_close(cli1, fnum1);
1397 if (!NT_STATUS_IS_OK(status)) {
1398 printf("close2 failed (%s)\n", nt_errstr(status));
1402 status = cli_close(cli2, fnum3);
1403 if (!NT_STATUS_IS_OK(status)) {
1404 printf("close3 failed (%s)\n", nt_errstr(status));
1408 status = cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1409 if (!NT_STATUS_IS_OK(status)) {
1410 printf("unlink failed (%s)\n", nt_errstr(status));
1415 if (!torture_close_connection(cli1)) {
1419 if (!torture_close_connection(cli2)) {
1423 printf("Passed locktest1\n");
1428 this checks to see if a secondary tconx can use open files from an
1431 static bool run_tcon_test(int dummy)
1433 static struct cli_state *cli;
1434 const char *fname = "\\tcontest.tmp";
1436 uint32_t cnum1, cnum2, cnum3;
1437 struct smbXcli_tcon *orig_tcon = NULL;
1438 uint16_t vuid1, vuid2;
1443 memset(buf, '\0', sizeof(buf));
1445 if (!torture_open_connection(&cli, 0)) {
1448 smbXcli_conn_set_sockopt(cli->conn, sockops);
1450 printf("starting tcontest\n");
1452 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1454 status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
1455 if (!NT_STATUS_IS_OK(status)) {
1456 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
1460 cnum1 = cli_state_get_tid(cli);
1461 vuid1 = cli_state_get_uid(cli);
1463 status = cli_writeall(cli, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
1464 if (!NT_STATUS_IS_OK(status)) {
1465 printf("initial write failed (%s)", nt_errstr(status));
1469 orig_tcon = cli_state_save_tcon(cli);
1470 if (orig_tcon == NULL) {
1474 status = cli_tree_connect_creds(cli, share, "?????", torture_creds);
1475 if (!NT_STATUS_IS_OK(status)) {
1476 printf("%s refused 2nd tree connect (%s)\n", host,
1478 cli_state_restore_tcon(cli, orig_tcon);
1483 cnum2 = cli_state_get_tid(cli);
1484 cnum3 = MAX(cnum1, cnum2) + 1; /* any invalid number */
1485 vuid2 = cli_state_get_uid(cli) + 1;
1487 /* try a write with the wrong tid */
1488 cli_state_set_tid(cli, cnum2);
1490 status = cli_writeall(cli, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
1491 if (NT_STATUS_IS_OK(status)) {
1492 printf("* server allows write with wrong TID\n");
1495 printf("server fails write with wrong TID : %s\n",
1500 /* try a write with an invalid tid */
1501 cli_state_set_tid(cli, cnum3);
1503 status = cli_writeall(cli, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
1504 if (NT_STATUS_IS_OK(status)) {
1505 printf("* server allows write with invalid TID\n");
1508 printf("server fails write with invalid TID : %s\n",
1512 /* try a write with an invalid vuid */
1513 cli_state_set_uid(cli, vuid2);
1514 cli_state_set_tid(cli, cnum1);
1516 status = cli_writeall(cli, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
1517 if (NT_STATUS_IS_OK(status)) {
1518 printf("* server allows write with invalid VUID\n");
1521 printf("server fails write with invalid VUID : %s\n",
1525 cli_state_set_tid(cli, cnum1);
1526 cli_state_set_uid(cli, vuid1);
1528 status = cli_close(cli, fnum1);
1529 if (!NT_STATUS_IS_OK(status)) {
1530 printf("close failed (%s)\n", nt_errstr(status));
1531 cli_state_restore_tcon(cli, orig_tcon);
1536 cli_state_set_tid(cli, cnum2);
1538 status = cli_tdis(cli);
1539 if (!NT_STATUS_IS_OK(status)) {
1540 printf("secondary tdis failed (%s)\n", nt_errstr(status));
1541 cli_state_restore_tcon(cli, orig_tcon);
1546 cli_state_restore_tcon(cli, orig_tcon);
1548 cli_state_set_tid(cli, cnum1);
1550 if (!torture_close_connection(cli)) {
1559 checks for old style tcon support
1561 static bool run_tcon2_test(int dummy)
1563 static struct cli_state *cli;
1564 uint16_t cnum, max_xmit;
1568 if (!torture_open_connection(&cli, 0)) {
1571 smbXcli_conn_set_sockopt(cli->conn, sockops);
1573 printf("starting tcon2 test\n");
1575 if (asprintf(&service, "\\\\%s\\%s", host, share) == -1) {
1579 status = cli_raw_tcon(cli, service, password, "?????", &max_xmit, &cnum);
1583 if (!NT_STATUS_IS_OK(status)) {
1584 printf("tcon2 failed : %s\n", nt_errstr(status));
1586 printf("tcon OK : max_xmit=%d cnum=%d\n",
1587 (int)max_xmit, (int)cnum);
1590 if (!torture_close_connection(cli)) {
1594 printf("Passed tcon2 test\n");
1598 static bool tcon_devtest(struct cli_state *cli,
1599 const char *myshare, const char *devtype,
1600 const char *return_devtype,
1601 NTSTATUS expected_error)
1606 status = cli_tree_connect_creds(cli, myshare, devtype, torture_creds);
1608 if (NT_STATUS_IS_OK(expected_error)) {
1609 if (NT_STATUS_IS_OK(status)) {
1610 if (return_devtype != NULL &&
1611 strequal(cli->dev, return_devtype)) {
1614 printf("tconX to share %s with type %s "
1615 "succeeded but returned the wrong "
1616 "device type (got [%s] but should have got [%s])\n",
1617 myshare, devtype, cli->dev, return_devtype);
1621 printf("tconX to share %s with type %s "
1622 "should have succeeded but failed\n",
1628 if (NT_STATUS_IS_OK(status)) {
1629 printf("tconx to share %s with type %s "
1630 "should have failed but succeeded\n",
1634 if (NT_STATUS_EQUAL(status, expected_error)) {
1637 printf("Returned unexpected error\n");
1646 checks for correct tconX support
1648 static bool run_tcon_devtype_test(int dummy)
1650 static struct cli_state *cli1 = NULL;
1651 int flags = CLI_FULL_CONNECTION_FORCE_SMB1;
1655 status = cli_full_connection_creds(&cli1,
1661 NULL, /* service_type */
1665 if (!NT_STATUS_IS_OK(status)) {
1666 printf("could not open connection\n");
1670 if (!tcon_devtest(cli1, "IPC$", "A:", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1673 if (!tcon_devtest(cli1, "IPC$", "?????", "IPC", NT_STATUS_OK))
1676 if (!tcon_devtest(cli1, "IPC$", "LPT:", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1679 if (!tcon_devtest(cli1, "IPC$", "IPC", "IPC", NT_STATUS_OK))
1682 if (!tcon_devtest(cli1, "IPC$", "FOOBA", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1685 if (!tcon_devtest(cli1, share, "A:", "A:", NT_STATUS_OK))
1688 if (!tcon_devtest(cli1, share, "?????", "A:", NT_STATUS_OK))
1691 if (!tcon_devtest(cli1, share, "LPT:", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1694 if (!tcon_devtest(cli1, share, "IPC", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1697 if (!tcon_devtest(cli1, share, "FOOBA", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1703 printf("Passed tcondevtest\n");
1710 This test checks that
1712 1) the server supports multiple locking contexts on the one SMB
1713 connection, distinguished by PID.
1715 2) the server correctly fails overlapping locks made by the same PID (this
1716 goes against POSIX behaviour, which is why it is tricky to implement)
1718 3) the server denies unlock requests by an incorrect client PID
1720 static bool run_locktest2(int dummy)
1722 static struct cli_state *cli;
1723 const char *fname = "\\lockt2.lck";
1724 uint16_t fnum1, fnum2, fnum3;
1725 bool correct = True;
1728 if (!torture_open_connection(&cli, 0)) {
1732 smbXcli_conn_set_sockopt(cli->conn, sockops);
1734 printf("starting locktest2\n");
1736 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1740 status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
1741 if (!NT_STATUS_IS_OK(status)) {
1742 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
1746 status = cli_openx(cli, fname, O_RDWR, DENY_NONE, &fnum2);
1747 if (!NT_STATUS_IS_OK(status)) {
1748 printf("open2 of %s failed (%s)\n", fname, nt_errstr(status));
1754 status = cli_openx(cli, fname, O_RDWR, DENY_NONE, &fnum3);
1755 if (!NT_STATUS_IS_OK(status)) {
1756 printf("open3 of %s failed (%s)\n", fname, nt_errstr(status));
1762 status = cli_lock32(cli, fnum1, 0, 4, 0, WRITE_LOCK);
1763 if (!NT_STATUS_IS_OK(status)) {
1764 printf("lock1 failed (%s)\n", nt_errstr(status));
1768 status = cli_lock32(cli, fnum1, 0, 4, 0, WRITE_LOCK);
1769 if (NT_STATUS_IS_OK(status)) {
1770 printf("WRITE lock1 succeeded! This is a locking bug\n");
1773 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1774 NT_STATUS_LOCK_NOT_GRANTED)) {
1779 status = cli_lock32(cli, fnum2, 0, 4, 0, WRITE_LOCK);
1780 if (NT_STATUS_IS_OK(status)) {
1781 printf("WRITE lock2 succeeded! This is a locking bug\n");
1784 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1785 NT_STATUS_LOCK_NOT_GRANTED)) {
1790 status = cli_lock32(cli, fnum2, 0, 4, 0, READ_LOCK);
1791 if (NT_STATUS_IS_OK(status)) {
1792 printf("READ lock2 succeeded! This is a locking bug\n");
1795 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1796 NT_STATUS_FILE_LOCK_CONFLICT)) {
1801 status = cli_lock32(cli, fnum1, 100, 4, 0, WRITE_LOCK);
1802 if (!NT_STATUS_IS_OK(status)) {
1803 printf("lock at 100 failed (%s)\n", nt_errstr(status));
1806 if (NT_STATUS_IS_OK(cli_unlock(cli, fnum1, 100, 4))) {
1807 printf("unlock at 100 succeeded! This is a locking bug\n");
1811 status = cli_unlock(cli, fnum1, 0, 4);
1812 if (NT_STATUS_IS_OK(status)) {
1813 printf("unlock1 succeeded! This is a locking bug\n");
1816 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1817 NT_STATUS_RANGE_NOT_LOCKED)) {
1822 status = cli_unlock(cli, fnum1, 0, 8);
1823 if (NT_STATUS_IS_OK(status)) {
1824 printf("unlock2 succeeded! This is a locking bug\n");
1827 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1828 NT_STATUS_RANGE_NOT_LOCKED)) {
1833 status = cli_lock32(cli, fnum3, 0, 4, 0, WRITE_LOCK);
1834 if (NT_STATUS_IS_OK(status)) {
1835 printf("lock3 succeeded! This is a locking bug\n");
1838 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1839 NT_STATUS_LOCK_NOT_GRANTED)) {
1846 status = cli_close(cli, fnum1);
1847 if (!NT_STATUS_IS_OK(status)) {
1848 printf("close1 failed (%s)\n", nt_errstr(status));
1852 status = cli_close(cli, fnum2);
1853 if (!NT_STATUS_IS_OK(status)) {
1854 printf("close2 failed (%s)\n", nt_errstr(status));
1858 status = cli_close(cli, fnum3);
1859 if (!NT_STATUS_IS_OK(status)) {
1860 printf("close3 failed (%s)\n", nt_errstr(status));
1864 if (!torture_close_connection(cli)) {
1868 printf("locktest2 finished\n");
1875 This test checks that
1877 1) the server supports the full offset range in lock requests
1879 static bool run_locktest3(int dummy)
1881 static struct cli_state *cli1, *cli2;
1882 const char *fname = "\\lockt3.lck";
1883 uint16_t fnum1, fnum2;
1886 bool correct = True;
1889 #define NEXT_OFFSET offset += (~(uint32_t)0) / torture_numops
1891 if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
1894 smbXcli_conn_set_sockopt(cli1->conn, sockops);
1895 smbXcli_conn_set_sockopt(cli2->conn, sockops);
1897 printf("starting locktest3\n");
1899 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1901 status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
1903 if (!NT_STATUS_IS_OK(status)) {
1904 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
1908 status = cli_openx(cli2, fname, O_RDWR, DENY_NONE, &fnum2);
1909 if (!NT_STATUS_IS_OK(status)) {
1910 printf("open2 of %s failed (%s)\n", fname, nt_errstr(status));
1914 for (offset=i=0;i<torture_numops;i++) {
1917 status = cli_lock32(cli1, fnum1, offset-1, 1, 0, WRITE_LOCK);
1918 if (!NT_STATUS_IS_OK(status)) {
1919 printf("lock1 %d failed (%s)\n",
1925 status = cli_lock32(cli2, fnum2, offset-2, 1, 0, WRITE_LOCK);
1926 if (!NT_STATUS_IS_OK(status)) {
1927 printf("lock2 %d failed (%s)\n",
1934 for (offset=i=0;i<torture_numops;i++) {
1937 status = cli_lock32(cli1, fnum1, offset-2, 1, 0, WRITE_LOCK);
1938 if (NT_STATUS_IS_OK(status)) {
1939 printf("error: lock1 %d succeeded!\n", i);
1943 status = cli_lock32(cli2, fnum2, offset-1, 1, 0, WRITE_LOCK);
1944 if (NT_STATUS_IS_OK(status)) {
1945 printf("error: lock2 %d succeeded!\n", i);
1949 status = cli_lock32(cli1, fnum1, offset-1, 1, 0, WRITE_LOCK);
1950 if (NT_STATUS_IS_OK(status)) {
1951 printf("error: lock3 %d succeeded!\n", i);
1955 status = cli_lock32(cli2, fnum2, offset-2, 1, 0, WRITE_LOCK);
1956 if (NT_STATUS_IS_OK(status)) {
1957 printf("error: lock4 %d succeeded!\n", i);
1962 for (offset=i=0;i<torture_numops;i++) {
1965 status = cli_unlock(cli1, fnum1, offset-1, 1);
1966 if (!NT_STATUS_IS_OK(status)) {
1967 printf("unlock1 %d failed (%s)\n",
1973 status = cli_unlock(cli2, fnum2, offset-2, 1);
1974 if (!NT_STATUS_IS_OK(status)) {
1975 printf("unlock2 %d failed (%s)\n",
1982 status = cli_close(cli1, fnum1);
1983 if (!NT_STATUS_IS_OK(status)) {
1984 printf("close1 failed (%s)\n", nt_errstr(status));
1988 status = cli_close(cli2, fnum2);
1989 if (!NT_STATUS_IS_OK(status)) {
1990 printf("close2 failed (%s)\n", nt_errstr(status));
1994 status = cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1995 if (!NT_STATUS_IS_OK(status)) {
1996 printf("unlink failed (%s)\n", nt_errstr(status));
2000 if (!torture_close_connection(cli1)) {
2004 if (!torture_close_connection(cli2)) {
2008 printf("finished locktest3\n");
2013 static bool test_cli_read(struct cli_state *cli, uint16_t fnum,
2014 char *buf, off_t offset, size_t size,
2015 size_t *nread, size_t expect)
2020 status = cli_read(cli, fnum, buf, offset, size, &l_nread);
2022 if(!NT_STATUS_IS_OK(status)) {
2024 } else if (l_nread != expect) {
2035 #define EXPECTED(ret, v) if ((ret) != (v)) { \
2036 printf("** "); correct = False; \
2040 looks at overlapping locks
2042 static bool run_locktest4(int dummy)
2044 static struct cli_state *cli1, *cli2;
2045 const char *fname = "\\lockt4.lck";
2046 uint16_t fnum1, fnum2, f;
2049 bool correct = True;
2052 if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
2056 smbXcli_conn_set_sockopt(cli1->conn, sockops);
2057 smbXcli_conn_set_sockopt(cli2->conn, sockops);
2059 printf("starting locktest4\n");
2061 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2063 cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
2064 cli_openx(cli2, fname, O_RDWR, DENY_NONE, &fnum2);
2066 memset(buf, 0, sizeof(buf));
2068 status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 0, sizeof(buf),
2070 if (!NT_STATUS_IS_OK(status)) {
2071 printf("Failed to create file: %s\n", nt_errstr(status));
2076 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 4, 0, WRITE_LOCK)) &&
2077 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 2, 4, 0, WRITE_LOCK));
2078 EXPECTED(ret, False);
2079 printf("the same process %s set overlapping write locks\n", ret?"can":"cannot");
2081 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 10, 4, 0, READ_LOCK)) &&
2082 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 12, 4, 0, READ_LOCK));
2083 EXPECTED(ret, True);
2084 printf("the same process %s set overlapping read locks\n", ret?"can":"cannot");
2086 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 20, 4, 0, WRITE_LOCK)) &&
2087 NT_STATUS_IS_OK(cli_lock32(cli2, fnum2, 22, 4, 0, WRITE_LOCK));
2088 EXPECTED(ret, False);
2089 printf("a different connection %s set overlapping write locks\n", ret?"can":"cannot");
2091 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 30, 4, 0, READ_LOCK)) &&
2092 NT_STATUS_IS_OK(cli_lock32(cli2, fnum2, 32, 4, 0, READ_LOCK));
2093 EXPECTED(ret, True);
2094 printf("a different connection %s set overlapping read locks\n", ret?"can":"cannot");
2096 ret = (cli_setpid(cli1, 1),
2097 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 40, 4, 0, WRITE_LOCK))) &&
2098 (cli_setpid(cli1, 2),
2099 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 42, 4, 0, WRITE_LOCK)));
2100 EXPECTED(ret, False);
2101 printf("a different pid %s set overlapping write locks\n", ret?"can":"cannot");
2103 ret = (cli_setpid(cli1, 1),
2104 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 50, 4, 0, READ_LOCK))) &&
2105 (cli_setpid(cli1, 2),
2106 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 52, 4, 0, READ_LOCK)));
2107 EXPECTED(ret, True);
2108 printf("a different pid %s set overlapping read locks\n", ret?"can":"cannot");
2110 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 60, 4, 0, READ_LOCK)) &&
2111 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 60, 4, 0, READ_LOCK));
2112 EXPECTED(ret, True);
2113 printf("the same process %s set the same read lock twice\n", ret?"can":"cannot");
2115 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 70, 4, 0, WRITE_LOCK)) &&
2116 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 70, 4, 0, WRITE_LOCK));
2117 EXPECTED(ret, False);
2118 printf("the same process %s set the same write lock twice\n", ret?"can":"cannot");
2120 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 80, 4, 0, READ_LOCK)) &&
2121 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 80, 4, 0, WRITE_LOCK));
2122 EXPECTED(ret, False);
2123 printf("the same process %s overlay a read lock with a write lock\n", ret?"can":"cannot");
2125 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 90, 4, 0, WRITE_LOCK)) &&
2126 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 90, 4, 0, READ_LOCK));
2127 EXPECTED(ret, True);
2128 printf("the same process %s overlay a write lock with a read lock\n", ret?"can":"cannot");
2130 ret = (cli_setpid(cli1, 1),
2131 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 100, 4, 0, WRITE_LOCK))) &&
2132 (cli_setpid(cli1, 2),
2133 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 100, 4, 0, READ_LOCK)));
2134 EXPECTED(ret, False);
2135 printf("a different pid %s overlay a write lock with a read lock\n", ret?"can":"cannot");
2137 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 110, 4, 0, READ_LOCK)) &&
2138 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 112, 4, 0, READ_LOCK)) &&
2139 NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 110, 6));
2140 EXPECTED(ret, False);
2141 printf("the same process %s coalesce read locks\n", ret?"can":"cannot");
2144 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 120, 4, 0, WRITE_LOCK)) &&
2145 test_cli_read(cli2, fnum2, buf, 120, 4, NULL, 4);
2146 EXPECTED(ret, False);
2147 printf("this server %s strict write locking\n", ret?"doesn't do":"does");
2149 status = cli_lock32(cli1, fnum1, 130, 4, 0, READ_LOCK);
2150 ret = NT_STATUS_IS_OK(status);
2152 status = cli_writeall(cli2, fnum2, 0, (uint8_t *)buf, 130, 4,
2154 ret = NT_STATUS_IS_OK(status);
2156 EXPECTED(ret, False);
2157 printf("this server %s strict read locking\n", ret?"doesn't do":"does");
2160 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 140, 4, 0, READ_LOCK)) &&
2161 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 140, 4, 0, READ_LOCK)) &&
2162 NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 140, 4)) &&
2163 NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 140, 4));
2164 EXPECTED(ret, True);
2165 printf("this server %s do recursive read locking\n", ret?"does":"doesn't");
2168 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 150, 4, 0, WRITE_LOCK)) &&
2169 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 150, 4, 0, READ_LOCK)) &&
2170 NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 150, 4)) &&
2171 test_cli_read(cli2, fnum2, buf, 150, 4, NULL, 4) &&
2172 !(NT_STATUS_IS_OK(cli_writeall(cli2, fnum2, 0, (uint8_t *)buf,
2174 NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 150, 4));
2175 EXPECTED(ret, True);
2176 printf("this server %s do recursive lock overlays\n", ret?"does":"doesn't");
2178 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 160, 4, 0, READ_LOCK)) &&
2179 NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 160, 4)) &&
2180 NT_STATUS_IS_OK(cli_writeall(cli2, fnum2, 0, (uint8_t *)buf,
2182 test_cli_read(cli2, fnum2, buf, 160, 4, NULL, 4);
2183 EXPECTED(ret, True);
2184 printf("the same process %s remove a read lock using write locking\n", ret?"can":"cannot");
2186 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 170, 4, 0, WRITE_LOCK)) &&
2187 NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 170, 4)) &&
2188 NT_STATUS_IS_OK(cli_writeall(cli2, fnum2, 0, (uint8_t *)buf,
2190 test_cli_read(cli2, fnum2, buf, 170, 4, NULL, 4);
2191 EXPECTED(ret, True);
2192 printf("the same process %s remove a write lock using read locking\n", ret?"can":"cannot");
2194 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 190, 4, 0, WRITE_LOCK)) &&
2195 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 190, 4, 0, READ_LOCK)) &&
2196 NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 190, 4)) &&
2197 !NT_STATUS_IS_OK(cli_writeall(cli2, fnum2, 0, (uint8_t *)buf,
2199 test_cli_read(cli2, fnum2, buf, 190, 4, NULL, 4);
2200 EXPECTED(ret, True);
2201 printf("the same process %s remove the first lock first\n", ret?"does":"doesn't");
2203 cli_close(cli1, fnum1);
2204 cli_close(cli2, fnum2);
2205 cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
2206 cli_openx(cli1, fname, O_RDWR, DENY_NONE, &f);
2207 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 8, 0, READ_LOCK)) &&
2208 NT_STATUS_IS_OK(cli_lock32(cli1, f, 0, 1, 0, READ_LOCK)) &&
2209 NT_STATUS_IS_OK(cli_close(cli1, fnum1)) &&
2210 NT_STATUS_IS_OK(cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1)) &&
2211 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 7, 1, 0, WRITE_LOCK));
2213 cli_close(cli1, fnum1);
2214 EXPECTED(ret, True);
2215 printf("the server %s have the NT byte range lock bug\n", !ret?"does":"doesn't");
2218 cli_close(cli1, fnum1);
2219 cli_close(cli2, fnum2);
2220 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2221 torture_close_connection(cli1);
2222 torture_close_connection(cli2);
2224 printf("finished locktest4\n");
2229 looks at lock upgrade/downgrade.
2231 static bool run_locktest5(int dummy)
2233 static struct cli_state *cli1, *cli2;
2234 const char *fname = "\\lockt5.lck";
2235 uint16_t fnum1, fnum2, fnum3;
2238 bool correct = True;
2241 if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
2245 smbXcli_conn_set_sockopt(cli1->conn, sockops);
2246 smbXcli_conn_set_sockopt(cli2->conn, sockops);
2248 printf("starting locktest5\n");
2250 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2252 cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
2253 cli_openx(cli2, fname, O_RDWR, DENY_NONE, &fnum2);
2254 cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum3);
2256 memset(buf, 0, sizeof(buf));
2258 status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 0, sizeof(buf),
2260 if (!NT_STATUS_IS_OK(status)) {
2261 printf("Failed to create file: %s\n", nt_errstr(status));
2266 /* Check for NT bug... */
2267 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 8, 0, READ_LOCK)) &&
2268 NT_STATUS_IS_OK(cli_lock32(cli1, fnum3, 0, 1, 0, READ_LOCK));
2269 cli_close(cli1, fnum1);
2270 cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
2271 status = cli_lock32(cli1, fnum1, 7, 1, 0, WRITE_LOCK);
2272 ret = NT_STATUS_IS_OK(status);
2273 EXPECTED(ret, True);
2274 printf("this server %s the NT locking bug\n", ret ? "doesn't have" : "has");
2275 cli_close(cli1, fnum1);
2276 cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
2277 cli_unlock(cli1, fnum3, 0, 1);
2279 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 4, 0, WRITE_LOCK)) &&
2280 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 1, 1, 0, READ_LOCK));
2281 EXPECTED(ret, True);
2282 printf("the same process %s overlay a write with a read lock\n", ret?"can":"cannot");
2284 status = cli_lock32(cli2, fnum2, 0, 4, 0, READ_LOCK);
2285 ret = NT_STATUS_IS_OK(status);
2286 EXPECTED(ret, False);
2288 printf("a different process %s get a read lock on the first process lock stack\n", ret?"can":"cannot");
2290 /* Unlock the process 2 lock. */
2291 cli_unlock(cli2, fnum2, 0, 4);
2293 status = cli_lock32(cli1, fnum3, 0, 4, 0, READ_LOCK);
2294 ret = NT_STATUS_IS_OK(status);
2295 EXPECTED(ret, False);
2297 printf("the same process on a different fnum %s get a read lock\n", ret?"can":"cannot");
2299 /* Unlock the process 1 fnum3 lock. */
2300 cli_unlock(cli1, fnum3, 0, 4);
2302 /* Stack 2 more locks here. */
2303 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 4, 0, READ_LOCK)) &&
2304 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 4, 0, READ_LOCK));
2306 EXPECTED(ret, True);
2307 printf("the same process %s stack read locks\n", ret?"can":"cannot");
2309 /* Unlock the first process lock, then check this was the WRITE lock that was
2312 ret = NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 0, 4)) &&
2313 NT_STATUS_IS_OK(cli_lock32(cli2, fnum2, 0, 4, 0, READ_LOCK));
2315 EXPECTED(ret, True);
2316 printf("the first unlock removes the %s lock\n", ret?"WRITE":"READ");
2318 /* Unlock the process 2 lock. */
2319 cli_unlock(cli2, fnum2, 0, 4);
2321 /* We should have 3 stacked locks here. Ensure we need to do 3 unlocks. */
2323 ret = NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 1, 1)) &&
2324 NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 0, 4)) &&
2325 NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 0, 4));
2327 EXPECTED(ret, True);
2328 printf("the same process %s unlock the stack of 4 locks\n", ret?"can":"cannot");
2330 /* Ensure the next unlock fails. */
2331 ret = NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 0, 4));
2332 EXPECTED(ret, False);
2333 printf("the same process %s count the lock stack\n", !ret?"can":"cannot");
2335 /* Ensure connection 2 can get a write lock. */
2336 status = cli_lock32(cli2, fnum2, 0, 4, 0, WRITE_LOCK);
2337 ret = NT_STATUS_IS_OK(status);
2338 EXPECTED(ret, True);
2340 printf("a different process %s get a write lock on the unlocked stack\n", ret?"can":"cannot");
2344 cli_close(cli1, fnum1);
2345 cli_close(cli2, fnum2);
2346 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2347 if (!torture_close_connection(cli1)) {
2350 if (!torture_close_connection(cli2)) {
2354 printf("finished locktest5\n");
2360 tries the unusual lockingX locktype bits
2362 static bool run_locktest6(int dummy)
2364 static struct cli_state *cli;
2365 const char *fname[1] = { "\\lock6.txt" };
2370 if (!torture_open_connection(&cli, 0)) {
2374 smbXcli_conn_set_sockopt(cli->conn, sockops);
2376 printf("starting locktest6\n");
2379 printf("Testing %s\n", fname[i]);
2381 cli_unlink(cli, fname[i], FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2383 cli_openx(cli, fname[i], O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
2384 status = cli_locktype(cli, fnum, 0, 8, 0, LOCKING_ANDX_CHANGE_LOCKTYPE);
2385 cli_close(cli, fnum);
2386 printf("CHANGE_LOCKTYPE gave %s\n", nt_errstr(status));
2388 cli_openx(cli, fname[i], O_RDWR, DENY_NONE, &fnum);
2389 status = cli_locktype(cli, fnum, 0, 8, 0, LOCKING_ANDX_CANCEL_LOCK);
2390 cli_close(cli, fnum);
2391 printf("CANCEL_LOCK gave %s\n", nt_errstr(status));
2393 cli_unlink(cli, fname[i], FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2396 torture_close_connection(cli);
2398 printf("finished locktest6\n");
2402 static bool run_locktest7(int dummy)
2404 struct cli_state *cli1;
2405 const char *fname = "\\lockt7.lck";
2408 bool correct = False;
2412 if (!torture_open_connection(&cli1, 0)) {
2416 smbXcli_conn_set_sockopt(cli1->conn, sockops);
2418 printf("starting locktest7\n");
2420 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2422 cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
2424 memset(buf, 0, sizeof(buf));
2426 status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 0, sizeof(buf),
2428 if (!NT_STATUS_IS_OK(status)) {
2429 printf("Failed to create file: %s\n", nt_errstr(status));
2433 cli_setpid(cli1, 1);
2435 status = cli_lock32(cli1, fnum1, 130, 4, 0, READ_LOCK);
2436 if (!NT_STATUS_IS_OK(status)) {
2437 printf("Unable to apply read lock on range 130:4, "
2438 "error was %s\n", nt_errstr(status));
2441 printf("pid1 successfully locked range 130:4 for READ\n");
2444 status = cli_read(cli1, fnum1, buf, 130, 4, &nread);
2445 if (!NT_STATUS_IS_OK(status)) {
2446 printf("pid1 unable to read the range 130:4, error was %s\n",
2449 } else if (nread != 4) {
2450 printf("pid1 unable to read the range 130:4, "
2451 "recv %ld req %d\n", (unsigned long)nread, 4);
2454 printf("pid1 successfully read the range 130:4\n");
2457 status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
2458 if (!NT_STATUS_IS_OK(status)) {
2459 printf("pid1 unable to write to the range 130:4, error was "
2460 "%s\n", nt_errstr(status));
2461 if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
2462 printf("Incorrect error (should be NT_STATUS_FILE_LOCK_CONFLICT)\n");
2466 printf("pid1 successfully wrote to the range 130:4 (should be denied)\n");
2470 cli_setpid(cli1, 2);
2472 status = cli_read(cli1, fnum1, buf, 130, 4, &nread);
2473 if (!NT_STATUS_IS_OK(status)) {
2474 printf("pid2 unable to read the range 130:4, error was %s\n",
2477 } else if (nread != 4) {
2478 printf("pid2 unable to read the range 130:4, "
2479 "recv %ld req %d\n", (unsigned long)nread, 4);
2482 printf("pid2 successfully read the range 130:4\n");
2485 status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
2486 if (!NT_STATUS_IS_OK(status)) {
2487 printf("pid2 unable to write to the range 130:4, error was "
2488 "%s\n", nt_errstr(status));
2489 if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
2490 printf("Incorrect error (should be NT_STATUS_FILE_LOCK_CONFLICT)\n");
2494 printf("pid2 successfully wrote to the range 130:4 (should be denied)\n");
2498 cli_setpid(cli1, 1);
2499 cli_unlock(cli1, fnum1, 130, 4);
2501 status = cli_lock32(cli1, fnum1, 130, 4, 0, WRITE_LOCK);
2502 if (!NT_STATUS_IS_OK(status)) {
2503 printf("Unable to apply write lock on range 130:4, error was %s\n", nt_errstr(status));
2506 printf("pid1 successfully locked range 130:4 for WRITE\n");
2509 status = cli_read(cli1, fnum1, buf, 130, 4, &nread);
2510 if (!NT_STATUS_IS_OK(status)) {
2511 printf("pid1 unable to read the range 130:4, error was %s\n",
2514 } else if (nread != 4) {
2515 printf("pid1 unable to read the range 130:4, "
2516 "recv %ld req %d\n", (unsigned long)nread, 4);
2519 printf("pid1 successfully read the range 130:4\n");
2522 status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
2523 if (!NT_STATUS_IS_OK(status)) {
2524 printf("pid1 unable to write to the range 130:4, error was "
2525 "%s\n", nt_errstr(status));
2528 printf("pid1 successfully wrote to the range 130:4\n");
2531 cli_setpid(cli1, 2);
2533 status = cli_read(cli1, fnum1, buf, 130, 4, &nread);
2534 if (!NT_STATUS_IS_OK(status)) {
2535 printf("pid2 unable to read the range 130:4, error was "
2536 "%s\n", nt_errstr(status));
2537 if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
2538 printf("Incorrect error (should be NT_STATUS_FILE_LOCK_CONFLICT)\n");
2542 printf("pid2 successfully read the range 130:4 (should be denied) recv %ld\n",
2543 (unsigned long)nread);
2547 status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
2548 if (!NT_STATUS_IS_OK(status)) {
2549 printf("pid2 unable to write to the range 130:4, error was "
2550 "%s\n", nt_errstr(status));
2551 if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
2552 printf("Incorrect error (should be NT_STATUS_FILE_LOCK_CONFLICT)\n");
2556 printf("pid2 successfully wrote to the range 130:4 (should be denied)\n");
2560 cli_unlock(cli1, fnum1, 130, 0);
2564 cli_close(cli1, fnum1);
2565 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2566 torture_close_connection(cli1);
2568 printf("finished locktest7\n");
2573 * This demonstrates a problem with our use of GPFS share modes: A file
2574 * descriptor sitting in the pending close queue holding a GPFS share mode
2575 * blocks opening a file another time. Happens with Word 2007 temp files.
2576 * With "posix locking = yes" and "gpfs:sharemodes = yes" enabled, the third
2577 * open is denied with NT_STATUS_SHARING_VIOLATION.
2580 static bool run_locktest8(int dummy)
2582 struct cli_state *cli1;
2583 const char *fname = "\\lockt8.lck";
2584 uint16_t fnum1, fnum2;
2586 bool correct = False;
2589 if (!torture_open_connection(&cli1, 0)) {
2593 smbXcli_conn_set_sockopt(cli1->conn, sockops);
2595 printf("starting locktest8\n");
2597 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2599 status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_WRITE,
2601 if (!NT_STATUS_IS_OK(status)) {
2602 d_fprintf(stderr, "cli_openx returned %s\n", nt_errstr(status));
2606 memset(buf, 0, sizeof(buf));
2608 status = cli_openx(cli1, fname, O_RDONLY, DENY_NONE, &fnum2);
2609 if (!NT_STATUS_IS_OK(status)) {
2610 d_fprintf(stderr, "cli_openx second time returned %s\n",
2615 status = cli_lock32(cli1, fnum2, 1, 1, 0, READ_LOCK);
2616 if (!NT_STATUS_IS_OK(status)) {
2617 printf("Unable to apply read lock on range 1:1, error was "
2618 "%s\n", nt_errstr(status));
2622 status = cli_close(cli1, fnum1);
2623 if (!NT_STATUS_IS_OK(status)) {
2624 d_fprintf(stderr, "cli_close(fnum1) %s\n", nt_errstr(status));
2628 status = cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
2629 if (!NT_STATUS_IS_OK(status)) {
2630 d_fprintf(stderr, "cli_openx third time returned %s\n",
2638 cli_close(cli1, fnum1);
2639 cli_close(cli1, fnum2);
2640 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2641 torture_close_connection(cli1);
2643 printf("finished locktest8\n");
2648 * This test is designed to be run in conjunction with
2649 * external NFS or POSIX locks taken in the filesystem.
2650 * It checks that the smbd server will block until the
2651 * lock is released and then acquire it. JRA.
2654 static bool got_alarm;
2655 static struct cli_state *alarm_cli;
2657 static void alarm_handler(int dummy)
2662 static void alarm_handler_parent(int dummy)
2664 smbXcli_conn_disconnect(alarm_cli->conn, NT_STATUS_LOCAL_DISCONNECT);
2667 static void do_local_lock(const char *fname, int read_fd, int write_fd)
2672 const char *local_pathname = NULL;
2675 local_pathname = talloc_asprintf(talloc_tos(),
2676 "%s/%s", local_path, fname);
2677 if (!local_pathname) {
2678 printf("child: alloc fail\n");
2682 unlink(local_pathname);
2683 fd = open(local_pathname, O_RDWR|O_CREAT, 0666);
2685 printf("child: open of %s failed %s.\n",
2686 local_pathname, strerror(errno));
2690 /* Now take a fcntl lock. */
2691 lock.l_type = F_WRLCK;
2692 lock.l_whence = SEEK_SET;
2695 lock.l_pid = getpid();
2697 ret = fcntl(fd,F_SETLK,&lock);
2699 printf("child: failed to get lock 0:4 on file %s. Error %s\n",
2700 local_pathname, strerror(errno));
2703 printf("child: got lock 0:4 on file %s.\n",
2708 CatchSignal(SIGALRM, alarm_handler);
2710 /* Signal the parent. */
2711 if (write(write_fd, &c, 1) != 1) {
2712 printf("child: start signal fail %s.\n",
2719 /* Wait for the parent to be ready. */
2720 if (read(read_fd, &c, 1) != 1) {
2721 printf("child: reply signal fail %s.\n",
2729 printf("child: released lock 0:4 on file %s.\n",
2735 static bool _run_locktest9X(const char *fname, int timeout)
2737 struct cli_state *cli1;
2738 char *fpath = talloc_asprintf(talloc_tos(), "\\%s", fname);
2740 bool correct = False;
2741 int pipe_in[2], pipe_out[2];
2745 struct timeval start;
2749 printf("starting locktest9X: %s\n", fname);
2751 if (local_path == NULL) {
2752 d_fprintf(stderr, "locktest9X must be given a local path via -l <localpath>\n");
2756 if (pipe(pipe_in) == -1 || pipe(pipe_out) == -1) {
2761 if (child_pid == -1) {
2765 if (child_pid == 0) {
2767 do_local_lock(fname, pipe_out[0], pipe_in[1]);
2777 ret = read(pipe_in[0], &c, 1);
2779 d_fprintf(stderr, "failed to read start signal from child. %s\n",
2784 if (!torture_open_connection(&cli1, 0)) {
2788 smbXcli_conn_set_sockopt(cli1->conn, sockops);
2790 status = cli_openx(cli1, fpath, O_RDWR, DENY_NONE,
2792 if (!NT_STATUS_IS_OK(status)) {
2793 d_fprintf(stderr, "cli_openx returned %s\n", nt_errstr(status));
2797 /* Ensure the child has the lock. */
2798 status = cli_lock32(cli1, fnum, 0, 4, 0, WRITE_LOCK);
2799 if (NT_STATUS_IS_OK(status)) {
2800 d_fprintf(stderr, "Got the lock on range 0:4 - this should not happen !\n");
2803 d_printf("Child has the lock.\n");
2806 /* Tell the child to wait 5 seconds then exit. */
2807 ret = write(pipe_out[1], &c, 1);
2809 d_fprintf(stderr, "failed to send exit signal to child. %s\n",
2814 /* Wait 20 seconds for the lock. */
2816 CatchSignal(SIGALRM, alarm_handler_parent);
2819 start = timeval_current();
2821 status = cli_lock32(cli1, fnum, 0, 4, timeout, WRITE_LOCK);
2822 if (!NT_STATUS_IS_OK(status)) {
2823 d_fprintf(stderr, "Unable to apply write lock on range 0:4, error was "
2824 "%s\n", nt_errstr(status));
2829 seconds = timeval_elapsed(&start);
2831 printf("Parent got the lock after %.2f seconds.\n",
2834 status = cli_close(cli1, fnum);
2835 if (!NT_STATUS_IS_OK(status)) {
2836 d_fprintf(stderr, "cli_close(fnum1) %s\n", nt_errstr(status));
2843 cli_close(cli1, fnum);
2844 torture_close_connection(cli1);
2848 printf("finished locktest9X: %s\n", fname);
2852 static bool run_locktest9a(int dummy)
2854 return _run_locktest9X("lock9a.dat", -1);
2857 static bool run_locktest9b(int dummy)
2859 return _run_locktest9X("lock9b.dat", 10000);
2862 struct locktest10_state {
2867 static void locktest10_lockingx_done(struct tevent_req *subreq);
2868 static void locktest10_read_andx_done(struct tevent_req *subreq);
2870 static bool run_locktest10(int dummy)
2872 struct tevent_context *ev = NULL;
2873 struct cli_state *cli1 = NULL;
2874 struct cli_state *cli2 = NULL;
2875 struct smb1_lock_element lck = { 0 };
2876 struct tevent_req *reqs[2] = { NULL };
2877 struct tevent_req *smbreqs[2] = { NULL };
2878 const char fname[] = "\\lockt10.lck";
2879 uint16_t fnum1, fnum2;
2883 struct locktest10_state state = { .ok = true };
2886 printf("starting locktest10\n");
2888 ev = samba_tevent_context_init(NULL);
2890 d_fprintf(stderr, "samba_tevent_context_init failed\n");
2894 ok = torture_open_connection(&cli1, 0);
2898 smbXcli_conn_set_sockopt(cli1->conn, sockops);
2900 ok = torture_open_connection(&cli2, 1);
2904 smbXcli_conn_set_sockopt(cli2->conn, sockops);
2906 status = cli_openx(cli1, fname, O_CREAT|O_RDWR, DENY_NONE, &fnum1);
2907 if (!NT_STATUS_IS_OK(status)) {
2909 "cli_openx failed: %s\n",
2914 status = cli_writeall(cli1, fnum1, 0, &data, 0, sizeof(data), NULL);
2915 if (!NT_STATUS_IS_OK(status)) {
2917 "cli_writeall failed: %s\n",
2922 status = cli_openx(cli2, fname, O_CREAT|O_RDWR, DENY_NONE, &fnum2);
2923 if (!NT_STATUS_IS_OK(status)) {
2925 "cli_openx failed: %s\n",
2930 status = cli_locktype(
2931 cli2, fnum2, 0, 1, 0, LOCKING_ANDX_EXCLUSIVE_LOCK);
2932 if (!NT_STATUS_IS_OK(status)) {
2934 "cli_locktype failed: %s\n",
2939 lck = (struct smb1_lock_element) {
2940 .pid = cli_getpid(cli1), .offset = 0, .length = 1,
2943 reqs[0] = cli_lockingx_create(
2945 ev, /* tevent_context */
2948 LOCKING_ANDX_EXCLUSIVE_LOCK, /* typeoflock */
2949 0, /* newoplocklevel */
2951 0, /* num_unlocks */
2955 &smbreqs[0]); /* psmbreq */
2956 if (reqs[0] == NULL) {
2957 d_fprintf(stderr, "cli_lockingx_create failed\n");
2960 tevent_req_set_callback(reqs[0], locktest10_lockingx_done, &state);
2962 reqs[1] = cli_read_andx_create(
2969 &smbreqs[1]); /* psmbreq */
2970 if (reqs[1] == NULL) {
2971 d_fprintf(stderr, "cli_read_andx_create failed\n");
2974 tevent_req_set_callback(reqs[1], locktest10_read_andx_done, &state);
2976 status = smb1cli_req_chain_submit(smbreqs, ARRAY_SIZE(smbreqs));
2977 if (!NT_STATUS_IS_OK(status)) {
2979 "smb1cli_req_chain_submit failed: %s\n",
2984 while (!state.done) {
2985 tevent_loop_once(ev);
2988 torture_close_connection(cli1);
2997 static void locktest10_lockingx_done(struct tevent_req *subreq)
2999 struct locktest10_state *state = tevent_req_callback_data_void(subreq);
3002 status = cli_lockingx_recv(subreq);
3003 TALLOC_FREE(subreq);
3005 if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
3006 d_printf("cli_lockingx returned %s\n", nt_errstr(status));
3011 static void locktest10_read_andx_done(struct tevent_req *subreq)
3013 struct locktest10_state *state = tevent_req_callback_data_void(subreq);
3014 ssize_t received = -1;
3015 uint8_t *rcvbuf = NULL;
3018 status = cli_read_andx_recv(subreq, &received, &rcvbuf);
3020 if (!NT_STATUS_EQUAL(status, NT_STATUS_REQUEST_ABORTED)) {
3021 d_printf("cli_read_andx returned %s\n", nt_errstr(status));
3026 TALLOC_FREE(subreq);
3029 static bool run_locktest11(int dummy)
3031 struct cli_state *cli1;
3032 const char *fname = "\\lockt11.lck";
3037 if (!torture_open_connection(&cli1, 0)) {
3041 smbXcli_conn_set_sockopt(cli1->conn, sockops);
3043 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3045 status = cli_openx(cli1, fname, O_CREAT|O_RDWR, DENY_NONE, &fnum);
3046 if (!NT_STATUS_IS_OK(status)) {
3048 "cli_openx returned %s\n",
3054 * Test that LOCKING_ANDX_CANCEL_LOCK without any locks
3055 * returns NT_STATUS_OK
3058 status = cli_lockingx(
3061 LOCKING_ANDX_CANCEL_LOCK, /* typeoflock */
3062 0, /* newoplocklevel */
3064 0, /* num_unlocks */
3069 if (!NT_STATUS_IS_OK(status)) {
3070 d_printf("cli_lockingX returned %s\n", nt_errstr(status));
3076 cli_close(cli1, fnum);
3077 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3082 struct deferred_close_state {
3083 struct tevent_context *ev;
3084 struct cli_state *cli;
3088 static void deferred_close_waited(struct tevent_req *subreq);
3089 static void deferred_close_done(struct tevent_req *subreq);
3091 static struct tevent_req *deferred_close_send(
3092 TALLOC_CTX *mem_ctx,
3093 struct tevent_context *ev,
3095 struct cli_state *cli,
3098 struct tevent_req *req = NULL, *subreq = NULL;
3099 struct deferred_close_state *state = NULL;
3100 struct timeval wakeup_time = timeval_current_ofs(wait_secs, 0);
3102 req = tevent_req_create(
3103 mem_ctx, &state, struct deferred_close_state);
3111 subreq = tevent_wakeup_send(state, state->ev, wakeup_time);
3112 if (tevent_req_nomem(subreq, req)) {
3113 return tevent_req_post(req, ev);
3115 tevent_req_set_callback(subreq, deferred_close_waited, req);
3119 static void deferred_close_waited(struct tevent_req *subreq)
3121 struct tevent_req *req = tevent_req_callback_data(
3122 subreq, struct tevent_req);
3123 struct deferred_close_state *state = tevent_req_data(
3124 req, struct deferred_close_state);
3127 ok = tevent_wakeup_recv(subreq);
3128 TALLOC_FREE(subreq);
3130 tevent_req_oom(req);
3134 subreq = cli_close_send(state, state->ev, state->cli, state->fnum);
3135 if (tevent_req_nomem(subreq, req)) {
3138 tevent_req_set_callback(subreq, deferred_close_done, req);
3141 static void deferred_close_done(struct tevent_req *subreq)
3143 NTSTATUS status = cli_close_recv(subreq);
3144 tevent_req_simple_finish_ntstatus(subreq, status);
3147 static NTSTATUS deferred_close_recv(struct tevent_req *req)
3149 return tevent_req_simple_recv_ntstatus(req);
3152 struct lockread_state {
3153 struct smb1_lock_element lck;
3154 struct tevent_req *reqs[2];
3155 struct tevent_req *smbreqs[2];
3156 NTSTATUS lock_status;
3157 NTSTATUS read_status;
3161 static void lockread_lockingx_done(struct tevent_req *subreq);
3162 static void lockread_read_andx_done(struct tevent_req *subreq);
3164 static struct tevent_req *lockread_send(
3165 TALLOC_CTX *mem_ctx,
3166 struct tevent_context *ev,
3167 struct cli_state *cli,
3170 struct tevent_req *req = NULL;
3171 struct lockread_state *state = NULL;
3174 req = tevent_req_create(mem_ctx, &state, struct lockread_state);
3179 state->lck = (struct smb1_lock_element) {
3180 .pid = cli_getpid(cli), .offset = 0, .length = 1,
3183 state->reqs[0] = cli_lockingx_create(
3185 ev, /* tevent_context */
3188 LOCKING_ANDX_EXCLUSIVE_LOCK, /* typeoflock */
3189 0, /* newoplocklevel */
3190 10000, /* timeout */
3191 0, /* num_unlocks */
3194 &state->lck, /* locks */
3195 &state->smbreqs[0]); /* psmbreq */
3196 if (tevent_req_nomem(state->reqs[0], req)) {
3197 return tevent_req_post(req, ev);
3199 tevent_req_set_callback(
3200 state->reqs[0], lockread_lockingx_done, req);
3202 state->reqs[1] = cli_read_andx_create(
3209 &state->smbreqs[1]); /* psmbreq */
3210 if (tevent_req_nomem(state->reqs[1], req)) {
3211 return tevent_req_post(req, ev);
3213 tevent_req_set_callback(
3214 state->reqs[1], lockread_read_andx_done, req);
3216 status = smb1cli_req_chain_submit(state->smbreqs, 2);
3217 if (tevent_req_nterror(req, status)) {
3218 return tevent_req_post(req, ev);
3223 static void lockread_lockingx_done(struct tevent_req *subreq)
3225 struct tevent_req *req = tevent_req_callback_data(
3226 subreq, struct tevent_req);
3227 struct lockread_state *state = tevent_req_data(
3228 req, struct lockread_state);
3229 state->lock_status = cli_lockingx_recv(subreq);
3230 TALLOC_FREE(subreq);
3232 "lockingx returned %s\n",
3233 nt_errstr(state->lock_status));
3236 static void lockread_read_andx_done(struct tevent_req *subreq)
3238 struct tevent_req *req = tevent_req_callback_data(
3239 subreq, struct tevent_req);
3240 struct lockread_state *state = tevent_req_data(
3241 req, struct lockread_state);
3242 ssize_t received = -1;
3243 uint8_t *rcvbuf = NULL;
3245 state->read_status = cli_read_andx_recv(subreq, &received, &rcvbuf);
3248 "read returned %s\n",
3249 nt_errstr(state->read_status));
3251 if (!NT_STATUS_IS_OK(state->read_status)) {
3252 TALLOC_FREE(subreq);
3253 tevent_req_done(req);
3258 state->readbuf = talloc_memdup(state, rcvbuf, received);
3259 TALLOC_FREE(subreq);
3260 if (tevent_req_nomem(state->readbuf, req)) {
3264 TALLOC_FREE(subreq);
3265 tevent_req_done(req);
3268 static NTSTATUS lockread_recv(
3269 struct tevent_req *req,
3270 NTSTATUS *lock_status,
3271 NTSTATUS *read_status,
3272 TALLOC_CTX *mem_ctx,
3275 struct lockread_state *state = tevent_req_data(
3276 req, struct lockread_state);
3279 if (tevent_req_is_nterror(req, &status)) {
3283 *lock_status = state->lock_status;
3284 *read_status = state->read_status;
3285 if (state->readbuf != NULL) {
3286 *read_buf = talloc_move(mem_ctx, &state->readbuf);
3291 return NT_STATUS_OK;
3294 struct lock12_state {
3298 static void lock12_closed(struct tevent_req *subreq);
3299 static void lock12_read(struct tevent_req *subreq);
3301 static struct tevent_req *lock12_send(
3302 TALLOC_CTX *mem_ctx,
3303 struct tevent_context *ev,
3304 struct cli_state *cli,
3308 struct tevent_req *req = NULL, *subreq = NULL;
3309 struct lock12_state *state = NULL;
3311 req = tevent_req_create(mem_ctx, &state, struct lock12_state);
3316 subreq = deferred_close_send(state, ev, 1, cli, fnum1);
3317 if (tevent_req_nomem(subreq, req)) {
3318 return tevent_req_post(req, ev);
3320 tevent_req_set_callback(subreq, lock12_closed, req);
3322 subreq = lockread_send(state, ev, cli, fnum2);
3323 if (tevent_req_nomem(subreq, req)) {
3324 return tevent_req_post(req, ev);
3326 tevent_req_set_callback(subreq, lock12_read, req);
3331 static void lock12_closed(struct tevent_req *subreq)
3333 struct tevent_req *req = tevent_req_callback_data(
3334 subreq, struct tevent_req);
3337 status = deferred_close_recv(subreq);
3338 TALLOC_FREE(subreq);
3339 DBG_DEBUG("close returned %s\n", nt_errstr(status));
3340 if (tevent_req_nterror(req, status)) {
3345 static void lock12_read(struct tevent_req *subreq)
3347 struct tevent_req *req = tevent_req_callback_data(
3348 subreq, struct tevent_req);
3349 struct lock12_state *state = tevent_req_data(
3350 req, struct lock12_state);
3351 NTSTATUS status, lock_status, read_status;
3352 uint8_t *buf = NULL;
3354 status = lockread_recv(
3355 subreq, &lock_status, &read_status, state, &buf);
3356 TALLOC_FREE(subreq);
3357 if (tevent_req_nterror(req, status) ||
3358 tevent_req_nterror(req, lock_status) ||
3359 tevent_req_nterror(req, read_status)) {
3362 tevent_req_done(req);
3365 static NTSTATUS lock12_recv(struct tevent_req *req)
3370 if (tevent_req_is_nterror(req, &status)) {
3373 return NT_STATUS_OK;
3376 static bool run_locktest12(int dummy)
3378 struct tevent_context *ev = NULL;
3379 struct tevent_req *req = NULL;
3380 struct cli_state *cli = NULL;
3381 const char fname[] = "\\lockt12.lck";
3382 uint16_t fnum1, fnum2;
3388 printf("starting locktest12\n");
3390 ev = samba_tevent_context_init(NULL);
3392 d_fprintf(stderr, "samba_tevent_context_init failed\n");
3396 ok = torture_open_connection(&cli, 0);
3400 smbXcli_conn_set_sockopt(cli->conn, sockops);
3402 status = cli_openx(cli, fname, O_CREAT|O_RDWR, DENY_NONE, &fnum1);
3403 if (!NT_STATUS_IS_OK(status)) {
3405 "cli_openx failed: %s\n",
3410 status = cli_openx(cli, fname, O_CREAT|O_RDWR, DENY_NONE, &fnum2);
3411 if (!NT_STATUS_IS_OK(status)) {
3413 "cli_openx failed: %s\n",
3418 status = cli_writeall(cli, fnum1, 0, &data, 0, sizeof(data), NULL);
3419 if (!NT_STATUS_IS_OK(status)) {
3421 "cli_writeall failed: %s\n",
3426 status = cli_locktype(
3427 cli, fnum1, 0, 1, 0, LOCKING_ANDX_EXCLUSIVE_LOCK);
3428 if (!NT_STATUS_IS_OK(status)) {
3430 "cli_locktype failed: %s\n",
3435 req = lock12_send(ev, ev, cli, fnum1, fnum2);
3437 d_fprintf(stderr, "lock12_send failed\n");
3441 ok = tevent_req_poll_ntstatus(req, ev, &status);
3443 d_fprintf(stderr, "tevent_req_poll_ntstatus failed\n");
3447 if (!NT_STATUS_IS_OK(status)) {
3449 "tevent_req_poll_ntstatus returned %s\n",
3454 status = lock12_recv(req);
3455 if (!NT_STATUS_IS_OK(status)) {
3456 d_fprintf(stderr, "lock12 returned %s\n", nt_errstr(status));
3463 torture_close_connection(cli);
3468 struct lock_ntcancel_state {
3469 struct timeval start;
3470 struct smb1_lock_element lck;
3471 struct tevent_req *subreq;
3474 static void lock_ntcancel_waited(struct tevent_req *subreq);
3475 static void lock_ntcancel_done(struct tevent_req *subreq);
3477 static struct tevent_req *lock_ntcancel_send(
3478 TALLOC_CTX *mem_ctx,
3479 struct tevent_context *ev,
3480 struct cli_state *cli,
3483 struct tevent_req *req = NULL, *subreq = NULL;
3484 struct lock_ntcancel_state *state = NULL;
3486 req = tevent_req_create(mem_ctx, &state, struct lock_ntcancel_state);
3490 state->lck = (struct smb1_lock_element) {
3491 .pid = cli_getpid(cli), .offset = 0, .length = 1,
3493 state->start = timeval_current();
3495 state->subreq = cli_lockingx_send(
3496 state, /* mem_ctx */
3497 ev, /* tevent_context */
3500 LOCKING_ANDX_EXCLUSIVE_LOCK, /* typeoflock */
3501 0, /* newoplocklevel */
3502 10000, /* timeout */
3503 0, /* num_unlocks */
3506 &state->lck); /* locks */
3507 if (tevent_req_nomem(state->subreq, req)) {
3508 return tevent_req_post(req, ev);
3510 tevent_req_set_callback(state->subreq, lock_ntcancel_done, req);
3512 subreq = tevent_wakeup_send(state, ev, timeval_current_ofs(1, 0));
3513 if (tevent_req_nomem(subreq, req)) {
3514 return tevent_req_post(req, ev);
3516 tevent_req_set_callback(subreq, lock_ntcancel_waited, req);
3520 static void lock_ntcancel_waited(struct tevent_req *subreq)
3522 struct tevent_req *req = tevent_req_callback_data(
3523 subreq, struct tevent_req);
3524 struct lock_ntcancel_state *state = tevent_req_data(
3525 req, struct lock_ntcancel_state);
3528 ok = tevent_wakeup_recv(subreq);
3529 TALLOC_FREE(subreq);
3531 tevent_req_oom(req);
3535 ok = tevent_req_cancel(state->subreq);
3537 d_fprintf(stderr, "Could not cancel subreq\n");
3538 tevent_req_oom(req);
3543 static void lock_ntcancel_done(struct tevent_req *subreq)
3545 struct tevent_req *req = tevent_req_callback_data(
3546 subreq, struct tevent_req);
3547 struct lock_ntcancel_state *state = tevent_req_data(
3548 req, struct lock_ntcancel_state);
3552 status = cli_lockingx_recv(subreq);
3553 TALLOC_FREE(subreq);
3555 if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
3556 d_printf("cli_lockingx returned %s\n", nt_errstr(status));
3557 tevent_req_nterror(req, NT_STATUS_UNSUCCESSFUL);
3561 elapsed = timeval_elapsed(&state->start);
3564 d_printf("cli_lockingx was too slow, cancel did not work\n");
3565 tevent_req_nterror(req, NT_STATUS_UNSUCCESSFUL);
3569 tevent_req_done(req);
3572 static NTSTATUS lock_ntcancel_recv(struct tevent_req *req)
3574 return tevent_req_simple_recv_ntstatus(req);
3577 static bool run_locktest13(int dummy)
3579 struct tevent_context *ev = NULL;
3580 struct tevent_req *req = NULL;
3581 struct cli_state *cli = NULL;
3582 const char fname[] = "\\lockt13.lck";
3583 uint16_t fnum1, fnum2;
3589 printf("starting locktest13\n");
3591 ev = samba_tevent_context_init(NULL);
3593 d_fprintf(stderr, "samba_tevent_context_init failed\n");
3597 ok = torture_open_connection(&cli, 0);
3601 smbXcli_conn_set_sockopt(cli->conn, sockops);
3603 status = cli_openx(cli, fname, O_CREAT|O_RDWR, DENY_NONE, &fnum1);
3604 if (!NT_STATUS_IS_OK(status)) {
3606 "cli_openx failed: %s\n",
3611 status = cli_openx(cli, fname, O_CREAT|O_RDWR, DENY_NONE, &fnum2);
3612 if (!NT_STATUS_IS_OK(status)) {
3614 "cli_openx failed: %s\n",
3619 status = cli_writeall(cli, fnum1, 0, &data, 0, sizeof(data), NULL);
3620 if (!NT_STATUS_IS_OK(status)) {
3622 "cli_writeall failed: %s\n",
3627 status = cli_locktype(
3628 cli, fnum1, 0, 1, 0, LOCKING_ANDX_EXCLUSIVE_LOCK);
3629 if (!NT_STATUS_IS_OK(status)) {
3631 "cli_locktype failed: %s\n",
3636 req = lock_ntcancel_send(ev, ev, cli, fnum2);
3638 d_fprintf(stderr, "lock_ntcancel_send failed\n");
3642 ok = tevent_req_poll_ntstatus(req, ev, &status);
3644 d_fprintf(stderr, "tevent_req_poll_ntstatus failed\n");
3648 if (!NT_STATUS_IS_OK(status)) {
3650 "tevent_req_poll_ntstatus returned %s\n",
3655 status = lock_ntcancel_recv(req);
3656 if (!NT_STATUS_IS_OK(status)) {
3658 "lock_ntcancel returned %s\n",
3666 torture_close_connection(cli);
3672 test whether fnums and tids open on one VC are available on another (a major
3675 static bool run_fdpasstest(int dummy)
3677 struct cli_state *cli1, *cli2;
3678 const char *fname = "\\fdpass.tst";
3683 if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
3686 smbXcli_conn_set_sockopt(cli1->conn, sockops);
3687 smbXcli_conn_set_sockopt(cli2->conn, sockops);
3689 printf("starting fdpasstest\n");
3691 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3693 status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
3695 if (!NT_STATUS_IS_OK(status)) {
3696 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
3700 status = cli_writeall(cli1, fnum1, 0, (const uint8_t *)"hello world\n", 0,
3702 if (!NT_STATUS_IS_OK(status)) {
3703 printf("write failed (%s)\n", nt_errstr(status));
3707 cli_state_set_uid(cli2, cli_state_get_uid(cli1));
3708 cli_state_set_tid(cli2, cli_state_get_tid(cli1));
3709 cli_setpid(cli2, cli_getpid(cli1));
3711 if (test_cli_read(cli2, fnum1, buf, 0, 13, NULL, 13)) {
3712 printf("read succeeded! nasty security hole [%s]\n", buf);
3716 cli_close(cli1, fnum1);
3717 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3719 torture_close_connection(cli1);
3720 torture_close_connection(cli2);
3722 printf("finished fdpasstest\n");
3726 static bool run_fdsesstest(int dummy)
3728 struct cli_state *cli;
3730 uint16_t saved_vuid;
3732 uint32_t saved_cnum;
3733 const char *fname = "\\fdsess.tst";
3734 const char *fname1 = "\\fdsess1.tst";
3741 if (!torture_open_connection(&cli, 0))
3743 smbXcli_conn_set_sockopt(cli->conn, sockops);
3745 if (!torture_cli_session_setup2(cli, &new_vuid))
3748 saved_cnum = cli_state_get_tid(cli);
3749 if (!NT_STATUS_IS_OK(cli_tree_connect(cli, share, "?????", NULL)))
3751 new_cnum = cli_state_get_tid(cli);
3752 cli_state_set_tid(cli, saved_cnum);
3754 printf("starting fdsesstest\n");
3756 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3757 cli_unlink(cli, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3759 status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
3760 if (!NT_STATUS_IS_OK(status)) {
3761 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
3765 status = cli_writeall(cli, fnum1, 0, (const uint8_t *)"hello world\n", 0, 13,
3767 if (!NT_STATUS_IS_OK(status)) {
3768 printf("write failed (%s)\n", nt_errstr(status));
3772 saved_vuid = cli_state_get_uid(cli);
3773 cli_state_set_uid(cli, new_vuid);
3775 if (test_cli_read(cli, fnum1, buf, 0, 13, NULL, 13)) {
3776 printf("read succeeded with different vuid! "
3777 "nasty security hole [%s]\n", buf);
3780 /* Try to open a file with different vuid, samba cnum. */
3781 if (NT_STATUS_IS_OK(cli_openx(cli, fname1, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum2))) {
3782 printf("create with different vuid, same cnum succeeded.\n");
3783 cli_close(cli, fnum2);
3784 cli_unlink(cli, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3786 printf("create with different vuid, same cnum failed.\n");
3787 printf("This will cause problems with service clients.\n");
3791 cli_state_set_uid(cli, saved_vuid);
3793 /* Try with same vuid, different cnum. */
3794 cli_state_set_tid(cli, new_cnum);
3796 if (test_cli_read(cli, fnum1, buf, 0, 13, NULL, 13)) {
3797 printf("read succeeded with different cnum![%s]\n", buf);
3801 cli_state_set_tid(cli, saved_cnum);
3802 cli_close(cli, fnum1);
3803 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3805 torture_close_connection(cli);
3807 printf("finished fdsesstest\n");
3812 This test checks that
3814 1) the server does not allow an unlink on a file that is open
3816 static bool run_unlinktest(int dummy)
3818 struct cli_state *cli;
3819 const char *fname = "\\unlink.tst";
3821 bool correct = True;
3824 if (!torture_open_connection(&cli, 0)) {
3828 smbXcli_conn_set_sockopt(cli->conn, sockops);
3830 printf("starting unlink test\n");
3832 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3836 status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
3837 if (!NT_STATUS_IS_OK(status)) {
3838 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
3842 status = cli_unlink(cli, fname,
3843 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3844 if (NT_STATUS_IS_OK(status)) {
3845 printf("error: server allowed unlink on an open file\n");
3848 correct = check_error(__LINE__, status, ERRDOS, ERRbadshare,
3849 NT_STATUS_SHARING_VIOLATION);
3852 cli_close(cli, fnum);
3853 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3855 if (!torture_close_connection(cli)) {
3859 printf("unlink test finished\n");
3866 test how many open files this server supports on the one socket
3868 static bool run_maxfidtest(int dummy)
3870 struct cli_state *cli;
3872 uint16_t fnums[0x11000];
3875 bool correct = True;
3881 printf("failed to connect\n");
3885 smbXcli_conn_set_sockopt(cli->conn, sockops);
3887 for (i=0; i<0x11000; i++) {
3888 slprintf(fname,sizeof(fname)-1,"\\maxfid.%d.%d", i,(int)getpid());
3889 status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_TRUNC, DENY_NONE,
3891 if (!NT_STATUS_IS_OK(status)) {
3892 printf("open of %s failed (%s)\n",
3893 fname, nt_errstr(status));
3894 printf("maximum fnum is %d\n", i);
3902 printf("cleaning up\n");
3904 slprintf(fname,sizeof(fname)-1,"\\maxfid.%d.%d", i,(int)getpid());
3905 cli_close(cli, fnums[i]);
3907 status = cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3908 if (!NT_STATUS_IS_OK(status)) {
3909 printf("unlink of %s failed (%s)\n",
3910 fname, nt_errstr(status));
3917 printf("maxfid test finished\n");
3918 if (!torture_close_connection(cli)) {
3924 /* generate a random buffer */
3925 static void rand_buf(char *buf, int len)
3928 *buf = (char)sys_random();
3933 /* send smb negprot commands, not reading the response */
3934 static bool run_negprot_nowait(int dummy)
3936 struct tevent_context *ev;
3938 struct cli_state *cli;
3939 bool correct = True;
3941 printf("starting negprot nowait test\n");
3943 ev = samba_tevent_context_init(talloc_tos());
3948 if (!(cli = open_nbt_connection())) {
3953 for (i=0;i<50000;i++) {
3954 struct tevent_req *req;
3956 req = smbXcli_negprot_send(ev, ev, cli->conn, cli->timeout,
3957 PROTOCOL_CORE, PROTOCOL_NT1, 0);
3962 if (!tevent_req_poll(req, ev)) {
3963 d_fprintf(stderr, "tevent_req_poll failed: %s\n",
3971 if (torture_close_connection(cli)) {
3975 printf("finished negprot nowait test\n");
3980 /* send smb negprot commands, not reading the response */
3981 static bool run_bad_nbt_session(int dummy)
3983 struct nmb_name called, calling;
3984 struct sockaddr_storage ss;
3989 printf("starting bad nbt session test\n");
3991 make_nmb_name(&calling, myname, 0x0);
3992 make_nmb_name(&called , host, 0x20);
3994 if (!resolve_name(host, &ss, 0x20, true)) {
3995 d_fprintf(stderr, "Could not resolve name %s\n", host);
3999 status = open_socket_out(&ss, NBT_SMB_PORT, 10000, &fd);
4000 if (!NT_STATUS_IS_OK(status)) {
4001 d_fprintf(stderr, "open_socket_out failed: %s\n",
4006 ret = cli_bad_session_request(fd, &calling, &called);
4009 d_fprintf(stderr, "open_socket_out failed: %s\n",
4014 printf("finished bad nbt session test\n");
4018 /* send random IPC commands */
4019 static bool run_randomipc(int dummy)
4021 char *rparam = NULL;
4023 unsigned int rdrcnt,rprcnt;
4025 int api, param_len, i;
4026 struct cli_state *cli;
4027 bool correct = True;
4030 printf("starting random ipc test\n");
4032 if (!torture_open_connection(&cli, 0)) {
4036 for (i=0;i<count;i++) {
4037 api = sys_random() % 500;
4038 param_len = (sys_random() % 64);
4040 rand_buf(param, param_len);
4045 param, param_len, 8,
4046 NULL, 0, CLI_BUFFER_SIZE,
4050 printf("%d/%d\r", i,count);
4053 printf("%d/%d\n", i, count);
4055 if (!torture_close_connection(cli)) {
4062 printf("finished random ipc test\n");
4069 static void browse_callback(const char *sname, uint32_t stype,
4070 const char *comment, void *state)
4072 printf("\t%20.20s %08x %s\n", sname, stype, comment);
4078 This test checks the browse list code
4081 static bool run_browsetest(int dummy)
4083 static struct cli_state *cli;
4084 bool correct = True;
4086 printf("starting browse test\n");
4088 if (!torture_open_connection(&cli, 0)) {
4092 printf("domain list:\n");
4093 cli_NetServerEnum(cli, cli->server_domain,
4094 SV_TYPE_DOMAIN_ENUM,
4095 browse_callback, NULL);
4097 printf("machine list:\n");
4098 cli_NetServerEnum(cli, cli->server_domain,
4100 browse_callback, NULL);
4102 if (!torture_close_connection(cli)) {
4106 printf("browse test finished\n");
4112 static bool check_attributes(struct cli_state *cli,
4114 uint32_t expected_attrs)
4117 NTSTATUS status = cli_getatr(cli,
4122 if (!NT_STATUS_IS_OK(status)) {
4123 printf("cli_getatr failed with %s\n",
4127 if (attrs != expected_attrs) {
4128 printf("Attributes incorrect 0x%x, should be 0x%x\n",
4129 (unsigned int)attrs,
4130 (unsigned int)expected_attrs);
4137 This checks how the getatr calls works
4139 static bool run_attrtest(int dummy)
4141 struct cli_state *cli;
4144 const char *fname = "\\attrib123456789.tst";
4145 bool correct = True;
4148 printf("starting attrib test\n");
4150 if (!torture_open_connection(&cli, 0)) {
4154 /* Ensure we can't unlink with out-of-range (unknown) attribute. */
4155 status = cli_unlink(cli, fname, 0x20000);
4156 if (!NT_STATUS_EQUAL(status, NT_STATUS_INVALID_PARAMETER)) {
4161 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4162 cli_openx(cli, fname,
4163 O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum);
4164 cli_close(cli, fnum);
4166 status = cli_getatr(cli, fname, NULL, NULL, &t);
4167 if (!NT_STATUS_IS_OK(status)) {
4168 printf("getatr failed (%s)\n", nt_errstr(status));
4172 if (labs(t - time(NULL)) > 60*60*24*10) {
4173 printf("ERROR: SMBgetatr bug. time is %s",
4179 t2 = t-60*60*24; /* 1 day ago */
4181 /* Ensure we can't set with out-of-range (unknown) attribute. */
4182 status = cli_setatr(cli, fname, 0x20000, t2);
4183 if (!NT_STATUS_EQUAL(status, NT_STATUS_INVALID_PARAMETER)) {
4188 status = cli_setatr(cli, fname, 0, t2);
4189 if (!NT_STATUS_IS_OK(status)) {
4190 printf("setatr failed (%s)\n", nt_errstr(status));
4194 status = cli_getatr(cli, fname, NULL, NULL, &t);
4195 if (!NT_STATUS_IS_OK(status)) {
4196 printf("getatr failed (%s)\n", nt_errstr(status));
4201 printf("ERROR: getatr/setatr bug. times are\n%s",
4203 printf("%s", ctime(&t2));
4207 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4209 /* Check cli_setpathinfo_ext() */
4210 /* Re-create the file. */
4211 status = cli_openx(cli, fname,
4212 O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum);
4213 if (!NT_STATUS_IS_OK(status)) {
4214 printf("Failed to recreate %s (%s)\n",
4215 fname, nt_errstr(status));
4218 cli_close(cli, fnum);
4220 status = cli_setpathinfo_ext(
4223 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* create */
4224 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* access */
4225 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* write */
4226 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* change */
4227 FILE_ATTRIBUTE_SYSTEM |
4228 FILE_ATTRIBUTE_HIDDEN |
4229 FILE_ATTRIBUTE_READONLY);
4230 if (!NT_STATUS_IS_OK(status)) {
4231 printf("cli_setpathinfo_ext failed with %s\n",
4236 /* Check attributes are correct. */
4237 correct = check_attributes(cli,
4239 FILE_ATTRIBUTE_SYSTEM |
4240 FILE_ATTRIBUTE_HIDDEN |
4241 FILE_ATTRIBUTE_READONLY);
4242 if (correct == false) {
4246 /* Setting to FILE_ATTRIBUTE_NORMAL should be ignored. */
4247 status = cli_setpathinfo_ext(
4250 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* create */
4251 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* access */
4252 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* write */
4253 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* change */
4254 FILE_ATTRIBUTE_NORMAL);
4255 if (!NT_STATUS_IS_OK(status)) {
4256 printf("cli_setpathinfo_ext failed with %s\n",
4261 /* Check attributes are correct. */
4262 correct = check_attributes(cli,
4264 FILE_ATTRIBUTE_SYSTEM |
4265 FILE_ATTRIBUTE_HIDDEN |
4266 FILE_ATTRIBUTE_READONLY);
4267 if (correct == false) {
4271 /* Setting to (uint16_t)-1 should also be ignored. */
4272 status = cli_setpathinfo_ext(
4275 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* create */
4276 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* access */
4277 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* write */
4278 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* change */
4280 if (!NT_STATUS_IS_OK(status)) {
4281 printf("cli_setpathinfo_ext failed with %s\n",
4286 /* Check attributes are correct. */
4287 correct = check_attributes(cli,
4289 FILE_ATTRIBUTE_SYSTEM |
4290 FILE_ATTRIBUTE_HIDDEN |
4291 FILE_ATTRIBUTE_READONLY);
4292 if (correct == false) {
4296 /* Setting to 0 should clear them all. */
4297 status = cli_setpathinfo_ext(
4300 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* create */
4301 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* access */
4302 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* write */
4303 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* change */
4305 if (!NT_STATUS_IS_OK(status)) {
4306 printf("cli_setpathinfo_ext failed with %s\n",
4311 /* Check attributes are correct. */
4312 correct = check_attributes(cli,
4314 FILE_ATTRIBUTE_NORMAL);
4315 if (correct == false) {
4323 FILE_ATTRIBUTE_SYSTEM |
4324 FILE_ATTRIBUTE_HIDDEN|
4325 FILE_ATTRIBUTE_READONLY);
4327 if (!torture_close_connection(cli)) {
4331 printf("attrib test finished\n");
4336 static NTSTATUS cli_qfilename(
4337 struct cli_state *cli,
4339 TALLOC_CTX *mem_ctx,
4342 uint16_t recv_flags2;
4349 status = cli_qfileinfo(talloc_tos(), cli, fnum,
4350 SMB_QUERY_FILE_NAME_INFO,
4351 4, CLI_BUFFER_SIZE, &recv_flags2,
4352 &rdata, &num_rdata);
4353 if (!NT_STATUS_IS_OK(status)) {
4357 namelen = IVAL(rdata, 0);
4358 if (namelen > (num_rdata - 4)) {
4360 return NT_STATUS_INVALID_NETWORK_RESPONSE;
4363 pull_string_talloc(mem_ctx,
4364 (const char *)rdata,
4371 status = map_nt_error_from_unix(errno);
4378 return NT_STATUS_OK;
4382 This checks a couple of trans2 calls
4384 static bool run_trans2test(int dummy)
4386 struct cli_state *cli;
4389 time_t c_time, a_time, m_time;
4390 struct timespec c_time_ts, a_time_ts, m_time_ts, w_time_ts, m_time2_ts;
4391 const char *fname = "\\trans2.tst";
4392 const char *dname = "\\trans2";
4393 const char *fname2 = "\\trans2\\trans2.tst";
4395 bool correct = True;
4400 printf("starting trans2 test\n");
4402 if (!torture_open_connection(&cli, 0)) {
4406 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
4407 /* Ensure ino is zero, SMB2 gets a real one. */
4410 /* Ensure ino is -1, SMB1 never gets a real one. */
4414 status = cli_get_fs_attr_info(cli, &fs_attr);
4415 if (!NT_STATUS_IS_OK(status)) {
4416 printf("ERROR: cli_get_fs_attr_info returned %s\n",
4421 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4422 cli_openx(cli, fname, O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum);
4423 status = cli_qfileinfo_basic(cli, fnum, NULL, &size, &c_time_ts,
4424 &a_time_ts, &w_time_ts, &m_time_ts, NULL);
4425 if (!NT_STATUS_IS_OK(status)) {
4426 printf("ERROR: qfileinfo failed (%s)\n", nt_errstr(status));
4430 status = cli_qfilename(cli, fnum, talloc_tos(), &pname);
4431 if (!NT_STATUS_IS_OK(status)) {
4432 printf("ERROR: qfilename failed (%s)\n", nt_errstr(status));
4435 else if (strcmp(pname, fname)) {
4436 printf("qfilename gave different name? [%s] [%s]\n",
4441 cli_close(cli, fnum);
4445 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4446 status = cli_openx(cli, fname, O_RDWR | O_CREAT | O_TRUNC, DENY_NONE,
4448 if (!NT_STATUS_IS_OK(status)) {
4449 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
4452 cli_close(cli, fnum);
4454 status = cli_qpathinfo1(cli, fname, &c_time, &a_time, &m_time, &size,
4456 if (!NT_STATUS_IS_OK(status)) {
4457 printf("ERROR: qpathinfo failed (%s)\n", nt_errstr(status));
4460 time_t t = time(NULL);
4462 if (c_time != m_time) {
4463 printf("create time=%s", ctime(&c_time));
4464 printf("modify time=%s", ctime(&m_time));
4465 printf("This system appears to have sticky create times\n");
4467 if ((labs(a_time - t) > 60) && (a_time % (60*60) == 0)) {
4468 printf("access time=%s", ctime(&a_time));
4469 printf("This system appears to set a midnight access time\n");
4473 if (labs(m_time - t) > 60*60*24*7) {
4474 printf("ERROR: totally incorrect times - maybe word reversed? mtime=%s", ctime(&m_time));
4480 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4481 cli_openx(cli, fname,
4482 O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum);
4483 cli_close(cli, fnum);
4484 status = cli_qpathinfo2(cli, fname, &c_time_ts, &a_time_ts, &w_time_ts,
4485 &m_time_ts, &size, NULL, &ino);
4486 if (!NT_STATUS_IS_OK(status)) {
4487 printf("ERROR: qpathinfo2 failed (%s)\n", nt_errstr(status));
4490 if (w_time_ts.tv_sec < 60*60*24*2) {
4491 printf("write time=%s", ctime(&w_time_ts.tv_sec));
4492 printf("This system appears to set a initial 0 write time\n");
4495 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
4496 /* SMB2 should always return an inode. */
4498 printf("SMB2 bad inode (0)\n");
4502 /* SMB1 must always return zero here. */
4504 printf("SMB1 bad inode (!0)\n");
4510 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4513 /* check if the server updates the directory modification time
4514 when creating a new file */
4515 status = cli_mkdir(cli, dname);
4516 if (!NT_STATUS_IS_OK(status)) {
4517 printf("ERROR: mkdir failed (%s)\n", nt_errstr(status));
4521 status = cli_qpathinfo2(cli, "\\trans2\\", &c_time_ts, &a_time_ts,
4522 &w_time_ts, &m_time_ts, &size, NULL, NULL);
4523 if (!NT_STATUS_IS_OK(status)) {
4524 printf("ERROR: qpathinfo2 failed (%s)\n", nt_errstr(status));
4528 cli_openx(cli, fname2,
4529 O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum);
4530 cli_writeall(cli, fnum, 0, (uint8_t *)&fnum, 0, sizeof(fnum), NULL);
4531 cli_close(cli, fnum);
4532 status = cli_qpathinfo2(cli, "\\trans2\\", &c_time_ts, &a_time_ts,
4533 &w_time_ts, &m_time2_ts, &size, NULL, NULL);
4534 if (!NT_STATUS_IS_OK(status)) {
4535 printf("ERROR: qpathinfo2 failed (%s)\n", nt_errstr(status));
4538 if (memcmp(&m_time_ts, &m_time2_ts, sizeof(struct timespec))
4540 printf("This system does not update directory modification times\n");
4544 cli_unlink(cli, fname2, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4545 cli_rmdir(cli, dname);
4547 if (!torture_close_connection(cli)) {
4551 printf("trans2 test finished\n");
4557 This checks new W2K calls.
4560 static NTSTATUS new_trans(struct cli_state *pcli, int fnum, int level)
4562 uint8_t *buf = NULL;
4566 status = cli_qfileinfo(talloc_tos(), pcli, fnum, level, 0,
4567 CLI_BUFFER_SIZE, NULL, &buf, &len);
4568 if (!NT_STATUS_IS_OK(status)) {
4569 printf("ERROR: qfileinfo (%d) failed (%s)\n", level,
4572 printf("qfileinfo: level %d, len = %u\n", level, len);
4573 dump_data(0, (uint8_t *)buf, len);
4580 static bool run_w2ktest(int dummy)
4582 struct cli_state *cli;
4584 const char *fname = "\\w2ktest\\w2k.tst";
4586 bool correct = True;
4588 printf("starting w2k test\n");
4590 if (!torture_open_connection(&cli, 0)) {
4594 cli_openx(cli, fname,
4595 O_RDWR | O_CREAT , DENY_NONE, &fnum);
4597 for (level = 1004; level < 1040; level++) {
4598 new_trans(cli, fnum, level);
4601 cli_close(cli, fnum);
4603 if (!torture_close_connection(cli)) {
4607 printf("w2k test finished\n");
4614 this is a harness for some oplock tests
4616 static bool run_oplock1(int dummy)
4618 struct cli_state *cli1;
4619 const char *fname = "\\lockt1.lck";
4621 bool correct = True;
4624 printf("starting oplock test 1\n");
4626 if (!torture_open_connection(&cli1, 0)) {
4630 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4632 smbXcli_conn_set_sockopt(cli1->conn, sockops);
4634 cli1->use_oplocks = True;
4636 status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
4638 if (!NT_STATUS_IS_OK(status)) {
4639 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
4643 cli1->use_oplocks = False;
4645 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4646 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4648 status = cli_close(cli1, fnum1);
4649 if (!NT_STATUS_IS_OK(status)) {
4650 printf("close2 failed (%s)\n", nt_errstr(status));
4654 status = cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4655 if (!NT_STATUS_IS_OK(status)) {
4656 printf("unlink failed (%s)\n", nt_errstr(status));
4660 if (!torture_close_connection(cli1)) {
4664 printf("finished oplock test 1\n");
4669 static bool run_oplock2(int dummy)
4671 struct cli_state *cli1, *cli2;
4672 const char *fname = "\\lockt2.lck";
4673 uint16_t fnum1, fnum2;
4674 int saved_use_oplocks = use_oplocks;
4676 bool correct = True;
4677 volatile bool *shared_correct;
4681 shared_correct = (volatile bool *)anonymous_shared_allocate(sizeof(bool));
4682 *shared_correct = True;
4684 use_level_II_oplocks = True;
4687 printf("starting oplock test 2\n");
4689 if (!torture_open_connection(&cli1, 0)) {
4690 use_level_II_oplocks = False;
4691 use_oplocks = saved_use_oplocks;
4695 if (!torture_open_connection(&cli2, 1)) {
4696 use_level_II_oplocks = False;
4697 use_oplocks = saved_use_oplocks;
4701 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4703 smbXcli_conn_set_sockopt(cli1->conn, sockops);
4704 smbXcli_conn_set_sockopt(cli2->conn, sockops);
4706 status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
4708 if (!NT_STATUS_IS_OK(status)) {
4709 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
4713 /* Don't need the globals any more. */
4714 use_level_II_oplocks = False;
4715 use_oplocks = saved_use_oplocks;
4719 status = cli_openx(cli2, fname, O_RDWR, DENY_NONE, &fnum2);
4720 if (!NT_STATUS_IS_OK(status)) {
4721 printf("second open of %s failed (%s)\n", fname, nt_errstr(status));
4722 *shared_correct = False;
4728 status = cli_close(cli2, fnum2);
4729 if (!NT_STATUS_IS_OK(status)) {
4730 printf("close2 failed (%s)\n", nt_errstr(status));
4731 *shared_correct = False;
4739 /* Ensure cli1 processes the break. Empty file should always return 0
4741 status = cli_read(cli1, fnum1, buf, 0, 4, &nread);
4742 if (!NT_STATUS_IS_OK(status)) {
4743 printf("read on fnum1 failed (%s)\n", nt_errstr(status));
4745 } else if (nread != 0) {
4746 printf("read on empty fnum1 failed. recv %ld expected %d\n",
4747 (unsigned long)nread, 0);
4751 /* Should now be at level II. */
4752 /* Test if sending a write locks causes a break to none. */
4753 status = cli_lock32(cli1, fnum1, 0, 4, 0, READ_LOCK);
4754 if (!NT_STATUS_IS_OK(status)) {
4755 printf("lock failed (%s)\n", nt_errstr(status));
4759 cli_unlock(cli1, fnum1, 0, 4);
4763 status = cli_lock32(cli1, fnum1, 0, 4, 0, WRITE_LOCK);
4764 if (!NT_STATUS_IS_OK(status)) {
4765 printf("lock failed (%s)\n", nt_errstr(status));
4769 cli_unlock(cli1, fnum1, 0, 4);
4773 cli_read(cli1, fnum1, buf, 0, 4, NULL);
4775 status = cli_close(cli1, fnum1);
4776 if (!NT_STATUS_IS_OK(status)) {
4777 printf("close1 failed (%s)\n", nt_errstr(status));
4783 status = cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4784 if (!NT_STATUS_IS_OK(status)) {
4785 printf("unlink failed (%s)\n", nt_errstr(status));
4789 if (!torture_close_connection(cli1)) {
4793 if (!*shared_correct) {
4797 printf("finished oplock test 2\n");
4802 struct oplock4_state {
4803 struct tevent_context *ev;
4804 struct cli_state *cli;
4809 static void oplock4_got_break(struct tevent_req *req);
4810 static void oplock4_got_open(struct tevent_req *req);
4812 static bool run_oplock4(int dummy)
4814 struct tevent_context *ev;
4815 struct cli_state *cli1, *cli2;
4816 struct tevent_req *oplock_req, *open_req;
4817 const char *fname = "\\lockt4.lck";
4818 const char *fname_ln = "\\lockt4_ln.lck";
4819 uint16_t fnum1, fnum2;
4820 int saved_use_oplocks = use_oplocks;
4822 bool correct = true;
4826 struct oplock4_state *state;
4828 printf("starting oplock test 4\n");
4830 if (!torture_open_connection(&cli1, 0)) {
4831 use_level_II_oplocks = false;
4832 use_oplocks = saved_use_oplocks;
4836 if (!torture_open_connection(&cli2, 1)) {
4837 use_level_II_oplocks = false;
4838 use_oplocks = saved_use_oplocks;
4842 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4843 cli_unlink(cli1, fname_ln, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4845 smbXcli_conn_set_sockopt(cli1->conn, sockops);
4846 smbXcli_conn_set_sockopt(cli2->conn, sockops);
4848 /* Create the file. */
4849 status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
4851 if (!NT_STATUS_IS_OK(status)) {
4852 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
4856 status = cli_close(cli1, fnum1);
4857 if (!NT_STATUS_IS_OK(status)) {
4858 printf("close1 failed (%s)\n", nt_errstr(status));
4862 /* Now create a hardlink. */
4863 status = cli_hardlink(cli1, fname, fname_ln);
4864 if (!NT_STATUS_IS_OK(status)) {
4865 printf("nt hardlink failed (%s)\n", nt_errstr(status));
4869 /* Prove that opening hardlinks cause deny modes to conflict. */
4870 status = cli_openx(cli1, fname, O_RDWR, DENY_ALL, &fnum1);
4871 if (!NT_STATUS_IS_OK(status)) {
4872 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
4876 status = cli_openx(cli1, fname_ln, O_RDWR, DENY_NONE, &fnum2);
4877 if (NT_STATUS_IS_OK(status)) {
4878 printf("open of %s succeeded - should fail with sharing violation.\n",
4883 if (!NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
4884 printf("open of %s should fail with sharing violation. Got %s\n",
4885 fname_ln, nt_errstr(status));
4889 status = cli_close(cli1, fnum1);
4890 if (!NT_STATUS_IS_OK(status)) {
4891 printf("close1 failed (%s)\n", nt_errstr(status));
4895 cli1->use_oplocks = true;
4896 cli2->use_oplocks = true;
4898 status = cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
4899 if (!NT_STATUS_IS_OK(status)) {
4900 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
4904 ev = samba_tevent_context_init(talloc_tos());
4906 printf("tevent_context_init failed\n");
4910 state = talloc(ev, struct oplock4_state);
4911 if (state == NULL) {
4912 printf("talloc failed\n");
4917 state->got_break = &got_break;
4918 state->fnum2 = &fnum2;
4920 oplock_req = cli_smb_oplock_break_waiter_send(
4921 talloc_tos(), ev, cli1);
4922 if (oplock_req == NULL) {
4923 printf("cli_smb_oplock_break_waiter_send failed\n");
4926 tevent_req_set_callback(oplock_req, oplock4_got_break, state);
4928 open_req = cli_openx_send(
4929 talloc_tos(), ev, cli2, fname_ln, O_RDWR, DENY_NONE);
4930 if (open_req == NULL) {
4931 printf("cli_openx_send failed\n");
4934 tevent_req_set_callback(open_req, oplock4_got_open, state);
4939 while (!got_break || fnum2 == 0xffff) {
4941 ret = tevent_loop_once(ev);
4943 printf("tevent_loop_once failed: %s\n",
4949 status = cli_close(cli2, fnum2);
4950 if (!NT_STATUS_IS_OK(status)) {
4951 printf("close2 failed (%s)\n", nt_errstr(status));
4955 status = cli_close(cli1, fnum1);
4956 if (!NT_STATUS_IS_OK(status)) {
4957 printf("close1 failed (%s)\n", nt_errstr(status));
4961 status = cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4962 if (!NT_STATUS_IS_OK(status)) {
4963 printf("unlink failed (%s)\n", nt_errstr(status));
4967 status = cli_unlink(cli1, fname_ln, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4968 if (!NT_STATUS_IS_OK(status)) {
4969 printf("unlink failed (%s)\n", nt_errstr(status));
4973 if (!torture_close_connection(cli1)) {
4981 printf("finished oplock test 4\n");
4986 static void oplock4_got_break(struct tevent_req *req)
4988 struct oplock4_state *state = tevent_req_callback_data(
4989 req, struct oplock4_state);
4994 status = cli_smb_oplock_break_waiter_recv(req, &fnum, &level);
4996 if (!NT_STATUS_IS_OK(status)) {
4997 printf("cli_smb_oplock_break_waiter_recv returned %s\n",
5001 *state->got_break = true;
5003 req = cli_oplock_ack_send(state, state->ev, state->cli, fnum,
5006 printf("cli_oplock_ack_send failed\n");
5011 static void oplock4_got_open(struct tevent_req *req)
5013 struct oplock4_state *state = tevent_req_callback_data(
5014 req, struct oplock4_state);
5017 status = cli_openx_recv(req, state->fnum2);
5018 if (!NT_STATUS_IS_OK(status)) {
5019 printf("cli_openx_recv returned %s\n", nt_errstr(status));
5020 *state->fnum2 = 0xffff;
5024 #ifdef HAVE_KERNEL_OPLOCKS_LINUX
5026 struct oplock5_state {
5031 * Async open the file that has a kernel oplock, do an echo to get
5032 * that 100% across, close the file to signal to the child fd that the
5033 * oplock can be dropped, wait for the open reply.
5036 static void oplock5_opened(struct tevent_req *subreq);
5037 static void oplock5_pong(struct tevent_req *subreq);
5038 static void oplock5_timedout(struct tevent_req *subreq);
5040 static struct tevent_req *oplock5_send(
5041 TALLOC_CTX *mem_ctx,
5042 struct tevent_context *ev,
5043 struct cli_state *cli,
5047 struct tevent_req *req = NULL, *subreq = NULL;
5048 struct oplock5_state *state = NULL;
5049 static uint8_t data = 0;
5051 req = tevent_req_create(mem_ctx, &state, struct oplock5_state);
5055 state->pipe_down_fd = pipe_down_fd;
5057 subreq = cli_ntcreate_send(
5063 SEC_FILE_READ_DATA, /* DesiredAccess */
5064 FILE_ATTRIBUTE_NORMAL, /* FileAttributes */
5065 FILE_SHARE_WRITE|FILE_SHARE_READ, /* ShareAccess */
5066 FILE_OPEN, /* CreateDisposition */
5067 FILE_NON_DIRECTORY_FILE, /* CreateOptions */
5068 0, /* Impersonation */
5069 0); /* SecurityFlags */
5070 if (tevent_req_nomem(subreq, req)) {
5071 return tevent_req_post(req, ev);
5073 tevent_req_set_callback(subreq, oplock5_opened, req);
5075 subreq = cli_echo_send(
5080 (DATA_BLOB) { .data = &data, .length = sizeof(data) });
5081 if (tevent_req_nomem(subreq, req)) {
5082 return tevent_req_post(req, ev);
5084 tevent_req_set_callback(subreq, oplock5_pong, req);
5086 subreq = tevent_wakeup_send(state, ev, timeval_current_ofs(20, 0));
5087 if (tevent_req_nomem(subreq, req)) {
5088 return tevent_req_post(req, ev);
5090 tevent_req_set_callback(subreq, oplock5_timedout, req);
5095 static void oplock5_opened(struct tevent_req *subreq)
5097 struct tevent_req *req = tevent_req_callback_data(
5098 subreq, struct tevent_req);
5102 status = cli_ntcreate_recv(subreq, &fnum, NULL);
5103 TALLOC_FREE(subreq);
5104 if (tevent_req_nterror(req, status)) {
5107 tevent_req_done(req);
5110 static void oplock5_pong(struct tevent_req *subreq)
5112 struct tevent_req *req = tevent_req_callback_data(
5113 subreq, struct tevent_req);
5114 struct oplock5_state *state = tevent_req_data(
5115 req, struct oplock5_state);
5118 status = cli_echo_recv(subreq);
5119 TALLOC_FREE(subreq);
5120 if (tevent_req_nterror(req, status)) {
5124 close(state->pipe_down_fd);
5127 static void oplock5_timedout(struct tevent_req *subreq)
5129 struct tevent_req *req = tevent_req_callback_data(
5130 subreq, struct tevent_req);
5133 ok = tevent_wakeup_recv(subreq);
5134 TALLOC_FREE(subreq);
5136 tevent_req_oom(req);
5139 tevent_req_nterror(req, NT_STATUS_TIMEOUT);
5142 static NTSTATUS oplock5_recv(struct tevent_req *req)
5144 return tevent_req_simple_recv_ntstatus(req);
5147 static bool run_oplock5(int dummy)
5149 struct tevent_context *ev = NULL;
5150 struct tevent_req *req = NULL;
5151 struct cli_state *cli = NULL;
5152 const char *fname = "oplock5.txt";
5153 int pipe_down[2], pipe_up[2];
5160 printf("starting oplock5\n");
5162 if (local_path == NULL) {
5163 d_fprintf(stderr, "oplock5 must be given a local path via "
5164 "-l <localpath>\n");
5168 ret = pipe(pipe_down);
5170 d_fprintf(stderr, "pipe() failed: %s\n", strerror(errno));
5173 ret = pipe(pipe_up);
5175 d_fprintf(stderr, "pipe() failed: %s\n", strerror(errno));
5180 if (child_pid == -1) {
5181 d_fprintf(stderr, "fork() failed: %s\n", strerror(errno));
5185 if (child_pid == 0) {
5186 char *local_file = NULL;
5189 close(pipe_down[1]);
5192 local_file = talloc_asprintf(
5193 talloc_tos(), "%s/%s", local_path, fname);
5194 if (local_file == 0) {
5198 fd = open(local_file, O_RDWR|O_CREAT, 0644);
5201 "open(%s) in child failed: %s\n",
5208 signal(SIGIO, SIG_IGN);
5210 ret = fcntl(fd, F_SETLEASE, F_WRLCK);
5213 "SETLEASE in child failed: %s\n",
5220 ret = sys_write(pipe_up[1], &c, sizeof(c));
5223 "sys_write failed: %s\n",
5227 ret = sys_read(pipe_down[0], &c, sizeof(c));
5230 "sys_read failed: %s\n",
5238 close(pipe_down[0]);
5240 ret = sys_read(pipe_up[0], &c, sizeof(c));
5243 "sys_read failed: %s\n",
5248 d_fprintf(stderr, "got error code %"PRIu8"\n", c);
5252 ok = torture_open_connection(&cli, 0);
5254 d_fprintf(stderr, "torture_open_connection failed\n");
5258 ev = samba_tevent_context_init(talloc_tos());
5260 d_fprintf(stderr, "samba_tevent_context_init failed\n");
5264 req = oplock5_send(ev, ev, cli, fname, pipe_down[1]);
5266 d_fprintf(stderr, "oplock5_send failed\n");
5270 ok = tevent_req_poll_ntstatus(req, ev, &status);
5273 "tevent_req_poll_ntstatus failed: %s\n",
5278 status = oplock5_recv(req);
5280 if (!NT_STATUS_IS_OK(status)) {
5282 "oplock5 failed: %s\n",
5290 #endif /* HAVE_KERNEL_OPLOCKS_LINUX */
5293 Test delete on close semantics.
5295 static bool run_deletetest(int dummy)
5297 struct cli_state *cli1 = NULL;
5298 struct cli_state *cli2 = NULL;
5299 const char *fname = "\\delete.file";
5300 uint16_t fnum1 = (uint16_t)-1;
5301 uint16_t fnum2 = (uint16_t)-1;
5302 bool correct = false;
5305 printf("starting delete test\n");
5307 if (!torture_open_connection(&cli1, 0)) {
5311 smbXcli_conn_set_sockopt(cli1->conn, sockops);
5313 /* Test 1 - this should delete the file on close. */
5315 cli_setatr(cli1, fname, 0, 0);
5316 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5318 status = cli_ntcreate(cli1, fname, 0, GENERIC_ALL_ACCESS|DELETE_ACCESS,
5319 FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
5320 FILE_DELETE_ON_CLOSE, 0, &fnum1, NULL);
5321 if (!NT_STATUS_IS_OK(status)) {
5322 printf("[1] open of %s failed (%s)\n", fname, nt_errstr(status));
5326 status = cli_close(cli1, fnum1);
5327 if (!NT_STATUS_IS_OK(status)) {
5328 printf("[1] close failed (%s)\n", nt_errstr(status));
5332 status = cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
5333 if (NT_STATUS_IS_OK(status)) {
5334 printf("[1] open of %s succeeded (should fail)\n", fname);
5338 printf("first delete on close test succeeded.\n");
5340 /* Test 2 - this should delete the file on close. */
5342 cli_setatr(cli1, fname, 0, 0);
5343 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5345 status = cli_ntcreate(cli1, fname, 0, GENERIC_ALL_ACCESS,
5346 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
5347 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
5348 if (!NT_STATUS_IS_OK(status)) {
5349 printf("[2] open of %s failed (%s)\n", fname, nt_errstr(status));
5353 status = cli_nt_delete_on_close(cli1, fnum1, true);
5354 if (!NT_STATUS_IS_OK(status)) {
5355 printf("[2] setting delete_on_close failed (%s)\n", nt_errstr(status));
5359 status = cli_close(cli1, fnum1);
5360 if (!NT_STATUS_IS_OK(status)) {
5361 printf("[2] close failed (%s)\n", nt_errstr(status));
5365 status = cli_openx(cli1, fname, O_RDONLY, DENY_NONE, &fnum1);
5366 if (NT_STATUS_IS_OK(status)) {
5367 printf("[2] open of %s succeeded should have been deleted on close !\n", fname);
5368 status = cli_close(cli1, fnum1);
5369 if (!NT_STATUS_IS_OK(status)) {
5370 printf("[2] close failed (%s)\n", nt_errstr(status));
5372 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5376 printf("second delete on close test succeeded.\n");
5379 cli_setatr(cli1, fname, 0, 0);
5380 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5382 status = cli_ntcreate(cli1, fname, 0, GENERIC_ALL_ACCESS,
5383 FILE_ATTRIBUTE_NORMAL,
5384 FILE_SHARE_READ|FILE_SHARE_WRITE,
5385 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
5386 if (!NT_STATUS_IS_OK(status)) {
5387 printf("[3] open - 1 of %s failed (%s)\n", fname, nt_errstr(status));
5391 /* This should fail with a sharing violation - open for delete is only compatible
5392 with SHARE_DELETE. */
5394 status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
5395 FILE_ATTRIBUTE_NORMAL,
5396 FILE_SHARE_READ|FILE_SHARE_WRITE,
5397 FILE_OPEN, 0, 0, &fnum2, NULL);
5398 if (NT_STATUS_IS_OK(status)) {
5399 printf("[3] open - 2 of %s succeeded - should have failed.\n", fname);
5403 /* This should succeed. */
5404 status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
5405 FILE_ATTRIBUTE_NORMAL,
5406 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5407 FILE_OPEN, 0, 0, &fnum2, NULL);
5408 if (!NT_STATUS_IS_OK(status)) {
5409 printf("[3] open - 3 of %s failed (%s)\n", fname, nt_errstr(status));
5413 status = cli_nt_delete_on_close(cli1, fnum1, true);
5414 if (!NT_STATUS_IS_OK(status)) {
5415 printf("[3] setting delete_on_close failed (%s)\n", nt_errstr(status));
5419 status = cli_close(cli1, fnum1);
5420 if (!NT_STATUS_IS_OK(status)) {
5421 printf("[3] close 1 failed (%s)\n", nt_errstr(status));
5425 status = cli_close(cli1, fnum2);
5426 if (!NT_STATUS_IS_OK(status)) {
5427 printf("[3] close 2 failed (%s)\n", nt_errstr(status));
5431 /* This should fail - file should no longer be there. */
5433 status = cli_openx(cli1, fname, O_RDONLY, DENY_NONE, &fnum1);
5434 if (NT_STATUS_IS_OK(status)) {
5435 printf("[3] open of %s succeeded should have been deleted on close !\n", fname);
5436 status = cli_close(cli1, fnum1);
5437 if (!NT_STATUS_IS_OK(status)) {
5438 printf("[3] close failed (%s)\n", nt_errstr(status));
5440 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5444 printf("third delete on close test succeeded.\n");
5447 cli_setatr(cli1, fname, 0, 0);
5448 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5450 status = cli_ntcreate(cli1, fname, 0,
5451 FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
5452 FILE_ATTRIBUTE_NORMAL,
5453 FILE_SHARE_READ|FILE_SHARE_WRITE,
5454 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
5455 if (!NT_STATUS_IS_OK(status)) {
5456 printf("[4] open of %s failed (%s)\n", fname, nt_errstr(status));
5460 /* This should succeed. */
5461 status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
5462 FILE_ATTRIBUTE_NORMAL,
5463 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5464 FILE_OPEN, 0, 0, &fnum2, NULL);
5465 if (!NT_STATUS_IS_OK(status)) {
5466 printf("[4] open - 2 of %s failed (%s)\n", fname, nt_errstr(status));
5470 status = cli_close(cli1, fnum2);
5471 if (!NT_STATUS_IS_OK(status)) {
5472 printf("[4] close - 1 failed (%s)\n", nt_errstr(status));
5476 status = cli_nt_delete_on_close(cli1, fnum1, true);
5477 if (!NT_STATUS_IS_OK(status)) {
5478 printf("[4] setting delete_on_close failed (%s)\n", nt_errstr(status));
5482 /* This should fail - no more opens once delete on close set. */
5483 status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
5484 FILE_ATTRIBUTE_NORMAL,
5485 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5486 FILE_OPEN, 0, 0, &fnum2, NULL);
5487 if (NT_STATUS_IS_OK(status)) {
5488 printf("[4] open - 3 of %s succeeded ! Should have failed.\n", fname );
5492 status = cli_close(cli1, fnum1);
5493 if (!NT_STATUS_IS_OK(status)) {
5494 printf("[4] close - 2 failed (%s)\n", nt_errstr(status));
5498 printf("fourth delete on close test succeeded.\n");
5501 cli_setatr(cli1, fname, 0, 0);
5502 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5504 status = cli_openx(cli1, fname, O_RDWR|O_CREAT, DENY_NONE, &fnum1);
5505 if (!NT_STATUS_IS_OK(status)) {
5506 printf("[5] open of %s failed (%s)\n", fname, nt_errstr(status));
5510 /* This should fail - only allowed on NT opens with DELETE access. */
5512 status = cli_nt_delete_on_close(cli1, fnum1, true);
5513 if (NT_STATUS_IS_OK(status)) {
5514 printf("[5] setting delete_on_close on OpenX file succeeded - should fail !\n");
5518 status = cli_close(cli1, fnum1);
5519 if (!NT_STATUS_IS_OK(status)) {
5520 printf("[5] close failed (%s)\n", nt_errstr(status));
5524 printf("fifth delete on close test succeeded.\n");
5527 cli_setatr(cli1, fname, 0, 0);
5528 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5530 status = cli_ntcreate(cli1, fname, 0, FILE_READ_DATA|FILE_WRITE_DATA,
5531 FILE_ATTRIBUTE_NORMAL,
5532 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5533 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
5534 if (!NT_STATUS_IS_OK(status)) {
5535 printf("[6] open of %s failed (%s)\n", fname,
5540 /* This should fail - only allowed on NT opens with DELETE access. */
5542 status = cli_nt_delete_on_close(cli1, fnum1, true);
5543 if (NT_STATUS_IS_OK(status)) {
5544 printf("[6] setting delete_on_close on file with no delete access succeeded - should fail !\n");
5548 status = cli_close(cli1, fnum1);
5549 if (!NT_STATUS_IS_OK(status)) {
5550 printf("[6] close failed (%s)\n", nt_errstr(status));
5554 printf("sixth delete on close test succeeded.\n");
5557 cli_setatr(cli1, fname, 0, 0);
5558 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5560 status = cli_ntcreate(cli1, fname, 0,
5561 FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
5562 FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
5563 0, 0, &fnum1, NULL);
5564 if (!NT_STATUS_IS_OK(status)) {
5565 printf("[7] open of %s failed (%s)\n", fname, nt_errstr(status));
5569 status = cli_nt_delete_on_close(cli1, fnum1, true);
5570 if (!NT_STATUS_IS_OK(status)) {
5571 printf("[7] setting delete_on_close on file failed !\n");
5575 status = cli_nt_delete_on_close(cli1, fnum1, false);
5576 if (!NT_STATUS_IS_OK(status)) {
5577 printf("[7] unsetting delete_on_close on file failed !\n");
5581 status = cli_close(cli1, fnum1);
5582 if (!NT_STATUS_IS_OK(status)) {
5583 printf("[7] close - 1 failed (%s)\n", nt_errstr(status));
5587 /* This next open should succeed - we reset the flag. */
5588 status = cli_openx(cli1, fname, O_RDONLY, DENY_NONE, &fnum1);
5589 if (!NT_STATUS_IS_OK(status)) {
5590 printf("[7] open of %s failed (%s)\n", fname, nt_errstr(status));
5594 status = cli_close(cli1, fnum1);
5595 if (!NT_STATUS_IS_OK(status)) {
5596 printf("[7] close - 2 failed (%s)\n", nt_errstr(status));
5600 printf("seventh delete on close test succeeded.\n");
5603 cli_setatr(cli1, fname, 0, 0);
5604 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5606 if (!torture_open_connection(&cli2, 1)) {
5607 printf("[8] failed to open second connection.\n");
5611 smbXcli_conn_set_sockopt(cli1->conn, sockops);
5613 status = cli_ntcreate(cli1, fname, 0,
5614 FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
5615 FILE_ATTRIBUTE_NORMAL,
5616 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5617 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
5618 if (!NT_STATUS_IS_OK(status)) {
5619 printf("[8] open 1 of %s failed (%s)\n", fname, nt_errstr(status));
5623 status = cli_ntcreate(cli2, fname, 0,
5624 FILE_READ_DATA|FILE_WRITE_DATA|DELETE_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("[8] open 2 of %s failed (%s)\n", fname, nt_errstr(status));
5633 status = cli_nt_delete_on_close(cli1, fnum1, true);
5634 if (!NT_STATUS_IS_OK(status)) {
5635 printf("[8] setting delete_on_close on file failed !\n");
5639 status = cli_close(cli1, fnum1);
5640 if (!NT_STATUS_IS_OK(status)) {
5641 printf("[8] close - 1 failed (%s)\n", nt_errstr(status));
5645 status = cli_close(cli2, fnum2);
5646 if (!NT_STATUS_IS_OK(status)) {
5647 printf("[8] close - 2 failed (%s)\n", nt_errstr(status));
5651 /* This should fail.. */
5652 status = cli_openx(cli1, fname, O_RDONLY, DENY_NONE, &fnum1);
5653 if (NT_STATUS_IS_OK(status)) {
5654 printf("[8] open of %s succeeded should have been deleted on close !\n", fname);
5658 printf("eighth delete on close test succeeded.\n");
5662 /* This should fail - we need to set DELETE_ACCESS. */
5663 status = cli_ntcreate(cli1, fname, 0, FILE_READ_DATA|FILE_WRITE_DATA,
5664 FILE_ATTRIBUTE_NORMAL,
5667 FILE_DELETE_ON_CLOSE, 0, &fnum1, NULL);
5668 if (NT_STATUS_IS_OK(status)) {
5669 printf("[9] open of %s succeeded should have failed!\n", fname);
5673 printf("ninth delete on close test succeeded.\n");
5677 status = cli_ntcreate(cli1, fname, 0,
5678 FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
5679 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
5680 FILE_OVERWRITE_IF, FILE_DELETE_ON_CLOSE,
5682 if (!NT_STATUS_IS_OK(status)) {
5683 printf("[10] open of %s failed (%s)\n", fname, nt_errstr(status));
5687 /* This should delete the file. */
5688 status = cli_close(cli1, fnum1);
5689 if (!NT_STATUS_IS_OK(status)) {
5690 printf("[10] close failed (%s)\n", nt_errstr(status));
5694 /* This should fail.. */
5695 status = cli_openx(cli1, fname, O_RDONLY, DENY_NONE, &fnum1);
5696 if (NT_STATUS_IS_OK(status)) {
5697 printf("[10] open of %s succeeded should have been deleted on close !\n", fname);
5701 printf("tenth delete on close test succeeded.\n");
5705 cli_setatr(cli1, fname, 0, 0);
5706 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5708 /* Can we open a read-only file with delete access? */
5710 /* Create a readonly file. */
5711 status = cli_ntcreate(cli1, fname, 0, FILE_READ_DATA|FILE_WRITE_DATA,
5712 FILE_ATTRIBUTE_READONLY, FILE_SHARE_NONE,
5713 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
5714 if (!NT_STATUS_IS_OK(status)) {
5715 printf("[11] open of %s failed (%s)\n", fname, nt_errstr(status));
5719 status = cli_close(cli1, fnum1);
5720 if (!NT_STATUS_IS_OK(status)) {
5721 printf("[11] close failed (%s)\n", nt_errstr(status));
5725 /* Now try open for delete access. */
5726 status = cli_ntcreate(cli1, fname, 0,
5727 FILE_READ_ATTRIBUTES|DELETE_ACCESS,
5729 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5730 FILE_OPEN, 0, 0, &fnum1, NULL);
5731 if (!NT_STATUS_IS_OK(status)) {
5732 printf("[11] open of %s failed: %s\n", fname, nt_errstr(status));
5736 cli_close(cli1, fnum1);
5738 printf("eleventh delete on close test succeeded.\n");
5742 * like test 4 but with initial delete on close
5745 cli_setatr(cli1, fname, 0, 0);
5746 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5748 status = cli_ntcreate(cli1, fname, 0,
5749 FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
5750 FILE_ATTRIBUTE_NORMAL,
5751 FILE_SHARE_READ|FILE_SHARE_WRITE,
5753 FILE_DELETE_ON_CLOSE, 0, &fnum1, NULL);
5754 if (!NT_STATUS_IS_OK(status)) {
5755 printf("[12] open 1 of %s failed (%s)\n", fname, nt_errstr(status));
5759 status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
5760 FILE_ATTRIBUTE_NORMAL,
5761 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5762 FILE_OPEN, 0, 0, &fnum2, NULL);
5763 if (!NT_STATUS_IS_OK(status)) {
5764 printf("[12] open 2 of %s failed(%s).\n", fname, nt_errstr(status));
5768 status = cli_close(cli1, fnum2);
5769 if (!NT_STATUS_IS_OK(status)) {
5770 printf("[12] close 1 failed (%s)\n", nt_errstr(status));
5774 status = cli_nt_delete_on_close(cli1, fnum1, true);
5775 if (!NT_STATUS_IS_OK(status)) {
5776 printf("[12] setting delete_on_close failed (%s)\n", nt_errstr(status));
5780 /* This should fail - no more opens once delete on close set. */
5781 status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
5782 FILE_ATTRIBUTE_NORMAL,
5783 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5784 FILE_OPEN, 0, 0, &fnum2, NULL);
5785 if (NT_STATUS_IS_OK(status)) {
5786 printf("[12] open 3 of %s succeeded - should fail).\n", fname);
5790 status = cli_nt_delete_on_close(cli1, fnum1, false);
5791 if (!NT_STATUS_IS_OK(status)) {
5792 printf("[12] unsetting delete_on_close failed (%s)\n", nt_errstr(status));
5796 status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
5797 FILE_ATTRIBUTE_NORMAL,
5798 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5799 FILE_OPEN, 0, 0, &fnum2, NULL);
5800 if (!NT_STATUS_IS_OK(status)) {
5801 printf("[12] open 4 of %s failed (%s)\n", fname, nt_errstr(status));
5805 status = cli_close(cli1, fnum2);
5806 if (!NT_STATUS_IS_OK(status)) {
5807 printf("[12] close 2 failed (%s)\n", nt_errstr(status));
5811 status = cli_close(cli1, fnum1);
5812 if (!NT_STATUS_IS_OK(status)) {
5813 printf("[12] close 3 failed (%s)\n", nt_errstr(status));
5818 * setting delete on close on the handle does
5819 * not unset the initial delete on close...
5821 status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
5822 FILE_ATTRIBUTE_NORMAL,
5823 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5824 FILE_OPEN, 0, 0, &fnum2, NULL);
5825 if (NT_STATUS_IS_OK(status)) {
5826 printf("[12] open 5 of %s succeeded - should fail).\n", fname);
5828 } else if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
5829 printf("ntcreate returned %s, expected "
5830 "NT_STATUS_OBJECT_NAME_NOT_FOUND\n",
5835 printf("twelfth delete on close test succeeded.\n");
5838 printf("finished delete test\n");
5843 /* FIXME: This will crash if we aborted before cli2 got
5844 * intialized, because these functions don't handle
5845 * uninitialized connections. */
5847 if (fnum1 != (uint16_t)-1) cli_close(cli1, fnum1);
5848 if (fnum2 != (uint16_t)-1) cli_close(cli1, fnum2);
5849 cli_setatr(cli1, fname, 0, 0);
5850 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5852 if (cli1 && !torture_close_connection(cli1)) {
5855 if (cli2 && !torture_close_connection(cli2)) {
5861 struct delete_stream_state {
5865 static void delete_stream_unlinked(struct tevent_req *subreq);
5866 static void delete_stream_closed(struct tevent_req *subreq);
5868 static struct tevent_req *delete_stream_send(
5869 TALLOC_CTX *mem_ctx,
5870 struct tevent_context *ev,
5871 struct cli_state *cli,
5872 const char *base_fname,
5873 uint16_t stream_fnum)
5875 struct tevent_req *req = NULL, *subreq = NULL;
5876 struct delete_stream_state *state = NULL;
5878 req = tevent_req_create(
5879 mem_ctx, &state, struct delete_stream_state);
5884 subreq = cli_unlink_send(
5889 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5890 if (tevent_req_nomem(subreq, req)) {
5891 return tevent_req_post(req, ev);
5893 tevent_req_set_callback(subreq, delete_stream_unlinked, req);
5895 subreq = cli_close_send(state, ev, cli, stream_fnum);
5896 if (tevent_req_nomem(subreq, req)) {
5897 return tevent_req_post(req, ev);
5899 tevent_req_set_callback(subreq, delete_stream_closed, req);
5904 static void delete_stream_unlinked(struct tevent_req *subreq)
5906 struct tevent_req *req = tevent_req_callback_data(
5907 subreq, struct tevent_req);
5908 struct delete_stream_state *state = tevent_req_data(
5909 req, struct delete_stream_state);
5912 status = cli_unlink_recv(subreq);
5913 TALLOC_FREE(subreq);
5914 if (!NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
5915 printf("cli_unlink returned %s\n",
5917 tevent_req_nterror(req, NT_STATUS_UNSUCCESSFUL);
5920 if (!state->closed) {
5921 /* close reply should have come in first */
5922 printf("Not closed\n");
5923 tevent_req_nterror(req, NT_STATUS_UNSUCCESSFUL);
5926 tevent_req_done(req);
5929 static void delete_stream_closed(struct tevent_req *subreq)
5931 struct tevent_req *req = tevent_req_callback_data(
5932 subreq, struct tevent_req);
5933 struct delete_stream_state *state = tevent_req_data(
5934 req, struct delete_stream_state);
5937 status = cli_close_recv(subreq);
5938 TALLOC_FREE(subreq);
5939 if (tevent_req_nterror(req, status)) {
5942 /* also waiting for the unlink to come back */
5943 state->closed = true;
5946 static NTSTATUS delete_stream_recv(struct tevent_req *req)
5948 return tevent_req_simple_recv_ntstatus(req);
5951 static bool run_delete_stream(int dummy)
5953 struct tevent_context *ev = NULL;
5954 struct tevent_req *req = NULL;
5955 struct cli_state *cli = NULL;
5956 const char fname[] = "delete_stream";
5957 const char fname_stream[] = "delete_stream:Zone.Identifier:$DATA";
5958 uint16_t fnum1, fnum2;
5962 printf("Starting stream delete test\n");
5964 ok = torture_open_connection(&cli, 0);
5969 cli_setatr(cli, fname, 0, 0);
5970 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5972 /* Create the file. */
5973 status = cli_ntcreate(
5977 READ_CONTROL_ACCESS,
5979 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5985 if (!NT_STATUS_IS_OK(status)) {
5987 "cli_ntcreate of %s failed (%s)\n",
5992 status = cli_close(cli, fnum1);
5993 if (!NT_STATUS_IS_OK(status)) {
5995 "cli_close of %s failed (%s)\n",
6001 /* Now create the stream. */
6002 status = cli_ntcreate(
6008 FILE_SHARE_READ|FILE_SHARE_WRITE,
6015 if (!NT_STATUS_IS_OK(status)) {
6017 "cli_ntcreate of %s failed (%s)\n",
6023 /* open it a second time */
6025 status = cli_ntcreate(
6031 FILE_SHARE_READ|FILE_SHARE_WRITE,
6038 if (!NT_STATUS_IS_OK(status)) {
6040 "2nd cli_ntcreate of %s failed (%s)\n",
6046 ev = samba_tevent_context_init(talloc_tos());
6048 d_fprintf(stderr, "samba_tevent_context_init failed\n");
6052 req = delete_stream_send(ev, ev, cli, fname, fnum1);
6054 d_fprintf(stderr, "delete_stream_send failed\n");
6058 ok = tevent_req_poll_ntstatus(req, ev, &status);
6061 "tevent_req_poll_ntstatus failed: %s\n",
6066 status = delete_stream_recv(req);
6068 if (!NT_STATUS_IS_OK(status)) {
6070 "delete_stream failed: %s\n",
6075 status = cli_close(cli, fnum2);
6076 if (!NT_STATUS_IS_OK(status)) {
6078 "close failed: %s\n",
6083 status = cli_unlink(
6084 cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6085 if (!NT_STATUS_IS_OK(status)) {
6087 "unlink failed: %s\n",
6096 Exercise delete on close semantics - use on the PRINT1 share in torture
6099 static bool run_delete_print_test(int dummy)
6101 struct cli_state *cli1 = NULL;
6102 const char *fname = "print_delete.file";
6103 uint16_t fnum1 = (uint16_t)-1;
6104 bool correct = false;
6105 const char *buf = "print file data\n";
6108 printf("starting print delete test\n");
6110 if (!torture_open_connection(&cli1, 0)) {
6114 smbXcli_conn_set_sockopt(cli1->conn, sockops);
6116 status = cli_ntcreate(cli1, fname, 0, GENERIC_ALL_ACCESS|DELETE_ACCESS,
6117 FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
6118 0, 0, &fnum1, NULL);
6119 if (!NT_STATUS_IS_OK(status)) {
6120 printf("open of %s failed (%s)\n",
6126 status = cli_writeall(cli1,
6129 (const uint8_t *)buf,
6131 strlen(buf), /* size */
6133 if (!NT_STATUS_IS_OK(status)) {
6134 printf("writing print file data failed (%s)\n",
6139 status = cli_nt_delete_on_close(cli1, fnum1, true);
6140 if (!NT_STATUS_IS_OK(status)) {
6141 printf("setting delete_on_close failed (%s)\n",
6146 status = cli_close(cli1, fnum1);
6147 if (!NT_STATUS_IS_OK(status)) {
6148 printf("close failed (%s)\n", nt_errstr(status));
6152 printf("finished print delete test\n");
6158 if (fnum1 != (uint16_t)-1) {
6159 cli_close(cli1, fnum1);
6162 if (cli1 && !torture_close_connection(cli1)) {
6168 static bool run_deletetest_ln(int dummy)
6170 struct cli_state *cli;
6171 const char *fname = "\\delete1";
6172 const char *fname_ln = "\\delete1_ln";
6176 bool correct = true;
6179 printf("starting deletetest-ln\n");
6181 if (!torture_open_connection(&cli, 0)) {
6185 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6186 cli_unlink(cli, fname_ln, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6188 smbXcli_conn_set_sockopt(cli->conn, sockops);
6190 /* Create the file. */
6191 status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
6192 if (!NT_STATUS_IS_OK(status)) {
6193 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
6197 status = cli_close(cli, fnum);
6198 if (!NT_STATUS_IS_OK(status)) {
6199 printf("close1 failed (%s)\n", nt_errstr(status));
6203 /* Now create a hardlink. */
6204 status = cli_hardlink(cli, fname, fname_ln);
6205 if (!NT_STATUS_IS_OK(status)) {
6206 printf("nt hardlink failed (%s)\n", nt_errstr(status));
6210 /* Open the original file. */
6211 status = cli_ntcreate(cli, fname, 0, FILE_READ_DATA,
6212 FILE_ATTRIBUTE_NORMAL,
6213 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6214 FILE_OPEN_IF, 0, 0, &fnum, NULL);
6215 if (!NT_STATUS_IS_OK(status)) {
6216 printf("ntcreate of %s failed (%s)\n", fname, nt_errstr(status));
6220 /* Unlink the hard link path. */
6221 status = cli_ntcreate(cli, fname_ln, 0, DELETE_ACCESS,
6222 FILE_ATTRIBUTE_NORMAL,
6223 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6224 FILE_OPEN_IF, 0, 0, &fnum1, NULL);
6225 if (!NT_STATUS_IS_OK(status)) {
6226 printf("ntcreate of %s failed (%s)\n", fname_ln, nt_errstr(status));
6229 status = cli_nt_delete_on_close(cli, fnum1, true);
6230 if (!NT_STATUS_IS_OK(status)) {
6231 d_printf("(%s) failed to set delete_on_close %s: %s\n",
6232 __location__, fname_ln, nt_errstr(status));
6236 status = cli_close(cli, fnum1);
6237 if (!NT_STATUS_IS_OK(status)) {
6238 printf("close %s failed (%s)\n",
6239 fname_ln, nt_errstr(status));
6243 status = cli_close(cli, fnum);
6244 if (!NT_STATUS_IS_OK(status)) {
6245 printf("close %s failed (%s)\n",
6246 fname, nt_errstr(status));
6250 /* Ensure the original file is still there. */
6251 status = cli_getatr(cli, fname, NULL, NULL, &t);
6252 if (!NT_STATUS_IS_OK(status)) {
6253 printf("%s getatr on file %s failed (%s)\n",
6260 /* Ensure the link path is gone. */
6261 status = cli_getatr(cli, fname_ln, NULL, NULL, &t);
6262 if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
6263 printf("%s, getatr for file %s returned wrong error code %s "
6264 "- should have been deleted\n",
6266 fname_ln, nt_errstr(status));
6270 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6271 cli_unlink(cli, fname_ln, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6273 if (!torture_close_connection(cli)) {
6277 printf("finished deletetest-ln\n");
6283 print out server properties
6285 static bool run_properties(int dummy)
6287 struct cli_state *cli;
6288 bool correct = True;
6290 printf("starting properties test\n");
6294 if (!torture_open_connection(&cli, 0)) {
6298 smbXcli_conn_set_sockopt(cli->conn, sockops);
6300 d_printf("Capabilities 0x%08x\n", smb1cli_conn_capabilities(cli->conn));
6302 if (!torture_close_connection(cli)) {
6311 /* FIRST_DESIRED_ACCESS 0xf019f */
6312 #define FIRST_DESIRED_ACCESS FILE_READ_DATA|FILE_WRITE_DATA|FILE_APPEND_DATA|\
6313 FILE_READ_EA| /* 0xf */ \
6314 FILE_WRITE_EA|FILE_READ_ATTRIBUTES| /* 0x90 */ \
6315 FILE_WRITE_ATTRIBUTES| /* 0x100 */ \
6316 DELETE_ACCESS|READ_CONTROL_ACCESS|\
6317 WRITE_DAC_ACCESS|WRITE_OWNER_ACCESS /* 0xf0000 */
6318 /* SECOND_DESIRED_ACCESS 0xe0080 */
6319 #define SECOND_DESIRED_ACCESS FILE_READ_ATTRIBUTES| /* 0x80 */ \
6320 READ_CONTROL_ACCESS|WRITE_DAC_ACCESS|\
6321 WRITE_OWNER_ACCESS /* 0xe0000 */
6324 #define THIRD_DESIRED_ACCESS FILE_READ_ATTRIBUTES| /* 0x80 */ \
6325 READ_CONTROL_ACCESS|WRITE_DAC_ACCESS|\
6327 WRITE_OWNER_ACCESS /* */
6331 Test ntcreate calls made by xcopy
6333 static bool run_xcopy(int dummy)
6335 static struct cli_state *cli1;
6336 const char *fname = "\\test.txt";
6337 bool correct = True;
6338 uint16_t fnum1, fnum2;
6341 printf("starting xcopy test\n");
6343 if (!torture_open_connection(&cli1, 0)) {
6347 status = cli_ntcreate(cli1, fname, 0, FIRST_DESIRED_ACCESS,
6348 FILE_ATTRIBUTE_ARCHIVE, FILE_SHARE_NONE,
6349 FILE_OVERWRITE_IF, 0x4044, 0, &fnum1, NULL);
6350 if (!NT_STATUS_IS_OK(status)) {
6351 printf("First open failed - %s\n", nt_errstr(status));
6355 status = cli_ntcreate(cli1, fname, 0, SECOND_DESIRED_ACCESS, 0,
6356 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6357 FILE_OPEN, 0x200000, 0, &fnum2, NULL);
6358 if (!NT_STATUS_IS_OK(status)) {
6359 printf("second open failed - %s\n", nt_errstr(status));
6363 if (!torture_close_connection(cli1)) {
6371 Test rename on files open with share delete and no share delete.
6373 static bool run_rename(int dummy)
6375 static struct cli_state *cli1;
6376 const char *fname = "\\test.txt";
6377 const char *fname1 = "\\test1.txt";
6378 bool correct = True;
6383 printf("starting rename test\n");
6385 if (!torture_open_connection(&cli1, 0)) {
6389 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6390 cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6392 status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
6393 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ,
6394 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
6395 if (!NT_STATUS_IS_OK(status)) {
6396 printf("First open failed - %s\n", nt_errstr(status));
6400 status = cli_rename(cli1, fname, fname1, false);
6401 if (!NT_STATUS_IS_OK(status)) {
6402 printf("First rename failed (SHARE_READ) (this is correct) - %s\n", nt_errstr(status));
6404 printf("First rename succeeded (SHARE_READ) - this should have failed !\n");
6408 status = cli_close(cli1, fnum1);
6409 if (!NT_STATUS_IS_OK(status)) {
6410 printf("close - 1 failed (%s)\n", nt_errstr(status));
6414 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6415 cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6416 status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS, FILE_ATTRIBUTE_NORMAL,
6418 FILE_SHARE_DELETE|FILE_SHARE_NONE,
6420 FILE_SHARE_DELETE|FILE_SHARE_READ,
6422 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
6423 if (!NT_STATUS_IS_OK(status)) {
6424 printf("Second open failed - %s\n", nt_errstr(status));
6428 status = cli_rename(cli1, fname, fname1, false);
6429 if (!NT_STATUS_IS_OK(status)) {
6430 printf("Second rename failed (SHARE_DELETE | SHARE_READ) - this should have succeeded - %s\n", nt_errstr(status));
6433 printf("Second rename succeeded (SHARE_DELETE | SHARE_READ)\n");
6436 status = cli_close(cli1, fnum1);
6437 if (!NT_STATUS_IS_OK(status)) {
6438 printf("close - 2 failed (%s)\n", nt_errstr(status));
6442 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6443 cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6445 status = cli_ntcreate(cli1, fname, 0, READ_CONTROL_ACCESS,
6446 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
6447 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
6448 if (!NT_STATUS_IS_OK(status)) {
6449 printf("Third open failed - %s\n", nt_errstr(status));
6454 status = cli_rename(cli1, fname, fname1, false);
6455 if (!NT_STATUS_IS_OK(status)) {
6456 printf("Third rename failed (SHARE_NONE) - this should have succeeded - %s\n", nt_errstr(status));
6459 printf("Third rename succeeded (SHARE_NONE)\n");
6462 status = cli_close(cli1, fnum1);
6463 if (!NT_STATUS_IS_OK(status)) {
6464 printf("close - 3 failed (%s)\n", nt_errstr(status));
6468 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6469 cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6473 status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
6474 FILE_ATTRIBUTE_NORMAL,
6475 FILE_SHARE_READ | FILE_SHARE_WRITE,
6476 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
6477 if (!NT_STATUS_IS_OK(status)) {
6478 printf("Fourth open failed - %s\n", nt_errstr(status));
6482 status = cli_rename(cli1, fname, fname1, false);
6483 if (!NT_STATUS_IS_OK(status)) {
6484 printf("Fourth rename failed (SHARE_READ | SHARE_WRITE) (this is correct) - %s\n", nt_errstr(status));
6486 printf("Fourth rename succeeded (SHARE_READ | SHARE_WRITE) - this should have failed !\n");
6490 status = cli_close(cli1, fnum1);
6491 if (!NT_STATUS_IS_OK(status)) {
6492 printf("close - 4 failed (%s)\n", nt_errstr(status));
6496 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6497 cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6501 status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
6502 FILE_ATTRIBUTE_NORMAL,
6503 FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
6504 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
6505 if (!NT_STATUS_IS_OK(status)) {
6506 printf("Fifth open failed - %s\n", nt_errstr(status));
6510 status = cli_rename(cli1, fname, fname1, false);
6511 if (!NT_STATUS_IS_OK(status)) {
6512 printf("Fifth rename failed (SHARE_READ | SHARE_WRITE | SHARE_DELETE) - this should have succeeded - %s ! \n", nt_errstr(status));
6515 printf("Fifth rename succeeded (SHARE_READ | SHARE_WRITE | SHARE_DELETE) (this is correct) - %s\n", nt_errstr(status));
6519 status = cli_close(cli1, fnum1);
6520 if (!NT_STATUS_IS_OK(status)) {
6521 printf("close - 5 failed (%s)\n", nt_errstr(status));
6525 /* Check that the renamed file has FILE_ATTRIBUTE_ARCHIVE. */
6526 status = cli_getatr(cli1, fname1, &attr, NULL, NULL);
6527 if (!NT_STATUS_IS_OK(status)) {
6528 printf("getatr on file %s failed - %s ! \n",
6529 fname1, nt_errstr(status));
6532 if (attr != FILE_ATTRIBUTE_ARCHIVE) {
6533 printf("Renamed file %s has wrong attr 0x%x "
6534 "(should be 0x%x)\n",
6537 (unsigned int)FILE_ATTRIBUTE_ARCHIVE);
6540 printf("Renamed file %s has archive bit set\n", fname1);
6544 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6545 cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6547 if (!torture_close_connection(cli1)) {
6555 Test rename into a directory with an ACL denying it.
6557 static bool run_rename_access(int dummy)
6559 static struct cli_state *cli = NULL;
6560 static struct cli_state *posix_cli = NULL;
6561 const char *src = "test.txt";
6562 const char *dname = "dir";
6563 const char *dst = "dir\\test.txt";
6564 const char *dsrc = "test.dir";
6565 const char *ddst = "dir\\test.dir";
6566 uint16_t fnum = (uint16_t)-1;
6567 struct security_descriptor *sd = NULL;
6568 struct security_descriptor *newsd = NULL;
6570 TALLOC_CTX *frame = NULL;
6572 frame = talloc_stackframe();
6573 printf("starting rename access test\n");
6575 /* Windows connection. */
6576 if (!torture_open_connection(&cli, 0)) {
6580 smbXcli_conn_set_sockopt(cli->conn, sockops);
6582 /* Posix connection. */
6583 if (!torture_open_connection(&posix_cli, 0)) {
6587 smbXcli_conn_set_sockopt(posix_cli->conn, sockops);
6589 status = torture_setup_unix_extensions(posix_cli);
6590 if (!NT_STATUS_IS_OK(status)) {
6594 /* Start with a clean slate. */
6595 cli_unlink(cli, src, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6596 cli_unlink(cli, dst, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6597 cli_rmdir(cli, dsrc);
6598 cli_rmdir(cli, ddst);
6599 cli_rmdir(cli, dname);
6602 * Setup the destination directory with a DENY ACE to
6603 * prevent new files within it.
6605 status = cli_ntcreate(cli,
6608 FILE_READ_ATTRIBUTES|READ_CONTROL_ACCESS|
6609 WRITE_DAC_ACCESS|FILE_READ_DATA|
6611 FILE_ATTRIBUTE_DIRECTORY,
6612 FILE_SHARE_READ|FILE_SHARE_WRITE,
6614 FILE_DIRECTORY_FILE,
6618 if (!NT_STATUS_IS_OK(status)) {
6619 printf("Create of %s - %s\n", dname, nt_errstr(status));
6623 status = cli_query_secdesc(cli,
6627 if (!NT_STATUS_IS_OK(status)) {
6628 printf("cli_query_secdesc failed for %s (%s)\n",
6629 dname, nt_errstr(status));
6633 newsd = security_descriptor_dacl_create(frame,
6638 SEC_ACE_TYPE_ACCESS_DENIED,
6639 SEC_DIR_ADD_FILE|SEC_DIR_ADD_SUBDIR,
6642 if (newsd == NULL) {
6645 sd->dacl = security_acl_concatenate(frame,
6648 if (sd->dacl == NULL) {
6651 status = cli_set_secdesc(cli, fnum, sd);
6652 if (!NT_STATUS_IS_OK(status)) {
6653 printf("cli_set_secdesc failed for %s (%s)\n",
6654 dname, nt_errstr(status));
6657 status = cli_close(cli, fnum);
6658 if (!NT_STATUS_IS_OK(status)) {
6659 printf("close failed for %s (%s)\n",
6660 dname, nt_errstr(status));
6663 /* Now go around the back and chmod to 777 via POSIX. */
6664 status = cli_posix_chmod(posix_cli, dname, 0777);
6665 if (!NT_STATUS_IS_OK(status)) {
6666 printf("cli_posix_chmod failed for %s (%s)\n",
6667 dname, nt_errstr(status));
6671 /* Check we can't create a file within dname via Windows. */
6672 status = cli_openx(cli, dst, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
6673 if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
6674 cli_close(posix_cli, fnum);
6675 printf("Create of %s should be ACCESS denied, was %s\n",
6676 dst, nt_errstr(status));
6680 /* Make the sample file/directory. */
6681 status = cli_openx(cli, src, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
6682 if (!NT_STATUS_IS_OK(status)) {
6683 printf("open of %s failed (%s)\n", src, nt_errstr(status));
6686 status = cli_close(cli, fnum);
6687 if (!NT_STATUS_IS_OK(status)) {
6688 printf("cli_close failed (%s)\n", nt_errstr(status));
6692 status = cli_mkdir(cli, dsrc);
6693 if (!NT_STATUS_IS_OK(status)) {
6694 printf("cli_mkdir of %s failed (%s)\n",
6695 dsrc, nt_errstr(status));
6700 * OK - renames of the new file and directory into the
6701 * dst directory should fail.
6704 status = cli_rename(cli, src, dst, false);
6705 if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
6706 printf("rename of %s -> %s should be ACCESS denied, was %s\n",
6707 src, dst, nt_errstr(status));
6710 status = cli_rename(cli, dsrc, ddst, false);
6711 if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
6712 printf("rename of %s -> %s should be ACCESS denied, was %s\n",
6713 src, dst, nt_errstr(status));
6723 torture_close_connection(posix_cli);
6727 if (fnum != (uint16_t)-1) {
6728 cli_close(cli, fnum);
6730 cli_unlink(cli, src,
6731 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6732 cli_unlink(cli, dst,
6733 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6734 cli_rmdir(cli, dsrc);
6735 cli_rmdir(cli, ddst);
6736 cli_rmdir(cli, dname);
6738 torture_close_connection(cli);
6746 Test owner rights ACE.
6748 static bool run_owner_rights(int dummy)
6750 static struct cli_state *cli = NULL;
6751 const char *fname = "owner_rights.txt";
6752 uint16_t fnum = (uint16_t)-1;
6753 struct security_descriptor *sd = NULL;
6754 struct security_descriptor *newsd = NULL;
6756 TALLOC_CTX *frame = NULL;
6758 frame = talloc_stackframe();
6759 printf("starting owner rights test\n");
6761 /* Windows connection. */
6762 if (!torture_open_connection(&cli, 0)) {
6766 smbXcli_conn_set_sockopt(cli->conn, sockops);
6768 /* Start with a clean slate. */
6769 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6771 /* Create the test file. */
6772 /* Now try and open for read and write-dac. */
6773 status = cli_ntcreate(cli,
6777 FILE_ATTRIBUTE_NORMAL,
6778 FILE_SHARE_READ|FILE_SHARE_WRITE|
6785 if (!NT_STATUS_IS_OK(status)) {
6786 printf("Create of %s - %s\n", fname, nt_errstr(status));
6790 /* Get the original SD. */
6791 status = cli_query_secdesc(cli,
6795 if (!NT_STATUS_IS_OK(status)) {
6796 printf("cli_query_secdesc failed for %s (%s)\n",
6797 fname, nt_errstr(status));
6802 * Add an "owner-rights" ACE denying WRITE_DATA,
6803 * and an "owner-rights" ACE allowing READ_DATA.
6806 newsd = security_descriptor_dacl_create(frame,
6811 SEC_ACE_TYPE_ACCESS_DENIED,
6815 SEC_ACE_TYPE_ACCESS_ALLOWED,
6819 if (newsd == NULL) {
6822 sd->dacl = security_acl_concatenate(frame,
6825 if (sd->dacl == NULL) {
6828 status = cli_set_secdesc(cli, fnum, sd);
6829 if (!NT_STATUS_IS_OK(status)) {
6830 printf("cli_set_secdesc failed for %s (%s)\n",
6831 fname, nt_errstr(status));
6834 status = cli_close(cli, fnum);
6835 if (!NT_STATUS_IS_OK(status)) {
6836 printf("close failed for %s (%s)\n",
6837 fname, nt_errstr(status));
6840 fnum = (uint16_t)-1;
6842 /* Try and open for FILE_WRITE_DATA */
6843 status = cli_ntcreate(cli,
6847 FILE_ATTRIBUTE_NORMAL,
6848 FILE_SHARE_READ|FILE_SHARE_WRITE|
6855 if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
6856 printf("Open of %s - %s\n", fname, nt_errstr(status));
6860 /* Now try and open for FILE_READ_DATA */
6861 status = cli_ntcreate(cli,
6865 FILE_ATTRIBUTE_NORMAL,
6866 FILE_SHARE_READ|FILE_SHARE_WRITE|
6873 if (!NT_STATUS_IS_OK(status)) {
6874 printf("Open of %s - %s\n", fname, nt_errstr(status));
6878 status = cli_close(cli, fnum);
6879 if (!NT_STATUS_IS_OK(status)) {
6880 printf("close failed for %s (%s)\n",
6881 fname, nt_errstr(status));
6885 /* Restore clean slate. */
6887 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6889 /* Create the test file. */
6890 status = cli_ntcreate(cli,
6894 FILE_ATTRIBUTE_NORMAL,
6895 FILE_SHARE_READ|FILE_SHARE_WRITE|
6902 if (!NT_STATUS_IS_OK(status)) {
6903 printf("Create of %s - %s\n", fname, nt_errstr(status));
6907 /* Get the original SD. */
6908 status = cli_query_secdesc(cli,
6912 if (!NT_STATUS_IS_OK(status)) {
6913 printf("cli_query_secdesc failed for %s (%s)\n",
6914 fname, nt_errstr(status));
6919 * Add an "owner-rights ACE denying WRITE_DATA,
6920 * and an "owner-rights ACE allowing READ_DATA|WRITE_DATA.
6923 newsd = security_descriptor_dacl_create(frame,
6928 SEC_ACE_TYPE_ACCESS_DENIED,
6932 SEC_ACE_TYPE_ACCESS_ALLOWED,
6933 FILE_READ_DATA|FILE_WRITE_DATA,
6936 if (newsd == NULL) {
6939 sd->dacl = security_acl_concatenate(frame,
6942 if (sd->dacl == NULL) {
6945 status = cli_set_secdesc(cli, fnum, sd);
6946 if (!NT_STATUS_IS_OK(status)) {
6947 printf("cli_set_secdesc failed for %s (%s)\n",
6948 fname, nt_errstr(status));
6951 status = cli_close(cli, fnum);
6952 if (!NT_STATUS_IS_OK(status)) {
6953 printf("close failed for %s (%s)\n",
6954 fname, nt_errstr(status));
6957 fnum = (uint16_t)-1;
6959 /* Try and open for FILE_WRITE_DATA */
6960 status = cli_ntcreate(cli,
6964 FILE_ATTRIBUTE_NORMAL,
6965 FILE_SHARE_READ|FILE_SHARE_WRITE|
6972 if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
6973 printf("Open of %s - %s\n", fname, nt_errstr(status));
6977 /* Now try and open for FILE_READ_DATA */
6978 status = cli_ntcreate(cli,
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 /* Restore clean slate. */
7004 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7007 /* Create the test file. */
7008 status = cli_ntcreate(cli,
7012 FILE_ATTRIBUTE_NORMAL,
7013 FILE_SHARE_READ|FILE_SHARE_WRITE|
7020 if (!NT_STATUS_IS_OK(status)) {
7021 printf("Create of %s - %s\n", fname, nt_errstr(status));
7025 /* Get the original SD. */
7026 status = cli_query_secdesc(cli,
7030 if (!NT_STATUS_IS_OK(status)) {
7031 printf("cli_query_secdesc failed for %s (%s)\n",
7032 fname, nt_errstr(status));
7037 * Add an "authenticated users" ACE allowing READ_DATA,
7038 * add an "owner-rights" denying READ_DATA,
7039 * and an "authenticated users" ACE allowing WRITE_DATA.
7042 newsd = security_descriptor_dacl_create(frame,
7046 SID_NT_AUTHENTICATED_USERS,
7047 SEC_ACE_TYPE_ACCESS_ALLOWED,
7051 SEC_ACE_TYPE_ACCESS_DENIED,
7054 SID_NT_AUTHENTICATED_USERS,
7055 SEC_ACE_TYPE_ACCESS_ALLOWED,
7059 if (newsd == NULL) {
7060 printf("newsd == NULL\n");
7063 sd->dacl = security_acl_concatenate(frame,
7066 if (sd->dacl == NULL) {
7067 printf("sd->dacl == NULL\n");
7070 status = cli_set_secdesc(cli, fnum, sd);
7071 if (!NT_STATUS_IS_OK(status)) {
7072 printf("cli_set_secdesc failed for %s (%s)\n",
7073 fname, nt_errstr(status));
7076 status = cli_close(cli, fnum);
7077 if (!NT_STATUS_IS_OK(status)) {
7078 printf("close failed for %s (%s)\n",
7079 fname, nt_errstr(status));
7082 fnum = (uint16_t)-1;
7084 /* Now try and open for FILE_READ_DATA|FILE_WRITE_DATA */
7085 status = cli_ntcreate(cli,
7088 FILE_READ_DATA|FILE_WRITE_DATA,
7089 FILE_ATTRIBUTE_NORMAL,
7090 FILE_SHARE_READ|FILE_SHARE_WRITE|
7097 if (!NT_STATUS_IS_OK(status)) {
7098 printf("Open of %s - %s\n", fname, nt_errstr(status));
7102 status = cli_close(cli, fnum);
7103 if (!NT_STATUS_IS_OK(status)) {
7104 printf("close failed for %s (%s)\n",
7105 fname, nt_errstr(status));
7109 cli_unlink(cli, fname,
7110 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7118 if (fnum != (uint16_t)-1) {
7119 cli_close(cli, fnum);
7121 cli_unlink(cli, fname,
7122 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7123 torture_close_connection(cli);
7131 * Test SMB1-specific open with SEC_FLAG_SYSTEM_SECURITY.
7132 * Note this test only works with a user with SeSecurityPrivilege set.
7134 * NB. This is also tested in samba3.base.createx_access
7135 * but this makes it very explicit what we're looking for.
7137 static bool run_smb1_system_security(int dummy)
7139 static struct cli_state *cli = NULL;
7140 const char *fname = "system_security.txt";
7141 uint16_t fnum = (uint16_t)-1;
7143 TALLOC_CTX *frame = NULL;
7145 frame = talloc_stackframe();
7146 printf("starting smb1 system security test\n");
7148 /* SMB1 connection - torture_open_connection() forces this. */
7149 if (!torture_open_connection(&cli, 0)) {
7153 smbXcli_conn_set_sockopt(cli->conn, sockops);
7155 /* Start with a clean slate. */
7156 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7158 /* Create the test file. */
7159 status = cli_ntcreate(cli,
7163 FILE_ATTRIBUTE_NORMAL,
7164 FILE_SHARE_READ|FILE_SHARE_WRITE|
7171 if (!NT_STATUS_IS_OK(status)) {
7172 printf("Create of %s - %s\n", fname, nt_errstr(status));
7176 status = cli_close(cli, fnum);
7178 /* Open with SEC_FLAG_SYSTEM_SECURITY only. */
7180 * On SMB1 this succeeds - SMB2 it fails,
7181 * see the SMB2-SACL test.
7183 status = cli_ntcreate(cli,
7186 SEC_FLAG_SYSTEM_SECURITY,
7187 FILE_ATTRIBUTE_NORMAL,
7188 FILE_SHARE_READ|FILE_SHARE_WRITE|
7195 if (!NT_STATUS_IS_OK(status)) {
7196 printf("Open of %s - %s\n", fname, nt_errstr(status));
7200 status = cli_close(cli, fnum);
7202 cli_unlink(cli, fname,
7203 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7205 torture_close_connection(cli);
7212 if (fnum != (uint16_t)-1) {
7213 cli_close(cli, fnum);
7215 cli_unlink(cli, fname,
7216 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7217 torture_close_connection(cli);
7224 static bool run_pipe_number(int dummy)
7226 struct cli_state *cli1;
7227 const char *pipe_name = "\\SPOOLSS";
7232 printf("starting pipenumber test\n");
7233 if (!torture_open_connection(&cli1, 0)) {
7237 smbXcli_conn_set_sockopt(cli1->conn, sockops);
7239 status = cli_ntcreate(cli1, pipe_name, 0, FILE_READ_DATA,
7240 FILE_ATTRIBUTE_NORMAL,
7241 FILE_SHARE_READ|FILE_SHARE_WRITE,
7242 FILE_OPEN_IF, 0, 0, &fnum, NULL);
7243 if (!NT_STATUS_IS_OK(status)) {
7244 printf("Open of pipe %s failed with error (%s)\n", pipe_name, nt_errstr(status));
7248 printf("\r%6d", num_pipes);
7251 printf("pipe_number test - we can open %d %s pipes.\n", num_pipes, pipe_name );
7252 torture_close_connection(cli1);
7257 Test open mode returns on read-only files.
7259 static bool run_opentest(int dummy)
7261 static struct cli_state *cli1;
7262 static struct cli_state *cli2;
7263 const char *fname = "\\readonly.file";
7264 uint16_t fnum1, fnum2;
7267 bool correct = True;
7271 printf("starting open test\n");
7273 if (!torture_open_connection(&cli1, 0)) {
7277 cli_setatr(cli1, fname, 0, 0);
7278 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7280 smbXcli_conn_set_sockopt(cli1->conn, sockops);
7282 status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
7283 if (!NT_STATUS_IS_OK(status)) {
7284 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
7288 status = cli_close(cli1, fnum1);
7289 if (!NT_STATUS_IS_OK(status)) {
7290 printf("close2 failed (%s)\n", nt_errstr(status));
7294 status = cli_setatr(cli1, fname, FILE_ATTRIBUTE_READONLY, 0);
7295 if (!NT_STATUS_IS_OK(status)) {
7296 printf("cli_setatr failed (%s)\n", nt_errstr(status));
7300 status = cli_openx(cli1, fname, O_RDONLY, DENY_WRITE, &fnum1);
7301 if (!NT_STATUS_IS_OK(status)) {
7302 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
7306 /* This will fail - but the error should be ERRnoaccess, not ERRbadshare. */
7307 status = cli_openx(cli1, fname, O_RDWR, DENY_ALL, &fnum2);
7309 if (check_error(__LINE__, status, ERRDOS, ERRnoaccess,
7310 NT_STATUS_ACCESS_DENIED)) {
7311 printf("correct error code ERRDOS/ERRnoaccess returned\n");
7314 printf("finished open test 1\n");
7316 cli_close(cli1, fnum1);
7318 /* Now try not readonly and ensure ERRbadshare is returned. */
7320 cli_setatr(cli1, fname, 0, 0);
7322 status = cli_openx(cli1, fname, O_RDONLY, DENY_WRITE, &fnum1);
7323 if (!NT_STATUS_IS_OK(status)) {
7324 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
7328 /* This will fail - but the error should be ERRshare. */
7329 status = cli_openx(cli1, fname, O_RDWR, DENY_ALL, &fnum2);
7331 if (check_error(__LINE__, status, ERRDOS, ERRbadshare,
7332 NT_STATUS_SHARING_VIOLATION)) {
7333 printf("correct error code ERRDOS/ERRbadshare returned\n");
7336 status = cli_close(cli1, fnum1);
7337 if (!NT_STATUS_IS_OK(status)) {
7338 printf("close2 failed (%s)\n", nt_errstr(status));
7342 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7344 printf("finished open test 2\n");
7346 /* Test truncate open disposition on file opened for read. */
7347 status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
7348 if (!NT_STATUS_IS_OK(status)) {
7349 printf("(3) open (1) of %s failed (%s)\n", fname, nt_errstr(status));
7353 /* write 20 bytes. */
7355 memset(buf, '\0', 20);
7357 status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 0, 20, NULL);
7358 if (!NT_STATUS_IS_OK(status)) {
7359 printf("write failed (%s)\n", nt_errstr(status));
7363 status = cli_close(cli1, fnum1);
7364 if (!NT_STATUS_IS_OK(status)) {
7365 printf("(3) close1 failed (%s)\n", nt_errstr(status));
7369 /* Ensure size == 20. */
7370 status = cli_getatr(cli1, fname, NULL, &fsize, NULL);
7371 if (!NT_STATUS_IS_OK(status)) {
7372 printf("(3) getatr failed (%s)\n", nt_errstr(status));
7377 printf("(3) file size != 20\n");
7381 /* Now test if we can truncate a file opened for readonly. */
7382 status = cli_openx(cli1, fname, O_RDONLY|O_TRUNC, DENY_NONE, &fnum1);
7383 if (!NT_STATUS_IS_OK(status)) {
7384 printf("(3) open (2) of %s failed (%s)\n", fname, nt_errstr(status));
7388 status = cli_close(cli1, fnum1);
7389 if (!NT_STATUS_IS_OK(status)) {
7390 printf("close2 failed (%s)\n", nt_errstr(status));
7394 /* Ensure size == 0. */
7395 status = cli_getatr(cli1, fname, NULL, &fsize, NULL);
7396 if (!NT_STATUS_IS_OK(status)) {
7397 printf("(3) getatr failed (%s)\n", nt_errstr(status));
7402 printf("(3) file size != 0\n");
7405 printf("finished open test 3\n");
7407 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7409 printf("Do ctemp tests\n");
7410 status = cli_ctemp(cli1, talloc_tos(), "\\", &fnum1, &tmp_path);
7411 if (!NT_STATUS_IS_OK(status)) {
7412 printf("ctemp failed (%s)\n", nt_errstr(status));
7416 printf("ctemp gave path %s\n", tmp_path);
7417 status = cli_close(cli1, fnum1);
7418 if (!NT_STATUS_IS_OK(status)) {
7419 printf("close of temp failed (%s)\n", nt_errstr(status));
7422 status = cli_unlink(cli1, tmp_path, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7423 if (!NT_STATUS_IS_OK(status)) {
7424 printf("unlink of temp failed (%s)\n", nt_errstr(status));
7427 /* Test the non-io opens... */
7429 if (!torture_open_connection(&cli2, 1)) {
7433 cli_setatr(cli2, fname, 0, 0);
7434 cli_unlink(cli2, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7436 smbXcli_conn_set_sockopt(cli2->conn, sockops);
7438 printf("TEST #1 testing 2 non-io opens (no delete)\n");
7439 status = cli_ntcreate(cli1, fname, 0, FILE_READ_ATTRIBUTES,
7440 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7441 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
7442 if (!NT_STATUS_IS_OK(status)) {
7443 printf("TEST #1 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
7447 status = cli_ntcreate(cli2, fname, 0, FILE_READ_ATTRIBUTES,
7448 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7449 FILE_OPEN_IF, 0, 0, &fnum2, NULL);
7450 if (!NT_STATUS_IS_OK(status)) {
7451 printf("TEST #1 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
7455 status = cli_close(cli1, fnum1);
7456 if (!NT_STATUS_IS_OK(status)) {
7457 printf("TEST #1 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
7461 status = cli_close(cli2, fnum2);
7462 if (!NT_STATUS_IS_OK(status)) {
7463 printf("TEST #1 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
7467 printf("non-io open test #1 passed.\n");
7469 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7471 printf("TEST #2 testing 2 non-io opens (first with delete)\n");
7473 status = cli_ntcreate(cli1, fname, 0,
7474 DELETE_ACCESS|FILE_READ_ATTRIBUTES,
7475 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7476 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
7477 if (!NT_STATUS_IS_OK(status)) {
7478 printf("TEST #2 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
7482 status = cli_ntcreate(cli2, fname, 0, FILE_READ_ATTRIBUTES,
7483 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7484 FILE_OPEN_IF, 0, 0, &fnum2, NULL);
7485 if (!NT_STATUS_IS_OK(status)) {
7486 printf("TEST #2 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
7490 status = cli_close(cli1, fnum1);
7491 if (!NT_STATUS_IS_OK(status)) {
7492 printf("TEST #2 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
7496 status = cli_close(cli2, fnum2);
7497 if (!NT_STATUS_IS_OK(status)) {
7498 printf("TEST #2 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
7502 printf("non-io open test #2 passed.\n");
7504 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7506 printf("TEST #3 testing 2 non-io opens (second with delete)\n");
7508 status = cli_ntcreate(cli1, fname, 0, FILE_READ_ATTRIBUTES,
7509 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7510 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
7511 if (!NT_STATUS_IS_OK(status)) {
7512 printf("TEST #3 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
7516 status = cli_ntcreate(cli2, fname, 0,
7517 DELETE_ACCESS|FILE_READ_ATTRIBUTES,
7518 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7519 FILE_OPEN_IF, 0, 0, &fnum2, NULL);
7520 if (!NT_STATUS_IS_OK(status)) {
7521 printf("TEST #3 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
7525 status = cli_close(cli1, fnum1);
7526 if (!NT_STATUS_IS_OK(status)) {
7527 printf("TEST #3 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
7531 status = cli_close(cli2, fnum2);
7532 if (!NT_STATUS_IS_OK(status)) {
7533 printf("TEST #3 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
7537 printf("non-io open test #3 passed.\n");
7539 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7541 printf("TEST #4 testing 2 non-io opens (both with delete)\n");
7543 status = cli_ntcreate(cli1, fname, 0,
7544 DELETE_ACCESS|FILE_READ_ATTRIBUTES,
7545 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7546 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
7547 if (!NT_STATUS_IS_OK(status)) {
7548 printf("TEST #4 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
7552 status = cli_ntcreate(cli2, fname, 0,
7553 DELETE_ACCESS|FILE_READ_ATTRIBUTES,
7554 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7555 FILE_OPEN_IF, 0, 0, &fnum2, NULL);
7556 if (NT_STATUS_IS_OK(status)) {
7557 printf("TEST #4 open 2 of %s SUCCEEDED - should have failed (%s)\n", fname, nt_errstr(status));
7561 printf("TEST #4 open 2 of %s gave %s (correct error should be %s)\n", fname, nt_errstr(status), "sharing violation");
7563 status = cli_close(cli1, fnum1);
7564 if (!NT_STATUS_IS_OK(status)) {
7565 printf("TEST #4 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
7569 printf("non-io open test #4 passed.\n");
7571 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7573 printf("TEST #5 testing 2 non-io opens (both with delete - both with file share delete)\n");
7575 status = cli_ntcreate(cli1, fname, 0,
7576 DELETE_ACCESS|FILE_READ_ATTRIBUTES,
7577 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_DELETE,
7578 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
7579 if (!NT_STATUS_IS_OK(status)) {
7580 printf("TEST #5 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
7584 status = cli_ntcreate(cli2, fname, 0,
7585 DELETE_ACCESS|FILE_READ_ATTRIBUTES,
7586 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_DELETE,
7587 FILE_OPEN_IF, 0, 0, &fnum2, NULL);
7588 if (!NT_STATUS_IS_OK(status)) {
7589 printf("TEST #5 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
7593 status = cli_close(cli1, fnum1);
7594 if (!NT_STATUS_IS_OK(status)) {
7595 printf("TEST #5 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
7599 status = cli_close(cli2, fnum2);
7600 if (!NT_STATUS_IS_OK(status)) {
7601 printf("TEST #5 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
7605 printf("non-io open test #5 passed.\n");
7607 printf("TEST #6 testing 1 non-io open, one io open\n");
7609 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7611 status = cli_ntcreate(cli1, fname, 0, FILE_READ_DATA,
7612 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7613 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
7614 if (!NT_STATUS_IS_OK(status)) {
7615 printf("TEST #6 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
7619 status = cli_ntcreate(cli2, fname, 0, FILE_READ_ATTRIBUTES,
7620 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ,
7621 FILE_OPEN_IF, 0, 0, &fnum2, NULL);
7622 if (!NT_STATUS_IS_OK(status)) {
7623 printf("TEST #6 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
7627 status = cli_close(cli1, fnum1);
7628 if (!NT_STATUS_IS_OK(status)) {
7629 printf("TEST #6 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
7633 status = cli_close(cli2, fnum2);
7634 if (!NT_STATUS_IS_OK(status)) {
7635 printf("TEST #6 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
7639 printf("non-io open test #6 passed.\n");
7641 printf("TEST #7 testing 1 non-io open, one io open with delete\n");
7643 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7645 status = cli_ntcreate(cli1, fname, 0, FILE_READ_DATA,
7646 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7647 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
7648 if (!NT_STATUS_IS_OK(status)) {
7649 printf("TEST #7 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
7653 status = cli_ntcreate(cli2, fname, 0,
7654 DELETE_ACCESS|FILE_READ_ATTRIBUTES,
7655 FILE_ATTRIBUTE_NORMAL,
7656 FILE_SHARE_READ|FILE_SHARE_DELETE,
7657 FILE_OPEN_IF, 0, 0, &fnum2, NULL);
7658 if (NT_STATUS_IS_OK(status)) {
7659 printf("TEST #7 open 2 of %s SUCCEEDED - should have failed (%s)\n", fname, nt_errstr(status));
7663 printf("TEST #7 open 2 of %s gave %s (correct error should be %s)\n", fname, nt_errstr(status), "sharing violation");
7665 status = cli_close(cli1, fnum1);
7666 if (!NT_STATUS_IS_OK(status)) {
7667 printf("TEST #7 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
7671 printf("non-io open test #7 passed.\n");
7673 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7675 printf("TEST #8 testing open without WRITE_ATTRIBUTES, updating close write time.\n");
7676 status = cli_ntcreate(cli1, fname, 0, FILE_WRITE_DATA, FILE_ATTRIBUTE_NORMAL,
7677 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
7678 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
7679 if (!NT_STATUS_IS_OK(status)) {
7680 printf("TEST #8 open of %s failed (%s)\n", fname, nt_errstr(status));
7685 /* Write to ensure we have to update the file time. */
7686 status = cli_writeall(cli1, fnum1, 0, (const uint8_t *)"TEST DATA\n", 0, 10,
7688 if (!NT_STATUS_IS_OK(status)) {
7689 printf("TEST #8 cli_write failed: %s\n", nt_errstr(status));
7694 status = cli_close(cli1, fnum1);
7695 if (!NT_STATUS_IS_OK(status)) {
7696 printf("TEST #8 close of %s failed (%s)\n", fname, nt_errstr(status));
7702 if (!torture_close_connection(cli1)) {
7705 if (!torture_close_connection(cli2)) {
7712 NTSTATUS torture_setup_unix_extensions(struct cli_state *cli)
7714 uint16_t major, minor;
7715 uint32_t caplow, caphigh;
7718 if (!SERVER_HAS_UNIX_CIFS(cli)) {
7719 printf("Server doesn't support UNIX CIFS extensions.\n");
7720 return NT_STATUS_NOT_SUPPORTED;
7723 status = cli_unix_extensions_version(cli, &major, &minor, &caplow,
7725 if (!NT_STATUS_IS_OK(status)) {
7726 printf("Server didn't return UNIX CIFS extensions: %s\n",
7731 status = cli_set_unix_extensions_capabilities(cli, major, minor,
7733 if (!NT_STATUS_IS_OK(status)) {
7734 printf("Server doesn't support setting UNIX CIFS extensions: "
7735 "%s.\n", nt_errstr(status));
7739 return NT_STATUS_OK;
7743 Test POSIX open /mkdir calls.
7745 static bool run_simple_posix_open_test(int dummy)
7747 static struct cli_state *cli1;
7748 const char *fname = "posix:file";
7749 const char *hname = "posix:hlink";
7750 const char *sname = "posix:symlink";
7751 const char *dname = "posix:dir";
7753 char *target = NULL;
7754 uint16_t fnum1 = (uint16_t)-1;
7755 SMB_STRUCT_STAT sbuf;
7756 bool correct = false;
7759 const char *fname_windows = "windows_file";
7760 uint16_t fnum2 = (uint16_t)-1;
7762 printf("Starting simple POSIX open test\n");
7764 if (!torture_open_connection(&cli1, 0)) {
7768 smbXcli_conn_set_sockopt(cli1->conn, sockops);
7770 status = torture_setup_unix_extensions(cli1);
7771 if (!NT_STATUS_IS_OK(status)) {
7775 cli_setatr(cli1, fname, 0, 0);
7776 cli_posix_unlink(cli1, fname);
7777 cli_setatr(cli1, dname, 0, 0);
7778 cli_posix_rmdir(cli1, dname);
7779 cli_setatr(cli1, hname, 0, 0);
7780 cli_posix_unlink(cli1, hname);
7781 cli_setatr(cli1, sname, 0, 0);
7782 cli_posix_unlink(cli1, sname);
7783 cli_setatr(cli1, fname_windows, 0, 0);
7784 cli_posix_unlink(cli1, fname_windows);
7786 /* Create a directory. */
7787 status = cli_posix_mkdir(cli1, dname, 0777);
7788 if (!NT_STATUS_IS_OK(status)) {
7789 printf("POSIX mkdir of %s failed (%s)\n", dname, nt_errstr(status));
7793 status = cli_posix_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL,
7795 if (!NT_STATUS_IS_OK(status)) {
7796 printf("POSIX create of %s failed (%s)\n", fname, nt_errstr(status));
7800 /* Test ftruncate - set file size. */
7801 status = cli_ftruncate(cli1, fnum1, 1000);
7802 if (!NT_STATUS_IS_OK(status)) {
7803 printf("ftruncate failed (%s)\n", nt_errstr(status));
7807 /* Ensure st_size == 1000 */
7808 status = cli_posix_stat(cli1, fname, &sbuf);
7809 if (!NT_STATUS_IS_OK(status)) {
7810 printf("stat failed (%s)\n", nt_errstr(status));
7814 if (sbuf.st_ex_size != 1000) {
7815 printf("ftruncate - stat size (%u) != 1000\n", (unsigned int)sbuf.st_ex_size);
7819 /* Ensure st_mode == 0600 */
7820 if ((sbuf.st_ex_mode & 07777) != 0600) {
7821 printf("posix_open - bad permissions 0%o != 0600\n",
7822 (unsigned int)(sbuf.st_ex_mode & 07777));
7826 /* Test ftruncate - set file size back to zero. */
7827 status = cli_ftruncate(cli1, fnum1, 0);
7828 if (!NT_STATUS_IS_OK(status)) {
7829 printf("ftruncate failed (%s)\n", nt_errstr(status));
7833 status = cli_close(cli1, fnum1);
7834 if (!NT_STATUS_IS_OK(status)) {
7835 printf("close failed (%s)\n", nt_errstr(status));
7839 /* Now open the file again for read only. */
7840 status = cli_posix_open(cli1, fname, O_RDONLY, 0, &fnum1);
7841 if (!NT_STATUS_IS_OK(status)) {
7842 printf("POSIX open of %s failed (%s)\n", fname, nt_errstr(status));
7846 /* Now unlink while open. */
7847 status = cli_posix_unlink(cli1, fname);
7848 if (!NT_STATUS_IS_OK(status)) {
7849 printf("POSIX unlink of %s failed (%s)\n", fname, nt_errstr(status));
7853 status = cli_close(cli1, fnum1);
7854 if (!NT_STATUS_IS_OK(status)) {
7855 printf("close(2) failed (%s)\n", nt_errstr(status));
7859 /* Ensure the file has gone. */
7860 status = cli_posix_open(cli1, fname, O_RDONLY, 0, &fnum1);
7861 if (NT_STATUS_IS_OK(status)) {
7862 printf("POSIX open of %s succeeded, should have been deleted.\n", fname);
7866 /* Create again to test open with O_TRUNC. */
7867 status = cli_posix_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL, 0600, &fnum1);
7868 if (!NT_STATUS_IS_OK(status)) {
7869 printf("POSIX create of %s failed (%s)\n", fname, nt_errstr(status));
7873 /* Test ftruncate - set file size. */
7874 status = cli_ftruncate(cli1, fnum1, 1000);
7875 if (!NT_STATUS_IS_OK(status)) {
7876 printf("ftruncate failed (%s)\n", nt_errstr(status));
7880 /* Ensure st_size == 1000 */
7881 status = cli_posix_stat(cli1, fname, &sbuf);
7882 if (!NT_STATUS_IS_OK(status)) {
7883 printf("stat failed (%s)\n", nt_errstr(status));
7887 if (sbuf.st_ex_size != 1000) {
7888 printf("ftruncate - stat size (%u) != 1000\n", (unsigned int)sbuf.st_ex_size);
7892 status = cli_close(cli1, fnum1);
7893 if (!NT_STATUS_IS_OK(status)) {
7894 printf("close(2) failed (%s)\n", nt_errstr(status));
7898 /* Re-open with O_TRUNC. */
7899 status = cli_posix_open(cli1, fname, O_WRONLY|O_TRUNC, 0600, &fnum1);
7900 if (!NT_STATUS_IS_OK(status)) {
7901 printf("POSIX create of %s failed (%s)\n", fname, nt_errstr(status));
7905 /* Ensure st_size == 0 */
7906 status = cli_posix_stat(cli1, fname, &sbuf);
7907 if (!NT_STATUS_IS_OK(status)) {
7908 printf("stat failed (%s)\n", nt_errstr(status));
7912 if (sbuf.st_ex_size != 0) {
7913 printf("O_TRUNC - stat size (%u) != 0\n", (unsigned int)sbuf.st_ex_size);
7917 status = cli_close(cli1, fnum1);
7918 if (!NT_STATUS_IS_OK(status)) {
7919 printf("close failed (%s)\n", nt_errstr(status));
7923 status = cli_posix_unlink(cli1, fname);
7924 if (!NT_STATUS_IS_OK(status)) {
7925 printf("POSIX unlink of %s failed (%s)\n", fname, nt_errstr(status));
7929 status = cli_posix_open(cli1, dname, O_RDONLY, 0, &fnum1);
7930 if (!NT_STATUS_IS_OK(status)) {
7931 printf("POSIX open directory O_RDONLY of %s failed (%s)\n",
7932 dname, nt_errstr(status));
7936 cli_close(cli1, fnum1);
7938 /* What happens when we try and POSIX open a directory for write ? */
7939 status = cli_posix_open(cli1, dname, O_RDWR, 0, &fnum1);
7940 if (NT_STATUS_IS_OK(status)) {
7941 printf("POSIX open of directory %s succeeded, "
7942 "should have failed.\n",
7946 if (!check_both_error(__LINE__, status, ERRDOS, EISDIR,
7947 NT_STATUS_FILE_IS_A_DIRECTORY)) {
7952 /* Create the file. */
7953 status = cli_posix_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL,
7955 if (!NT_STATUS_IS_OK(status)) {
7956 printf("POSIX create of %s failed (%s)\n", fname, nt_errstr(status));
7960 /* Write some data into it. */
7961 status = cli_writeall(cli1, fnum1, 0, (const uint8_t *)"TEST DATA\n", 0, 10,
7963 if (!NT_STATUS_IS_OK(status)) {
7964 printf("cli_write failed: %s\n", nt_errstr(status));
7968 cli_close(cli1, fnum1);
7970 /* Now create a hardlink. */
7971 status = cli_posix_hardlink(cli1, fname, hname);
7972 if (!NT_STATUS_IS_OK(status)) {
7973 printf("POSIX hardlink of %s failed (%s)\n", hname, nt_errstr(status));
7977 /* Now create a symlink. */
7978 status = cli_posix_symlink(cli1, fname, sname);
7979 if (!NT_STATUS_IS_OK(status)) {
7980 printf("POSIX symlink of %s failed (%s)\n", sname, nt_errstr(status));
7984 /* Open the hardlink for read. */
7985 status = cli_posix_open(cli1, hname, O_RDONLY, 0, &fnum1);
7986 if (!NT_STATUS_IS_OK(status)) {
7987 printf("POSIX open of %s failed (%s)\n", hname, nt_errstr(status));
7991 status = cli_read(cli1, fnum1, buf, 0, 10, &nread);
7992 if (!NT_STATUS_IS_OK(status)) {
7993 printf("POSIX read of %s failed (%s)\n", hname,
7996 } else if (nread != 10) {
7997 printf("POSIX read of %s failed. Received %ld, expected %d\n",
7998 hname, (unsigned long)nread, 10);
8002 if (memcmp(buf, "TEST DATA\n", 10)) {
8003 printf("invalid data read from hardlink\n");
8007 /* Do a POSIX lock/unlock. */
8008 status = cli_posix_lock(cli1, fnum1, 0, 100, true, READ_LOCK);
8009 if (!NT_STATUS_IS_OK(status)) {
8010 printf("POSIX lock failed %s\n", nt_errstr(status));
8014 /* Punch a hole in the locked area. */
8015 status = cli_posix_unlock(cli1, fnum1, 10, 80);
8016 if (!NT_STATUS_IS_OK(status)) {
8017 printf("POSIX unlock failed %s\n", nt_errstr(status));
8021 cli_close(cli1, fnum1);
8023 /* Open the symlink for read - this should fail. A POSIX
8024 client should not be doing opens on a symlink. */
8025 status = cli_posix_open(cli1, sname, O_RDONLY, 0, &fnum1);
8026 if (NT_STATUS_IS_OK(status)) {
8027 printf("POSIX open of %s succeeded (should have failed)\n", sname);
8030 if (!check_both_error(__LINE__, status, ERRDOS, ERRbadpath,
8031 NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
8032 printf("POSIX open of %s should have failed "
8033 "with NT_STATUS_OBJECT_NAME_NOT_FOUND, "
8034 "failed with %s instead.\n",
8035 sname, nt_errstr(status));
8040 status = cli_posix_readlink(cli1, sname, talloc_tos(), &target);
8041 if (!NT_STATUS_IS_OK(status)) {
8042 printf("POSIX readlink on %s failed (%s)\n", sname, nt_errstr(status));
8046 if (strcmp(target, fname) != 0) {
8047 printf("POSIX readlink on %s failed to match name %s (read %s)\n",
8048 sname, fname, target);
8052 status = cli_posix_rmdir(cli1, dname);
8053 if (!NT_STATUS_IS_OK(status)) {
8054 printf("POSIX rmdir failed (%s)\n", nt_errstr(status));
8058 /* Check directory opens with a specific permission. */
8059 status = cli_posix_mkdir(cli1, dname, 0700);
8060 if (!NT_STATUS_IS_OK(status)) {
8061 printf("POSIX mkdir of %s failed (%s)\n", dname, nt_errstr(status));
8065 /* Ensure st_mode == 0700 */
8066 status = cli_posix_stat(cli1, dname, &sbuf);
8067 if (!NT_STATUS_IS_OK(status)) {
8068 printf("stat failed (%s)\n", nt_errstr(status));
8072 if ((sbuf.st_ex_mode & 07777) != 0700) {
8073 printf("posix_mkdir - bad permissions 0%o != 0700\n",
8074 (unsigned int)(sbuf.st_ex_mode & 07777));
8079 * Now create a Windows file, and attempt a POSIX unlink.
8080 * This should fail with a sharing violation but due to:
8082 * [Bug 9571] Unlink after open causes smbd to panic
8084 * ensure we've fixed the lock ordering violation.
8087 status = cli_ntcreate(cli1, fname_windows, 0,
8088 FILE_READ_DATA|FILE_WRITE_DATA, 0,
8089 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
8091 0x0, 0x0, &fnum2, NULL);
8092 if (!NT_STATUS_IS_OK(status)) {
8093 printf("Windows create of %s failed (%s)\n", fname_windows,
8098 /* Now try posix_unlink. */
8099 status = cli_posix_unlink(cli1, fname_windows);
8100 if (!NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
8101 printf("POSIX unlink of %s should fail "
8102 "with NT_STATUS_SHARING_VIOLATION "
8103 "got %s instead !\n",
8109 cli_close(cli1, fnum2);
8111 printf("Simple POSIX open test passed\n");
8116 if (fnum1 != (uint16_t)-1) {
8117 cli_close(cli1, fnum1);
8118 fnum1 = (uint16_t)-1;
8121 if (fnum2 != (uint16_t)-1) {
8122 cli_close(cli1, fnum2);
8123 fnum2 = (uint16_t)-1;
8126 cli_setatr(cli1, sname, 0, 0);
8127 cli_posix_unlink(cli1, sname);
8128 cli_setatr(cli1, hname, 0, 0);
8129 cli_posix_unlink(cli1, hname);
8130 cli_setatr(cli1, fname, 0, 0);
8131 cli_posix_unlink(cli1, fname);
8132 cli_setatr(cli1, dname, 0, 0);
8133 cli_posix_rmdir(cli1, dname);
8134 cli_setatr(cli1, fname_windows, 0, 0);
8135 cli_posix_unlink(cli1, fname_windows);
8137 if (!torture_close_connection(cli1)) {
8145 Test POSIX and Windows ACLs are rejected on symlinks.
8147 static bool run_acl_symlink_test(int dummy)
8149 static struct cli_state *cli;
8150 const char *fname = "posix_file";
8151 const char *sname = "posix_symlink";
8152 uint16_t fnum = (uint16_t)-1;
8153 bool correct = false;
8155 char *posix_acl = NULL;
8156 size_t posix_acl_len = 0;
8157 char *posix_acl_sym = NULL;
8158 size_t posix_acl_len_sym = 0;
8159 struct security_descriptor *sd = NULL;
8160 TALLOC_CTX *frame = NULL;
8162 frame = talloc_stackframe();
8164 printf("Starting acl symlink test\n");
8166 if (!torture_open_connection(&cli, 0)) {
8171 smbXcli_conn_set_sockopt(cli->conn, sockops);
8173 status = torture_setup_unix_extensions(cli);
8174 if (!NT_STATUS_IS_OK(status)) {
8179 cli_setatr(cli, fname, 0, 0);
8180 cli_posix_unlink(cli, fname);
8181 cli_setatr(cli, sname, 0, 0);
8182 cli_posix_unlink(cli, sname);
8184 status = cli_ntcreate(cli,
8187 READ_CONTROL_ACCESS,
8189 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
8196 if (!NT_STATUS_IS_OK(status)) {
8197 printf("cli_ntcreate of %s failed (%s)\n",
8203 /* Get the Windows ACL on the file. */
8204 status = cli_query_secdesc(cli,
8208 if (!NT_STATUS_IS_OK(status)) {
8209 printf("cli_query_secdesc failed (%s)\n",
8214 /* Get the POSIX ACL on the file. */
8215 status = cli_posix_getacl(cli,
8221 if (!NT_STATUS_IS_OK(status)) {
8222 printf("cli_posix_getacl failed (%s)\n",
8227 status = cli_close(cli, fnum);
8228 if (!NT_STATUS_IS_OK(status)) {
8229 printf("close failed (%s)\n", nt_errstr(status));
8232 fnum = (uint16_t)-1;
8234 /* Now create a symlink. */
8235 status = cli_posix_symlink(cli, fname, sname);
8236 if (!NT_STATUS_IS_OK(status)) {
8237 printf("cli_posix_symlink of %s -> %s failed (%s)\n",
8244 /* Open a handle on the symlink for SD set/get should fail. */
8245 status = cli_ntcreate(cli,
8248 READ_CONTROL_ACCESS|SEC_STD_WRITE_DAC,
8250 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
8257 if (NT_STATUS_IS_OK(status)) {
8258 printf("Symlink open for getsd/setsd of %s "
8259 "succeeded (should fail)\n",
8264 /* Try a stat-open on the symlink, should also fail. */
8265 status = cli_ntcreate(cli,
8268 FILE_READ_ATTRIBUTES|FILE_WRITE_ATTRIBUTES,
8270 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
8277 if (NT_STATUS_IS_OK(status)) {
8278 printf("Stat-open of symlink succeeded (should fail)\n");
8282 /* Get the POSIX ACL on the symlink pathname. Should fail. */
8283 status = cli_posix_getacl(cli,
8289 if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
8290 printf("cli_posix_getacl on a symlink gave %s. "
8291 "Should be NT_STATUS_ACCESS_DENIED.\n",
8296 /* Set the POSIX ACL on the symlink pathname. Should fail. */
8297 status = cli_posix_setacl(cli,
8302 if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
8303 printf("cli_posix_setacl on a symlink gave %s. "
8304 "Should be NT_STATUS_ACCESS_DENIED.\n",
8309 printf("ACL symlink test passed\n");
8314 if (fnum != (uint16_t)-1) {
8315 cli_close(cli, fnum);
8316 fnum = (uint16_t)-1;
8319 cli_setatr(cli, sname, 0, 0);
8320 cli_posix_unlink(cli, sname);
8321 cli_setatr(cli, fname, 0, 0);
8322 cli_posix_unlink(cli, fname);
8324 if (!torture_close_connection(cli)) {
8333 Test POSIX can delete a file containing streams.
8335 static bool run_posix_stream_delete(int dummy)
8337 struct cli_state *cli1 = NULL;
8338 struct cli_state *cli2 = NULL;
8339 const char *fname = "streamfile";
8340 const char *stream_fname = "streamfile:Zone.Identifier:$DATA";
8341 uint16_t fnum1 = (uint16_t)-1;
8342 bool correct = false;
8344 TALLOC_CTX *frame = NULL;
8346 frame = talloc_stackframe();
8348 printf("Starting POSIX stream delete test\n");
8350 if (!torture_open_connection(&cli1, 0) ||
8351 !torture_open_connection(&cli2, 1)) {
8356 smbXcli_conn_set_sockopt(cli1->conn, sockops);
8357 smbXcli_conn_set_sockopt(cli2->conn, sockops);
8359 status = torture_setup_unix_extensions(cli2);
8360 if (!NT_STATUS_IS_OK(status)) {
8364 cli_setatr(cli1, fname, 0, 0);
8365 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
8367 /* Create the file. */
8368 status = cli_ntcreate(cli1,
8371 READ_CONTROL_ACCESS,
8373 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
8380 if (!NT_STATUS_IS_OK(status)) {
8381 printf("cli_ntcreate of %s failed (%s)\n",
8387 status = cli_close(cli1, fnum1);
8388 if (!NT_STATUS_IS_OK(status)) {
8389 printf("cli_close of %s failed (%s)\n",
8394 fnum1 = (uint16_t)-1;
8396 /* Now create the stream. */
8397 status = cli_ntcreate(cli1,
8402 FILE_SHARE_READ|FILE_SHARE_WRITE,
8409 if (!NT_STATUS_IS_OK(status)) {
8410 printf("cli_ntcreate of %s failed (%s)\n",
8416 /* Leave the stream handle open... */
8418 /* POSIX unlink should fail. */
8419 status = cli_posix_unlink(cli2, fname);
8420 if (NT_STATUS_IS_OK(status)) {
8421 printf("cli_posix_unlink of %s succeeded, should have failed\n",
8426 if (!NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
8427 printf("cli_posix_unlink of %s failed with (%s) "
8428 "should have been NT_STATUS_SHARING_VIOLATION\n",
8434 /* Close the stream handle. */
8435 status = cli_close(cli1, fnum1);
8436 if (!NT_STATUS_IS_OK(status)) {
8437 printf("cli_close of %s failed (%s)\n",
8442 fnum1 = (uint16_t)-1;
8444 /* POSIX unlink after stream handle closed should succeed. */
8445 status = cli_posix_unlink(cli2, fname);
8446 if (!NT_STATUS_IS_OK(status)) {
8447 printf("cli_posix_unlink of %s failed (%s)\n",
8453 printf("POSIX stream delete test passed\n");
8458 if (fnum1 != (uint16_t)-1) {
8459 cli_close(cli1, fnum1);
8460 fnum1 = (uint16_t)-1;
8463 cli_setatr(cli1, fname, 0, 0);
8464 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
8466 if (!torture_close_connection(cli1)) {
8469 if (!torture_close_connection(cli2)) {
8478 Test setting EA's are rejected on symlinks.
8480 static bool run_ea_symlink_test(int dummy)
8482 static struct cli_state *cli;
8483 const char *fname = "posix_file_ea";
8484 const char *sname = "posix_symlink_ea";
8485 const char *ea_name = "testea_name";
8486 const char *ea_value = "testea_value";
8487 uint16_t fnum = (uint16_t)-1;
8488 bool correct = false;
8491 struct ea_struct *eas = NULL;
8492 TALLOC_CTX *frame = NULL;
8494 frame = talloc_stackframe();
8496 printf("Starting EA symlink test\n");
8498 if (!torture_open_connection(&cli, 0)) {
8503 smbXcli_conn_set_sockopt(cli->conn, sockops);
8505 status = torture_setup_unix_extensions(cli);
8506 if (!NT_STATUS_IS_OK(status)) {
8511 cli_setatr(cli, fname, 0, 0);
8512 cli_posix_unlink(cli, fname);
8513 cli_setatr(cli, sname, 0, 0);
8514 cli_posix_unlink(cli, sname);
8516 status = cli_ntcreate(cli,
8519 READ_CONTROL_ACCESS,
8521 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
8528 if (!NT_STATUS_IS_OK(status)) {
8529 printf("cli_ntcreate of %s failed (%s)\n",
8535 status = cli_close(cli, fnum);
8536 if (!NT_STATUS_IS_OK(status)) {
8537 printf("close failed (%s)\n",
8541 fnum = (uint16_t)-1;
8543 /* Set an EA on the path. */
8544 status = cli_set_ea_path(cli,
8548 strlen(ea_value)+1);
8550 if (!NT_STATUS_IS_OK(status)) {
8551 printf("cli_set_ea_path failed (%s)\n",
8556 /* Now create a symlink. */
8557 status = cli_posix_symlink(cli, fname, sname);
8558 if (!NT_STATUS_IS_OK(status)) {
8559 printf("cli_posix_symlink of %s -> %s failed (%s)\n",
8566 /* Get the EA list on the path. Should return value set. */
8567 status = cli_get_ea_list_path(cli,
8573 if (!NT_STATUS_IS_OK(status)) {
8574 printf("cli_get_ea_list_path failed (%s)\n",
8579 /* Ensure the EA we set is there. */
8580 for (i=0; i<num_eas; i++) {
8581 if (strcmp(eas[i].name, ea_name) == 0 &&
8582 eas[i].value.length == strlen(ea_value)+1 &&
8583 memcmp(eas[i].value.data,
8585 eas[i].value.length) == 0) {
8591 printf("Didn't find EA on pathname %s\n",
8599 /* Get the EA list on the symlink. Should return empty list. */
8600 status = cli_get_ea_list_path(cli,
8606 if (!NT_STATUS_IS_OK(status)) {
8607 printf("cli_get_ea_list_path failed (%s)\n",
8613 printf("cli_get_ea_list_path failed (%s)\n",
8618 /* Set an EA on the symlink. Should fail. */
8619 status = cli_set_ea_path(cli,
8623 strlen(ea_value)+1);
8625 if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
8626 printf("cli_set_ea_path on a symlink gave %s. "
8627 "Should be NT_STATUS_ACCESS_DENIED.\n",
8632 printf("EA symlink test passed\n");
8637 if (fnum != (uint16_t)-1) {
8638 cli_close(cli, fnum);
8639 fnum = (uint16_t)-1;
8642 cli_setatr(cli, sname, 0, 0);
8643 cli_posix_unlink(cli, sname);
8644 cli_setatr(cli, fname, 0, 0);
8645 cli_posix_unlink(cli, fname);
8647 if (!torture_close_connection(cli)) {
8656 Test POSIX locks are OFD-locks.
8658 static bool run_posix_ofd_lock_test(int dummy)
8660 static struct cli_state *cli;
8661 const char *fname = "posix_file";
8662 uint16_t fnum1 = (uint16_t)-1;
8663 uint16_t fnum2 = (uint16_t)-1;
8664 bool correct = false;
8666 TALLOC_CTX *frame = NULL;
8668 frame = talloc_stackframe();
8670 printf("Starting POSIX ofd-lock test\n");
8672 if (!torture_open_connection(&cli, 0)) {
8677 smbXcli_conn_set_sockopt(cli->conn, sockops);
8679 status = torture_setup_unix_extensions(cli);
8680 if (!NT_STATUS_IS_OK(status)) {
8685 cli_setatr(cli, fname, 0, 0);
8686 cli_posix_unlink(cli, fname);
8688 /* Open the file twice. */
8689 status = cli_posix_open(cli, fname, O_RDWR|O_CREAT|O_EXCL,
8691 if (!NT_STATUS_IS_OK(status)) {
8692 printf("First POSIX open of %s failed\n", fname);
8696 status = cli_posix_open(cli, fname, O_RDWR, 0, &fnum2);
8697 if (!NT_STATUS_IS_OK(status)) {
8698 printf("First POSIX open of %s failed\n", fname);
8702 /* Set a 0-50 lock on fnum1. */
8703 status = cli_posix_lock(cli, fnum1, 0, 50, false, WRITE_LOCK);
8704 if (!NT_STATUS_IS_OK(status)) {
8705 printf("POSIX lock (1) failed %s\n", nt_errstr(status));
8709 /* Set a 60-100 lock on fnum2. */
8710 status = cli_posix_lock(cli, fnum2, 60, 100, false, WRITE_LOCK);
8711 if (!NT_STATUS_IS_OK(status)) {
8712 printf("POSIX lock (2) failed %s\n", nt_errstr(status));
8716 /* close fnum1 - 0-50 lock should go away. */
8717 status = cli_close(cli, fnum1);
8718 if (!NT_STATUS_IS_OK(status)) {
8719 printf("close failed (%s)\n",
8723 fnum1 = (uint16_t)-1;
8725 /* Change the lock context. */
8726 cli_setpid(cli, cli_getpid(cli) + 1);
8728 /* Re-open fnum1. */
8729 status = cli_posix_open(cli, fname, O_RDWR, 0, &fnum1);
8730 if (!NT_STATUS_IS_OK(status)) {
8731 printf("Third POSIX open of %s failed\n", fname);
8735 /* 60-100 lock should still be there. */
8736 status = cli_posix_lock(cli, fnum1, 60, 100, false, WRITE_LOCK);
8737 if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
8738 printf("POSIX lock 60-100 not there %s\n", nt_errstr(status));
8742 /* 0-50 lock should be gone. */
8743 status = cli_posix_lock(cli, fnum1, 0, 50, false, WRITE_LOCK);
8744 if (!NT_STATUS_IS_OK(status)) {
8745 printf("POSIX lock 0-50 failed %s\n", nt_errstr(status));
8749 printf("POSIX OFD lock test passed\n");
8754 if (fnum1 != (uint16_t)-1) {
8755 cli_close(cli, fnum1);
8756 fnum1 = (uint16_t)-1;
8758 if (fnum2 != (uint16_t)-1) {
8759 cli_close(cli, fnum2);
8760 fnum2 = (uint16_t)-1;
8763 cli_setatr(cli, fname, 0, 0);
8764 cli_posix_unlink(cli, fname);
8766 if (!torture_close_connection(cli)) {
8774 struct posix_blocking_state {
8775 struct tevent_context *ev;
8776 struct cli_state *cli1;
8778 struct cli_state *cli2;
8784 static void posix_blocking_locked(struct tevent_req *subreq);
8785 static void posix_blocking_gotblocked(struct tevent_req *subreq);
8786 static void posix_blocking_gotecho(struct tevent_req *subreq);
8787 static void posix_blocking_unlocked(struct tevent_req *subreq);
8789 static struct tevent_req *posix_blocking_send(
8790 TALLOC_CTX *mem_ctx,
8791 struct tevent_context *ev,
8792 struct cli_state *cli1,
8794 struct cli_state *cli2,
8797 struct tevent_req *req = NULL, *subreq = NULL;
8798 struct posix_blocking_state *state = NULL;
8800 req = tevent_req_create(mem_ctx, &state, struct posix_blocking_state);
8806 state->fnum1 = fnum1;
8808 state->fnum2 = fnum2;
8810 subreq = cli_posix_lock_send(
8819 if (tevent_req_nomem(subreq, req)) {
8820 return tevent_req_post(req, ev);
8822 tevent_req_set_callback(subreq, posix_blocking_locked, req);
8826 static void posix_blocking_locked(struct tevent_req *subreq)
8828 struct tevent_req *req = tevent_req_callback_data(
8829 subreq, struct tevent_req);
8830 struct posix_blocking_state *state = tevent_req_data(
8831 req, struct posix_blocking_state);
8834 status = cli_posix_lock_recv(subreq);
8835 TALLOC_FREE(subreq);
8836 if (tevent_req_nterror(req, status)) {
8840 subreq = cli_posix_lock_send(
8849 if (tevent_req_nomem(subreq, req)) {
8852 tevent_req_set_callback(subreq, posix_blocking_gotblocked, req);
8854 /* Make sure the blocking request is delivered */
8855 subreq = cli_echo_send(
8860 (DATA_BLOB) { .data = (uint8_t *)state, .length = 1 });
8861 if (tevent_req_nomem(subreq, req)) {
8864 tevent_req_set_callback(subreq, posix_blocking_gotecho, req);
8867 static void posix_blocking_gotblocked(struct tevent_req *subreq)
8869 struct tevent_req *req = tevent_req_callback_data(
8870 subreq, struct tevent_req);
8871 struct posix_blocking_state *state = tevent_req_data(
8872 req, struct posix_blocking_state);
8875 status = cli_posix_lock_recv(subreq);
8876 TALLOC_FREE(subreq);
8877 if (tevent_req_nterror(req, status)) {
8880 if (!state->gotecho) {
8881 printf("blocked req got through before echo\n");
8882 tevent_req_nterror(req, NT_STATUS_INVALID_LOCK_SEQUENCE);
8885 tevent_req_done(req);
8888 static void posix_blocking_gotecho(struct tevent_req *subreq)
8890 struct tevent_req *req = tevent_req_callback_data(
8891 subreq, struct tevent_req);
8892 struct posix_blocking_state *state = tevent_req_data(
8893 req, struct posix_blocking_state);
8896 status = cli_echo_recv(subreq);
8897 TALLOC_FREE(subreq);
8898 if (tevent_req_nterror(req, status)) {
8901 if (state->gotblocked) {
8902 printf("blocked req got through before echo\n");
8903 tevent_req_nterror(req, NT_STATUS_INVALID_LOCK_SEQUENCE);
8906 state->gotecho = true;
8908 subreq = cli_posix_lock_send(
8917 if (tevent_req_nomem(subreq, req)) {
8920 tevent_req_set_callback(subreq, posix_blocking_unlocked, req);
8923 static void posix_blocking_unlocked(struct tevent_req *subreq)
8925 struct tevent_req *req = tevent_req_callback_data(
8926 subreq, struct tevent_req);
8929 status = cli_posix_lock_recv(subreq);
8930 TALLOC_FREE(subreq);
8931 if (tevent_req_nterror(req, status)) {
8934 /* tevent_req_done in posix_blocking_gotlocked */
8937 static NTSTATUS posix_blocking_recv(struct tevent_req *req)
8939 return tevent_req_simple_recv_ntstatus(req);
8942 static bool run_posix_blocking_lock(int dummy)
8944 struct tevent_context *ev = NULL;
8945 struct cli_state *cli1 = NULL, *cli2 = NULL;
8946 const char *fname = "posix_blocking";
8947 uint16_t fnum1 = UINT16_MAX, fnum2 = UINT16_MAX;
8948 struct tevent_req *req = NULL;
8953 printf("Starting posix blocking lock test\n");
8955 ev = samba_tevent_context_init(NULL);
8960 ok = torture_open_connection(&cli1, 0);
8964 ok = torture_open_connection(&cli2, 0);
8969 smbXcli_conn_set_sockopt(cli1->conn, sockops);
8971 status = torture_setup_unix_extensions(cli1);
8972 if (!NT_STATUS_IS_OK(status)) {
8976 status = torture_setup_unix_extensions(cli2);
8977 if (!NT_STATUS_IS_OK(status)) {
8981 cli_setatr(cli1, fname, 0, 0);
8982 cli_posix_unlink(cli1, fname);
8984 status = cli_posix_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL,
8986 if (!NT_STATUS_IS_OK(status)) {
8987 printf("First POSIX open of %s failed: %s\n",
8993 status = cli_posix_open(cli2, fname, O_RDWR, 0600, &fnum2);
8994 if (!NT_STATUS_IS_OK(status)) {
8995 printf("Second POSIX open of %s failed: %s\n",
9001 req = posix_blocking_send(ev, ev, cli1, fnum1, cli2, fnum2);
9003 printf("cli_posix_blocking failed\n");
9007 ok = tevent_req_poll_ntstatus(req, ev, &status);
9009 printf("tevent_req_poll_ntstatus failed: %s\n",
9013 status = posix_blocking_recv(req);
9015 if (!NT_STATUS_IS_OK(status)) {
9016 printf("posix_blocking_recv returned %s\n",
9024 if (fnum1 != UINT16_MAX) {
9025 cli_close(cli1, fnum1);
9028 if (fnum2 != UINT16_MAX) {
9029 cli_close(cli2, fnum2);
9034 cli_setatr(cli1, fname, 0, 0);
9035 cli_posix_unlink(cli1, fname);
9041 ok &= torture_close_connection(cli1);
9045 ok &= torture_close_connection(cli2);
9057 Test POSIX mkdir is case-sensitive.
9059 static bool run_posix_mkdir_test(int dummy)
9061 static struct cli_state *cli;
9062 const char *fname_foo = "POSIX_foo";
9063 const char *fname_foo_Foo = "POSIX_foo/Foo";
9064 const char *fname_foo_foo = "POSIX_foo/foo";
9065 const char *fname_Foo = "POSIX_Foo";
9066 const char *fname_Foo_Foo = "POSIX_Foo/Foo";
9067 const char *fname_Foo_foo = "POSIX_Foo/foo";
9068 bool correct = false;
9070 TALLOC_CTX *frame = NULL;
9071 uint16_t fnum = (uint16_t)-1;
9073 frame = talloc_stackframe();
9075 printf("Starting POSIX mkdir test\n");
9077 if (!torture_open_connection(&cli, 0)) {
9082 smbXcli_conn_set_sockopt(cli->conn, sockops);
9084 status = torture_setup_unix_extensions(cli);
9085 if (!NT_STATUS_IS_OK(status)) {
9090 cli_posix_rmdir(cli, fname_foo_foo);
9091 cli_posix_rmdir(cli, fname_foo_Foo);
9092 cli_posix_rmdir(cli, fname_foo);
9094 cli_posix_rmdir(cli, fname_Foo_foo);
9095 cli_posix_rmdir(cli, fname_Foo_Foo);
9096 cli_posix_rmdir(cli, fname_Foo);
9099 * Create a file POSIX_foo then try
9100 * and use it in a directory path by
9101 * doing mkdir POSIX_foo/bar.
9102 * The mkdir should fail with
9103 * NT_STATUS_OBJECT_PATH_NOT_FOUND
9106 status = cli_posix_open(cli,
9111 if (!NT_STATUS_IS_OK(status)) {
9112 printf("cli_posix_open of %s failed error %s\n",
9118 status = cli_posix_mkdir(cli, fname_foo_foo, 0777);
9119 if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_PATH_NOT_FOUND)) {
9120 printf("cli_posix_mkdir of %s should fail with "
9121 "NT_STATUS_OBJECT_PATH_NOT_FOUND got "
9128 status = cli_close(cli, fnum);
9129 if (!NT_STATUS_IS_OK(status)) {
9130 printf("cli_close failed %s\n", nt_errstr(status));
9133 fnum = (uint16_t)-1;
9135 status = cli_posix_unlink(cli, fname_foo);
9136 if (!NT_STATUS_IS_OK(status)) {
9137 printf("cli_posix_unlink of %s failed error %s\n",
9144 * Now we've deleted everything, posix_mkdir, posix_rmdir,
9145 * posix_open, posix_unlink, on
9146 * POSIX_foo/foo should return NT_STATUS_OBJECT_PATH_NOT_FOUND
9147 * not silently create POSIX_foo/foo.
9150 status = cli_posix_mkdir(cli, fname_foo_foo, 0777);
9151 if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_PATH_NOT_FOUND)) {
9152 printf("cli_posix_mkdir of %s should fail with "
9153 "NT_STATUS_OBJECT_PATH_NOT_FOUND got "
9160 status = cli_posix_rmdir(cli, fname_foo_foo);
9161 if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_PATH_NOT_FOUND)) {
9162 printf("cli_posix_rmdir of %s should fail with "
9163 "NT_STATUS_OBJECT_PATH_NOT_FOUND got "
9170 status = cli_posix_open(cli,
9175 if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_PATH_NOT_FOUND)) {
9176 printf("cli_posix_open of %s should fail with "
9177 "NT_STATUS_OBJECT_PATH_NOT_FOUND got "
9184 status = cli_posix_unlink(cli, fname_foo_foo);
9185 if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_PATH_NOT_FOUND)) {
9186 printf("cli_posix_unlink of %s should fail with "
9187 "NT_STATUS_OBJECT_PATH_NOT_FOUND got "
9194 status = cli_posix_mkdir(cli, fname_foo, 0777);
9195 if (!NT_STATUS_IS_OK(status)) {
9196 printf("cli_posix_mkdir of %s failed\n", fname_foo);
9200 status = cli_posix_mkdir(cli, fname_Foo, 0777);
9201 if (!NT_STATUS_IS_OK(status)) {
9202 printf("cli_posix_mkdir of %s failed\n", fname_Foo);
9206 status = cli_posix_mkdir(cli, fname_foo_foo, 0777);
9207 if (!NT_STATUS_IS_OK(status)) {
9208 printf("cli_posix_mkdir of %s failed\n", fname_foo_foo);
9212 status = cli_posix_mkdir(cli, fname_foo_Foo, 0777);
9213 if (!NT_STATUS_IS_OK(status)) {
9214 printf("cli_posix_mkdir of %s failed\n", fname_foo_Foo);
9218 status = cli_posix_mkdir(cli, fname_Foo_foo, 0777);
9219 if (!NT_STATUS_IS_OK(status)) {
9220 printf("cli_posix_mkdir of %s failed\n", fname_Foo_foo);
9224 status = cli_posix_mkdir(cli, fname_Foo_Foo, 0777);
9225 if (!NT_STATUS_IS_OK(status)) {
9226 printf("cli_posix_mkdir of %s failed\n", fname_Foo_Foo);
9230 printf("POSIX mkdir test passed\n");
9235 if (fnum != (uint16_t)-1) {
9236 cli_close(cli, fnum);
9237 fnum = (uint16_t)-1;
9240 cli_posix_rmdir(cli, fname_foo_foo);
9241 cli_posix_rmdir(cli, fname_foo_Foo);
9242 cli_posix_rmdir(cli, fname_foo);
9244 cli_posix_rmdir(cli, fname_Foo_foo);
9245 cli_posix_rmdir(cli, fname_Foo_Foo);
9246 cli_posix_rmdir(cli, fname_Foo);
9248 if (!torture_close_connection(cli)) {
9256 struct posix_acl_oplock_state {
9257 struct tevent_context *ev;
9258 struct cli_state *cli;
9264 static void posix_acl_oplock_got_break(struct tevent_req *req)
9266 struct posix_acl_oplock_state *state = tevent_req_callback_data(
9267 req, struct posix_acl_oplock_state);
9272 status = cli_smb_oplock_break_waiter_recv(req, &fnum, &level);
9274 if (!NT_STATUS_IS_OK(status)) {
9275 printf("cli_smb_oplock_break_waiter_recv returned %s\n",
9279 *state->got_break = true;
9281 req = cli_oplock_ack_send(state, state->ev, state->cli, fnum,
9284 printf("cli_oplock_ack_send failed\n");
9289 static void posix_acl_oplock_got_acl(struct tevent_req *req)
9291 struct posix_acl_oplock_state *state = tevent_req_callback_data(
9292 req, struct posix_acl_oplock_state);
9293 size_t ret_size = 0;
9294 char *ret_data = NULL;
9296 state->status = cli_posix_getacl_recv(req,
9301 if (!NT_STATUS_IS_OK(state->status)) {
9302 printf("cli_posix_getacl_recv returned %s\n",
9303 nt_errstr(state->status));
9305 *state->acl_ret = true;
9308 static bool run_posix_acl_oplock_test(int dummy)
9310 struct tevent_context *ev;
9311 struct cli_state *cli1, *cli2;
9312 struct tevent_req *oplock_req, *getacl_req;
9313 const char *fname = "posix_acl_oplock";
9315 int saved_use_oplocks = use_oplocks;
9317 bool correct = true;
9318 bool got_break = false;
9319 bool acl_ret = false;
9321 struct posix_acl_oplock_state *state;
9323 printf("starting posix_acl_oplock test\n");
9325 if (!torture_open_connection(&cli1, 0)) {
9326 use_level_II_oplocks = false;
9327 use_oplocks = saved_use_oplocks;
9331 if (!torture_open_connection(&cli2, 1)) {
9332 use_level_II_oplocks = false;
9333 use_oplocks = saved_use_oplocks;
9337 /* Setup posix on cli2 only. */
9338 status = torture_setup_unix_extensions(cli2);
9339 if (!NT_STATUS_IS_OK(status)) {
9343 smbXcli_conn_set_sockopt(cli1->conn, sockops);
9344 smbXcli_conn_set_sockopt(cli2->conn, sockops);
9346 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
9348 /* Create the file on the Windows connection. */
9349 status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
9351 if (!NT_STATUS_IS_OK(status)) {
9352 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
9356 status = cli_close(cli1, fnum);
9357 if (!NT_STATUS_IS_OK(status)) {
9358 printf("close1 failed (%s)\n", nt_errstr(status));
9362 cli1->use_oplocks = true;
9364 /* Open with oplock. */
9365 status = cli_ntcreate(cli1,
9369 FILE_ATTRIBUTE_NORMAL,
9370 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
9377 if (!NT_STATUS_IS_OK(status)) {
9378 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
9382 ev = samba_tevent_context_init(talloc_tos());
9384 printf("tevent_context_init failed\n");
9388 state = talloc_zero(ev, struct posix_acl_oplock_state);
9389 if (state == NULL) {
9390 printf("talloc failed\n");
9395 state->got_break = &got_break;
9396 state->acl_ret = &acl_ret;
9398 oplock_req = cli_smb_oplock_break_waiter_send(
9399 talloc_tos(), ev, cli1);
9400 if (oplock_req == NULL) {
9401 printf("cli_smb_oplock_break_waiter_send failed\n");
9404 tevent_req_set_callback(oplock_req, posix_acl_oplock_got_break, state);
9406 /* Get ACL on POSIX connection - should break oplock. */
9407 getacl_req = cli_posix_getacl_send(talloc_tos(),
9411 if (getacl_req == NULL) {
9412 printf("cli_posix_getacl_send failed\n");
9415 tevent_req_set_callback(getacl_req, posix_acl_oplock_got_acl, state);
9417 while (!got_break || !acl_ret) {
9419 ret = tevent_loop_once(ev);
9421 printf("tevent_loop_once failed: %s\n",
9427 if (!NT_STATUS_IS_OK(state->status)) {
9428 printf("getacl failed (%s)\n", nt_errstr(state->status));
9432 status = cli_close(cli1, fnum);
9433 if (!NT_STATUS_IS_OK(status)) {
9434 printf("close2 failed (%s)\n", nt_errstr(status));
9438 status = cli_unlink(cli1,
9440 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
9441 if (!NT_STATUS_IS_OK(status)) {
9442 printf("unlink failed (%s)\n", nt_errstr(status));
9446 if (!torture_close_connection(cli1)) {
9449 if (!torture_close_connection(cli2)) {
9457 printf("finished posix acl oplock test\n");
9462 static bool run_posix_acl_shareroot_test(int dummy)
9464 struct cli_state *cli;
9466 bool correct = false;
9467 char *posix_acl = NULL;
9468 size_t posix_acl_len = 0;
9469 uint16_t num_file_acls = 0;
9470 uint16_t num_dir_acls = 0;
9472 uint32_t expected_size = 0;
9473 bool got_user = false;
9474 bool got_group = false;
9475 bool got_other = false;
9476 TALLOC_CTX *frame = NULL;
9478 frame = talloc_stackframe();
9480 printf("starting posix_acl_shareroot test\n");
9482 if (!torture_open_connection(&cli, 0)) {
9487 smbXcli_conn_set_sockopt(cli->conn, sockops);
9489 status = torture_setup_unix_extensions(cli);
9490 if (!NT_STATUS_IS_OK(status)) {
9491 printf("Failed to setup unix extensions\n");
9495 /* Get the POSIX ACL on the root of the share. */
9496 status = cli_posix_getacl(cli,
9502 if (!NT_STATUS_IS_OK(status)) {
9503 printf("cli_posix_getacl of '.' failed (%s)\n",
9508 if (posix_acl_len < 6 ||
9509 SVAL(posix_acl,0) != SMB_POSIX_ACL_VERSION) {
9510 printf("getfacl ., unknown POSIX acl version %u.\n",
9511 (unsigned int)CVAL(posix_acl,0) );
9515 num_file_acls = SVAL(posix_acl,2);
9516 num_dir_acls = SVAL(posix_acl,4);
9517 expected_size = SMB_POSIX_ACL_HEADER_SIZE +
9518 SMB_POSIX_ACL_ENTRY_SIZE*
9519 (num_file_acls+num_dir_acls);
9521 if (posix_acl_len != expected_size) {
9522 printf("incorrect POSIX acl buffer size "
9523 "(should be %u, was %u).\n",
9524 (unsigned int)expected_size,
9525 (unsigned int)posix_acl_len);
9530 * We don't need to know what the ACL's are
9531 * we just need to know we have at least 3
9532 * file entries (u,g,o).
9535 for (i = 0; i < num_file_acls; i++) {
9536 unsigned char tagtype =
9538 SMB_POSIX_ACL_HEADER_SIZE+
9539 (i*SMB_POSIX_ACL_ENTRY_SIZE));
9542 case SMB_POSIX_ACL_USER_OBJ:
9545 case SMB_POSIX_ACL_GROUP_OBJ:
9548 case SMB_POSIX_ACL_OTHER:
9557 printf("Missing user entry\n");
9562 printf("Missing group entry\n");
9567 printf("Missing other entry\n");
9575 if (!torture_close_connection(cli)) {
9579 printf("finished posix acl shareroot test\n");
9585 static uint32_t open_attrs_table[] = {
9586 FILE_ATTRIBUTE_NORMAL,
9587 FILE_ATTRIBUTE_ARCHIVE,
9588 FILE_ATTRIBUTE_READONLY,
9589 FILE_ATTRIBUTE_HIDDEN,
9590 FILE_ATTRIBUTE_SYSTEM,
9592 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY,
9593 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN,
9594 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM,
9595 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN,
9596 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM,
9597 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM,
9599 FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN,
9600 FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM,
9601 FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM,
9602 FILE_ATTRIBUTE_HIDDEN,FILE_ATTRIBUTE_SYSTEM,
9605 struct trunc_open_results {
9608 uint32_t trunc_attr;
9609 uint32_t result_attr;
9612 static struct trunc_open_results attr_results[] = {
9613 { 0, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_ARCHIVE },
9614 { 1, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_ARCHIVE },
9615 { 2, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_READONLY, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY },
9616 { 16, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_ARCHIVE },
9617 { 17, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_ARCHIVE },
9618 { 18, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_READONLY, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY },
9619 { 51, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
9620 { 54, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
9621 { 56, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN },
9622 { 68, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
9623 { 71, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
9624 { 73, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM },
9625 { 99, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_HIDDEN,FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
9626 { 102, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
9627 { 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 },
9628 { 116, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
9629 { 119, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
9630 { 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 },
9631 { 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 },
9632 { 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 },
9633 { 227, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
9634 { 230, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
9635 { 232, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN },
9636 { 244, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
9637 { 247, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
9638 { 249, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM }
9641 static bool run_openattrtest(int dummy)
9643 static struct cli_state *cli1;
9644 const char *fname = "\\openattr.file";
9646 bool correct = True;
9648 unsigned int i, j, k, l;
9651 printf("starting open attr test\n");
9653 if (!torture_open_connection(&cli1, 0)) {
9657 smbXcli_conn_set_sockopt(cli1->conn, sockops);
9659 for (k = 0, i = 0; i < sizeof(open_attrs_table)/sizeof(uint32_t); i++) {
9660 cli_setatr(cli1, fname, 0, 0);
9661 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
9663 status = cli_ntcreate(cli1, fname, 0, FILE_WRITE_DATA,
9664 open_attrs_table[i], FILE_SHARE_NONE,
9665 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
9666 if (!NT_STATUS_IS_OK(status)) {
9667 printf("open %d (1) of %s failed (%s)\n", i, fname, nt_errstr(status));
9671 status = cli_close(cli1, fnum1);
9672 if (!NT_STATUS_IS_OK(status)) {
9673 printf("close %d (1) of %s failed (%s)\n", i, fname, nt_errstr(status));
9677 for (j = 0; j < sizeof(open_attrs_table)/sizeof(uint32_t); j++) {
9678 status = cli_ntcreate(cli1, fname, 0,
9679 FILE_READ_DATA|FILE_WRITE_DATA,
9680 open_attrs_table[j],
9681 FILE_SHARE_NONE, FILE_OVERWRITE,
9682 0, 0, &fnum1, NULL);
9683 if (!NT_STATUS_IS_OK(status)) {
9684 for (l = 0; l < sizeof(attr_results)/sizeof(struct trunc_open_results); l++) {
9685 if (attr_results[l].num == k) {
9686 printf("[%d] trunc open 0x%x -> 0x%x of %s failed - should have succeeded !(0x%x:%s)\n",
9687 k, open_attrs_table[i],
9688 open_attrs_table[j],
9689 fname, NT_STATUS_V(status), nt_errstr(status));
9694 if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
9695 printf("[%d] trunc open 0x%x -> 0x%x failed with wrong error code %s\n",
9696 k, open_attrs_table[i], open_attrs_table[j],
9701 printf("[%d] trunc open 0x%x -> 0x%x failed\n", k, open_attrs_table[i], open_attrs_table[j]);
9707 status = cli_close(cli1, fnum1);
9708 if (!NT_STATUS_IS_OK(status)) {
9709 printf("close %d (2) of %s failed (%s)\n", j, fname, nt_errstr(status));
9713 status = cli_getatr(cli1, fname, &attr, NULL, NULL);
9714 if (!NT_STATUS_IS_OK(status)) {
9715 printf("getatr(2) failed (%s)\n", nt_errstr(status));
9720 printf("[%d] getatr check [0x%x] trunc [0x%x] got attr 0x%x\n",
9721 k, open_attrs_table[i], open_attrs_table[j], attr );
9724 for (l = 0; l < sizeof(attr_results)/sizeof(struct trunc_open_results); l++) {
9725 if (attr_results[l].num == k) {
9726 if (attr != attr_results[l].result_attr ||
9727 open_attrs_table[i] != attr_results[l].init_attr ||
9728 open_attrs_table[j] != attr_results[l].trunc_attr) {
9729 printf("getatr check failed. [0x%x] trunc [0x%x] got attr 0x%x, should be 0x%x\n",
9730 open_attrs_table[i],
9731 open_attrs_table[j],
9733 attr_results[l].result_attr);
9743 cli_setatr(cli1, fname, 0, 0);
9744 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
9746 printf("open attr test %s.\n", correct ? "passed" : "failed");
9748 if (!torture_close_connection(cli1)) {
9754 static NTSTATUS list_fn(struct file_info *finfo,
9755 const char *name, void *state)
9757 int *matched = (int *)state;
9758 if (matched != NULL) {
9761 return NT_STATUS_OK;
9765 test directory listing speed
9767 static bool run_dirtest(int dummy)
9770 static struct cli_state *cli;
9772 struct timeval core_start;
9773 bool correct = True;
9776 printf("starting directory test\n");
9778 if (!torture_open_connection(&cli, 0)) {
9782 smbXcli_conn_set_sockopt(cli->conn, sockops);
9785 for (i=0;i<torture_numops;i++) {
9787 slprintf(fname, sizeof(fname), "\\%x", (int)random());
9788 if (!NT_STATUS_IS_OK(cli_openx(cli, fname, O_RDWR|O_CREAT, DENY_NONE, &fnum))) {
9789 fprintf(stderr,"Failed to open %s\n", fname);
9792 cli_close(cli, fnum);
9795 core_start = timeval_current();
9798 cli_list(cli, "a*.*", 0, list_fn, &matched);
9799 printf("Matched %d\n", matched);
9802 cli_list(cli, "b*.*", 0, list_fn, &matched);
9803 printf("Matched %d\n", matched);
9806 cli_list(cli, "xyzabc", 0, list_fn, &matched);
9807 printf("Matched %d\n", matched);
9809 printf("dirtest core %g seconds\n", timeval_elapsed(&core_start));
9812 for (i=0;i<torture_numops;i++) {
9814 slprintf(fname, sizeof(fname), "\\%x", (int)random());
9815 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
9818 if (!torture_close_connection(cli)) {
9822 printf("finished dirtest\n");
9827 static NTSTATUS del_fn(struct file_info *finfo, const char *mask,
9830 struct cli_state *pcli = (struct cli_state *)state;
9832 slprintf(fname, sizeof(fname), "\\LISTDIR\\%s", finfo->name);
9834 if (strcmp(finfo->name, ".") == 0 || strcmp(finfo->name, "..") == 0)
9835 return NT_STATUS_OK;
9837 if (finfo->attr & FILE_ATTRIBUTE_DIRECTORY) {
9838 if (!NT_STATUS_IS_OK(cli_rmdir(pcli, fname)))
9839 printf("del_fn: failed to rmdir %s\n,", fname );
9841 if (!NT_STATUS_IS_OK(cli_unlink(pcli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN)))
9842 printf("del_fn: failed to unlink %s\n,", fname );
9844 return NT_STATUS_OK;
9849 sees what IOCTLs are supported
9851 bool torture_ioctl_test(int dummy)
9853 static struct cli_state *cli;
9854 uint16_t device, function;
9856 const char *fname = "\\ioctl.dat";
9860 if (!torture_open_connection(&cli, 0)) {
9864 printf("starting ioctl test\n");
9866 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
9868 status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
9869 if (!NT_STATUS_IS_OK(status)) {
9870 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
9874 status = cli_raw_ioctl(cli, fnum, 0x2d0000 | (0x0420<<2), &blob);
9875 printf("ioctl device info: %s\n", nt_errstr(status));
9877 status = cli_raw_ioctl(cli, fnum, IOCTL_QUERY_JOB_INFO, &blob);
9878 printf("ioctl job info: %s\n", nt_errstr(status));
9880 for (device=0;device<0x100;device++) {
9881 printf("ioctl test with device = 0x%x\n", device);
9882 for (function=0;function<0x100;function++) {
9883 uint32_t code = (device<<16) | function;
9885 status = cli_raw_ioctl(cli, fnum, code, &blob);
9887 if (NT_STATUS_IS_OK(status)) {
9888 printf("ioctl 0x%x OK : %d bytes\n", (int)code,
9890 data_blob_free(&blob);
9895 if (!torture_close_connection(cli)) {
9904 tries varients of chkpath
9906 bool torture_chkpath_test(int dummy)
9908 static struct cli_state *cli;
9913 if (!torture_open_connection(&cli, 0)) {
9917 printf("starting chkpath test\n");
9919 /* cleanup from an old run */
9920 torture_deltree(cli, "\\chkpath.dir");
9922 status = cli_mkdir(cli, "\\chkpath.dir");
9923 if (!NT_STATUS_IS_OK(status)) {
9924 printf("mkdir1 failed : %s\n", nt_errstr(status));
9928 status = cli_mkdir(cli, "\\chkpath.dir\\dir2");
9929 if (!NT_STATUS_IS_OK(status)) {
9930 printf("mkdir2 failed : %s\n", nt_errstr(status));
9934 status = cli_openx(cli, "\\chkpath.dir\\foo.txt", O_RDWR|O_CREAT|O_EXCL,
9936 if (!NT_STATUS_IS_OK(status)) {
9937 printf("open1 failed (%s)\n", nt_errstr(status));
9940 cli_close(cli, fnum);
9942 status = cli_chkpath(cli, "\\chkpath.dir");
9943 if (!NT_STATUS_IS_OK(status)) {
9944 printf("chkpath1 failed: %s\n", nt_errstr(status));
9948 status = cli_chkpath(cli, "\\chkpath.dir\\dir2");
9949 if (!NT_STATUS_IS_OK(status)) {
9950 printf("chkpath2 failed: %s\n", nt_errstr(status));
9954 status = cli_chkpath(cli, "\\chkpath.dir\\foo.txt");
9955 if (!NT_STATUS_IS_OK(status)) {
9956 ret = check_error(__LINE__, status, ERRDOS, ERRbadpath,
9957 NT_STATUS_NOT_A_DIRECTORY);
9959 printf("* chkpath on a file should fail\n");
9963 status = cli_chkpath(cli, "\\chkpath.dir\\bar.txt");
9964 if (!NT_STATUS_IS_OK(status)) {
9965 ret = check_error(__LINE__, status, ERRDOS, ERRbadfile,
9966 NT_STATUS_OBJECT_NAME_NOT_FOUND);
9968 printf("* chkpath on a non existent file should fail\n");
9972 status = cli_chkpath(cli, "\\chkpath.dir\\dirxx\\bar.txt");
9973 if (!NT_STATUS_IS_OK(status)) {
9974 ret = check_error(__LINE__, status, ERRDOS, ERRbadpath,
9975 NT_STATUS_OBJECT_PATH_NOT_FOUND);
9977 printf("* chkpath on a non existent component should fail\n");
9981 torture_deltree(cli, "\\chkpath.dir");
9983 if (!torture_close_connection(cli)) {
9990 static bool run_eatest(int dummy)
9992 static struct cli_state *cli;
9993 const char *fname = "\\eatest.txt";
9994 bool correct = True;
9997 struct ea_struct *ea_list = NULL;
9998 TALLOC_CTX *mem_ctx = talloc_init("eatest");
10001 printf("starting eatest\n");
10003 if (!torture_open_connection(&cli, 0)) {
10004 talloc_destroy(mem_ctx);
10008 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
10010 status = cli_ntcreate(cli, fname, 0,
10011 FIRST_DESIRED_ACCESS, FILE_ATTRIBUTE_ARCHIVE,
10012 FILE_SHARE_NONE, FILE_OVERWRITE_IF,
10013 0x4044, 0, &fnum, NULL);
10014 if (!NT_STATUS_IS_OK(status)) {
10015 printf("open failed - %s\n", nt_errstr(status));
10016 talloc_destroy(mem_ctx);
10020 for (i = 0; i < 10; i++) {
10021 fstring ea_name, ea_val;
10023 slprintf(ea_name, sizeof(ea_name), "EA_%zu", i);
10024 memset(ea_val, (char)i+1, i+1);
10025 status = cli_set_ea_fnum(cli, fnum, ea_name, ea_val, i+1);
10026 if (!NT_STATUS_IS_OK(status)) {
10027 printf("ea_set of name %s failed - %s\n", ea_name,
10028 nt_errstr(status));
10029 talloc_destroy(mem_ctx);
10034 cli_close(cli, fnum);
10035 for (i = 0; i < 10; i++) {
10036 fstring ea_name, ea_val;
10038 slprintf(ea_name, sizeof(ea_name), "EA_%zu", i+10);
10039 memset(ea_val, (char)i+1, i+1);
10040 status = cli_set_ea_path(cli, fname, ea_name, ea_val, i+1);
10041 if (!NT_STATUS_IS_OK(status)) {
10042 printf("ea_set of name %s failed - %s\n", ea_name,
10043 nt_errstr(status));
10044 talloc_destroy(mem_ctx);
10049 status = cli_get_ea_list_path(cli, fname, mem_ctx, &num_eas, &ea_list);
10050 if (!NT_STATUS_IS_OK(status)) {
10051 printf("ea_get list failed - %s\n", nt_errstr(status));
10055 printf("num_eas = %d\n", (int)num_eas);
10057 if (num_eas != 20) {
10058 printf("Should be 20 EA's stored... failing.\n");
10062 for (i = 0; i < num_eas; i++) {
10063 printf("%zu: ea_name = %s. Val = ", i, ea_list[i].name);
10064 dump_data(0, ea_list[i].value.data,
10065 ea_list[i].value.length);
10068 /* Setting EA's to zero length deletes them. Test this */
10069 printf("Now deleting all EA's - case indepenent....\n");
10072 cli_set_ea_path(cli, fname, "", "", 0);
10074 for (i = 0; i < 20; i++) {
10076 slprintf(ea_name, sizeof(ea_name), "ea_%d", i);
10077 status = cli_set_ea_path(cli, fname, ea_name, "", 0);
10078 if (!NT_STATUS_IS_OK(status)) {
10079 printf("ea_set of name %s failed - %s\n", ea_name,
10080 nt_errstr(status));
10081 talloc_destroy(mem_ctx);
10087 status = cli_get_ea_list_path(cli, fname, mem_ctx, &num_eas, &ea_list);
10088 if (!NT_STATUS_IS_OK(status)) {
10089 printf("ea_get list failed - %s\n", nt_errstr(status));
10093 printf("num_eas = %d\n", (int)num_eas);
10094 for (i = 0; i < num_eas; i++) {
10095 printf("%zu: ea_name = %s. Val = ", i, ea_list[i].name);
10096 dump_data(0, ea_list[i].value.data,
10097 ea_list[i].value.length);
10100 if (num_eas != 0) {
10101 printf("deleting EA's failed.\n");
10105 /* Try and delete a non existent EA. */
10106 status = cli_set_ea_path(cli, fname, "foo", "", 0);
10107 if (!NT_STATUS_IS_OK(status)) {
10108 printf("deleting non-existent EA 'foo' should succeed. %s\n",
10109 nt_errstr(status));
10113 talloc_destroy(mem_ctx);
10114 if (!torture_close_connection(cli)) {
10121 static bool run_dirtest1(int dummy)
10124 static struct cli_state *cli;
10127 bool correct = True;
10129 printf("starting directory test\n");
10131 if (!torture_open_connection(&cli, 0)) {
10135 smbXcli_conn_set_sockopt(cli->conn, sockops);
10137 cli_list(cli, "\\LISTDIR\\*", 0, del_fn, cli);
10138 cli_list(cli, "\\LISTDIR\\*", FILE_ATTRIBUTE_DIRECTORY, del_fn, cli);
10139 cli_rmdir(cli, "\\LISTDIR");
10140 cli_mkdir(cli, "\\LISTDIR");
10142 /* Create 1000 files and 1000 directories. */
10143 for (i=0;i<1000;i++) {
10145 slprintf(fname, sizeof(fname), "\\LISTDIR\\f%d", i);
10146 if (!NT_STATUS_IS_OK(cli_ntcreate(cli, fname, 0, GENERIC_ALL_ACCESS, FILE_ATTRIBUTE_ARCHIVE,
10147 FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OVERWRITE_IF,
10148 0, 0, &fnum, NULL))) {
10149 fprintf(stderr,"Failed to open %s\n", fname);
10152 cli_close(cli, fnum);
10154 for (i=0;i<1000;i++) {
10156 slprintf(fname, sizeof(fname), "\\LISTDIR\\d%d", i);
10157 if (!NT_STATUS_IS_OK(cli_mkdir(cli, fname))) {
10158 fprintf(stderr,"Failed to open %s\n", fname);
10163 /* Now ensure that doing an old list sees both files and directories. */
10165 cli_list_old(cli, "\\LISTDIR\\*", FILE_ATTRIBUTE_DIRECTORY, list_fn, &num_seen);
10166 printf("num_seen = %d\n", num_seen );
10167 /* We should see 100 files + 1000 directories + . and .. */
10168 if (num_seen != 2002)
10171 /* Ensure if we have the "must have" bits we only see the
10172 * relevent entries.
10175 cli_list_old(cli, "\\LISTDIR\\*", (FILE_ATTRIBUTE_DIRECTORY<<8)|FILE_ATTRIBUTE_DIRECTORY, list_fn, &num_seen);
10176 printf("num_seen = %d\n", num_seen );
10177 if (num_seen != 1002)
10181 cli_list_old(cli, "\\LISTDIR\\*", (FILE_ATTRIBUTE_ARCHIVE<<8)|FILE_ATTRIBUTE_DIRECTORY, list_fn, &num_seen);
10182 printf("num_seen = %d\n", num_seen );
10183 if (num_seen != 1000)
10186 /* Delete everything. */
10187 cli_list(cli, "\\LISTDIR\\*", 0, del_fn, cli);
10188 cli_list(cli, "\\LISTDIR\\*", FILE_ATTRIBUTE_DIRECTORY, del_fn, cli);
10189 cli_rmdir(cli, "\\LISTDIR");
10192 printf("Matched %d\n", cli_list(cli, "a*.*", 0, list_fn, NULL));
10193 printf("Matched %d\n", cli_list(cli, "b*.*", 0, list_fn, NULL));
10194 printf("Matched %d\n", cli_list(cli, "xyzabc", 0, list_fn, NULL));
10197 if (!torture_close_connection(cli)) {
10201 printf("finished dirtest1\n");
10206 static bool run_error_map_extract(int dummy) {
10208 static struct cli_state *c_dos;
10209 static struct cli_state *c_nt;
10217 NTSTATUS nt_status;
10221 /* NT-Error connection */
10223 disable_spnego = true;
10224 if (!(c_nt = open_nbt_connection())) {
10225 disable_spnego = false;
10228 disable_spnego = false;
10230 status = smbXcli_negprot(c_nt->conn, c_nt->timeout, PROTOCOL_CORE,
10233 if (!NT_STATUS_IS_OK(status)) {
10234 printf("%s rejected the NT-error negprot (%s)\n", host,
10235 nt_errstr(status));
10236 cli_shutdown(c_nt);
10240 status = cli_session_setup_anon(c_nt);
10241 if (!NT_STATUS_IS_OK(status)) {
10242 printf("%s rejected the NT-error initial session setup (%s)\n",host, nt_errstr(status));
10246 /* DOS-Error connection */
10248 disable_spnego = true;
10249 force_dos_errors = true;
10250 if (!(c_dos = open_nbt_connection())) {
10251 disable_spnego = false;
10252 force_dos_errors = false;
10255 disable_spnego = false;
10256 force_dos_errors = false;
10258 status = smbXcli_negprot(c_dos->conn, c_dos->timeout, PROTOCOL_CORE,
10260 if (!NT_STATUS_IS_OK(status)) {
10261 printf("%s rejected the DOS-error negprot (%s)\n", host,
10262 nt_errstr(status));
10263 cli_shutdown(c_dos);
10267 status = cli_session_setup_anon(c_dos);
10268 if (!NT_STATUS_IS_OK(status)) {
10269 printf("%s rejected the DOS-error initial session setup (%s)\n",
10270 host, nt_errstr(status));
10274 c_nt->map_dos_errors = false;
10275 c_dos->map_dos_errors = false;
10277 for (error=(0xc0000000 | 0x1); error < (0xc0000000| 0xFFF); error++) {
10278 struct cli_credentials *user_creds = NULL;
10280 fstr_sprintf(user, "%X", error);
10282 user_creds = cli_session_creds_init(talloc_tos(),
10287 false, /* use_kerberos */
10288 false, /* fallback_after_kerberos */
10289 false, /* use_ccache */
10290 false); /* password_is_nt_hash */
10291 if (user_creds == NULL) {
10292 printf("cli_session_creds_init(%s) failed\n", user);
10296 status = cli_session_setup_creds(c_nt, user_creds);
10297 if (NT_STATUS_IS_OK(status)) {
10298 printf("/** Session setup succeeded. This shouldn't happen...*/\n");
10301 /* Case #1: 32-bit NT errors */
10302 if (!NT_STATUS_IS_DOS(status)) {
10303 nt_status = status;
10305 printf("/** Dos error on NT connection! (%s) */\n",
10306 nt_errstr(status));
10307 nt_status = NT_STATUS(0xc0000000);
10310 status = cli_session_setup_creds(c_dos, user_creds);
10311 if (NT_STATUS_IS_OK(status)) {
10312 printf("/** Session setup succeeded. This shouldn't happen...*/\n");
10315 /* Case #1: 32-bit NT errors */
10316 if (NT_STATUS_IS_DOS(status)) {
10317 printf("/** NT error on DOS connection! (%s) */\n",
10318 nt_errstr(status));
10319 errnum = errclass = 0;
10321 errclass = NT_STATUS_DOS_CLASS(status);
10322 errnum = NT_STATUS_DOS_CODE(status);
10325 if (NT_STATUS_V(nt_status) != error) {
10326 printf("/*\t{ This NT error code was 'sqashed'\n\t from %s to %s \n\t during the session setup }\n*/\n",
10327 get_nt_error_c_code(talloc_tos(), NT_STATUS(error)),
10328 get_nt_error_c_code(talloc_tos(), nt_status));
10331 printf("\t{%s,\t%s,\t%s},\n",
10332 smb_dos_err_class(errclass),
10333 smb_dos_err_name(errclass, errnum),
10334 get_nt_error_c_code(talloc_tos(), NT_STATUS(error)));
10336 TALLOC_FREE(user_creds);
10341 static bool run_sesssetup_bench(int dummy)
10343 static struct cli_state *c;
10344 const char *fname = "\\file.dat";
10349 if (!torture_open_connection(&c, 0)) {
10353 status = cli_ntcreate(c, fname, 0, GENERIC_ALL_ACCESS|DELETE_ACCESS,
10354 FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
10355 FILE_DELETE_ON_CLOSE, 0, &fnum, NULL);
10356 if (!NT_STATUS_IS_OK(status)) {
10357 d_printf("open %s failed: %s\n", fname, nt_errstr(status));
10361 for (i=0; i<torture_numops; i++) {
10362 status = cli_session_setup_creds(c, torture_creds);
10363 if (!NT_STATUS_IS_OK(status)) {
10364 d_printf("(%s) cli_session_setup_creds failed: %s\n",
10365 __location__, nt_errstr(status));
10369 d_printf("\r%d ", (int)cli_state_get_uid(c));
10371 status = cli_ulogoff(c);
10372 if (!NT_STATUS_IS_OK(status)) {
10373 d_printf("(%s) cli_ulogoff failed: %s\n",
10374 __location__, nt_errstr(status));
10382 static bool subst_test(const char *str, const char *user, const char *domain,
10383 uid_t uid, gid_t gid, const char *expected)
10386 bool result = true;
10388 subst = talloc_sub_specified(talloc_tos(), str, user, NULL, domain, uid, gid);
10390 if (strcmp(subst, expected) != 0) {
10391 printf("sub_specified(%s, %s, %s, %d, %d) returned [%s], expected "
10392 "[%s]\n", str, user, domain, (int)uid, (int)gid, subst,
10397 TALLOC_FREE(subst);
10401 static void chain1_open_completion(struct tevent_req *req)
10405 status = cli_openx_recv(req, &fnum);
10408 d_printf("cli_openx_recv returned %s: %d\n",
10410 NT_STATUS_IS_OK(status) ? fnum : -1);
10413 static void chain1_write_completion(struct tevent_req *req)
10417 status = cli_write_andx_recv(req, &written);
10420 d_printf("cli_write_andx_recv returned %s: %d\n",
10422 NT_STATUS_IS_OK(status) ? (int)written : -1);
10425 static void chain1_close_completion(struct tevent_req *req)
10428 bool *done = (bool *)tevent_req_callback_data_void(req);
10430 status = cli_close_recv(req);
10435 d_printf("cli_close returned %s\n", nt_errstr(status));
10438 static bool run_chain1(int dummy)
10440 struct cli_state *cli1;
10441 struct tevent_context *evt = samba_tevent_context_init(NULL);
10442 struct tevent_req *reqs[3], *smbreqs[3];
10444 const char *str = "foobar";
10445 const char *fname = "\\test_chain";
10448 printf("starting chain1 test\n");
10449 if (!torture_open_connection(&cli1, 0)) {
10453 smbXcli_conn_set_sockopt(cli1->conn, sockops);
10455 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
10457 reqs[0] = cli_openx_create(talloc_tos(), evt, cli1, fname,
10458 O_CREAT|O_RDWR, 0, &smbreqs[0]);
10459 if (reqs[0] == NULL) return false;
10460 tevent_req_set_callback(reqs[0], chain1_open_completion, NULL);
10463 reqs[1] = cli_write_andx_create(talloc_tos(), evt, cli1, 0, 0,
10464 (const uint8_t *)str, 0, strlen(str)+1,
10465 smbreqs, 1, &smbreqs[1]);
10466 if (reqs[1] == NULL) return false;
10467 tevent_req_set_callback(reqs[1], chain1_write_completion, NULL);
10469 reqs[2] = cli_smb1_close_create(talloc_tos(), evt, cli1, 0, &smbreqs[2]);
10470 if (reqs[2] == NULL) return false;
10471 tevent_req_set_callback(reqs[2], chain1_close_completion, &done);
10473 status = smb1cli_req_chain_submit(smbreqs, ARRAY_SIZE(smbreqs));
10474 if (!NT_STATUS_IS_OK(status)) {
10479 tevent_loop_once(evt);
10482 torture_close_connection(cli1);
10486 static void chain2_sesssetup_completion(struct tevent_req *req)
10489 status = cli_session_setup_guest_recv(req);
10490 d_printf("sesssetup returned %s\n", nt_errstr(status));
10493 static void chain2_tcon_completion(struct tevent_req *req)
10495 bool *done = (bool *)tevent_req_callback_data_void(req);
10497 status = cli_tcon_andx_recv(req);
10498 d_printf("tcon_and_x returned %s\n", nt_errstr(status));
10502 static bool run_chain2(int dummy)
10504 struct cli_state *cli1;
10505 struct tevent_context *evt = samba_tevent_context_init(NULL);
10506 struct tevent_req *reqs[2], *smbreqs[2];
10509 int flags = CLI_FULL_CONNECTION_FORCE_SMB1;
10511 printf("starting chain2 test\n");
10512 status = cli_start_connection(&cli1, lp_netbios_name(), host, NULL,
10513 port_to_use, SMB_SIGNING_DEFAULT, flags);
10514 if (!NT_STATUS_IS_OK(status)) {
10518 smbXcli_conn_set_sockopt(cli1->conn, sockops);
10520 reqs[0] = cli_session_setup_guest_create(talloc_tos(), evt, cli1,
10522 if (reqs[0] == NULL) return false;
10523 tevent_req_set_callback(reqs[0], chain2_sesssetup_completion, NULL);
10525 reqs[1] = cli_tcon_andx_create(talloc_tos(), evt, cli1, "IPC$",
10526 "?????", NULL, 0, &smbreqs[1]);
10527 if (reqs[1] == NULL) return false;
10528 tevent_req_set_callback(reqs[1], chain2_tcon_completion, &done);
10530 status = smb1cli_req_chain_submit(smbreqs, ARRAY_SIZE(smbreqs));
10531 if (!NT_STATUS_IS_OK(status)) {
10536 tevent_loop_once(evt);
10539 torture_close_connection(cli1);
10544 struct torture_createdel_state {
10545 struct tevent_context *ev;
10546 struct cli_state *cli;
10549 static void torture_createdel_created(struct tevent_req *subreq);
10550 static void torture_createdel_closed(struct tevent_req *subreq);
10552 static struct tevent_req *torture_createdel_send(TALLOC_CTX *mem_ctx,
10553 struct tevent_context *ev,
10554 struct cli_state *cli,
10557 struct tevent_req *req, *subreq;
10558 struct torture_createdel_state *state;
10560 req = tevent_req_create(mem_ctx, &state,
10561 struct torture_createdel_state);
10568 subreq = cli_ntcreate_send(
10569 state, ev, cli, name, 0,
10570 FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
10571 FILE_ATTRIBUTE_NORMAL,
10572 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
10573 FILE_OPEN_IF, FILE_DELETE_ON_CLOSE,
10574 SMB2_IMPERSONATION_IMPERSONATION, 0);
10576 if (tevent_req_nomem(subreq, req)) {
10577 return tevent_req_post(req, ev);
10579 tevent_req_set_callback(subreq, torture_createdel_created, req);
10583 static void torture_createdel_created(struct tevent_req *subreq)
10585 struct tevent_req *req = tevent_req_callback_data(
10586 subreq, struct tevent_req);
10587 struct torture_createdel_state *state = tevent_req_data(
10588 req, struct torture_createdel_state);
10592 status = cli_ntcreate_recv(subreq, &fnum, NULL);
10593 TALLOC_FREE(subreq);
10594 if (tevent_req_nterror(req, status)) {
10595 DEBUG(10, ("cli_ntcreate_recv returned %s\n",
10596 nt_errstr(status)));
10600 subreq = cli_close_send(state, state->ev, state->cli, fnum);
10601 if (tevent_req_nomem(subreq, req)) {
10604 tevent_req_set_callback(subreq, torture_createdel_closed, req);
10607 static void torture_createdel_closed(struct tevent_req *subreq)
10609 struct tevent_req *req = tevent_req_callback_data(
10610 subreq, struct tevent_req);
10613 status = cli_close_recv(subreq);
10614 if (tevent_req_nterror(req, status)) {
10615 DEBUG(10, ("cli_close_recv returned %s\n", nt_errstr(status)));
10618 tevent_req_done(req);
10621 static NTSTATUS torture_createdel_recv(struct tevent_req *req)
10623 return tevent_req_simple_recv_ntstatus(req);
10626 struct torture_createdels_state {
10627 struct tevent_context *ev;
10628 struct cli_state *cli;
10629 const char *base_name;
10633 struct tevent_req **reqs;
10636 static void torture_createdels_done(struct tevent_req *subreq);
10638 static struct tevent_req *torture_createdels_send(TALLOC_CTX *mem_ctx,
10639 struct tevent_context *ev,
10640 struct cli_state *cli,
10641 const char *base_name,
10645 struct tevent_req *req;
10646 struct torture_createdels_state *state;
10649 req = tevent_req_create(mem_ctx, &state,
10650 struct torture_createdels_state);
10656 state->base_name = talloc_strdup(state, base_name);
10657 if (tevent_req_nomem(state->base_name, req)) {
10658 return tevent_req_post(req, ev);
10660 state->num_files = MAX(num_parallel, num_files);
10662 state->received = 0;
10664 state->reqs = talloc_array(state, struct tevent_req *, num_parallel);
10665 if (tevent_req_nomem(state->reqs, req)) {
10666 return tevent_req_post(req, ev);
10669 for (i=0; i<num_parallel; i++) {
10672 name = talloc_asprintf(state, "%s%8.8d", state->base_name,
10674 if (tevent_req_nomem(name, req)) {
10675 return tevent_req_post(req, ev);
10677 state->reqs[i] = torture_createdel_send(
10678 state->reqs, state->ev, state->cli, name);
10679 if (tevent_req_nomem(state->reqs[i], req)) {
10680 return tevent_req_post(req, ev);
10682 name = talloc_move(state->reqs[i], &name);
10683 tevent_req_set_callback(state->reqs[i],
10684 torture_createdels_done, req);
10690 static void torture_createdels_done(struct tevent_req *subreq)
10692 struct tevent_req *req = tevent_req_callback_data(
10693 subreq, struct tevent_req);
10694 struct torture_createdels_state *state = tevent_req_data(
10695 req, struct torture_createdels_state);
10696 size_t i, num_parallel = talloc_array_length(state->reqs);
10700 status = torture_createdel_recv(subreq);
10701 if (!NT_STATUS_IS_OK(status)){
10702 DEBUG(10, ("torture_createdel_recv returned %s\n",
10703 nt_errstr(status)));
10704 TALLOC_FREE(subreq);
10705 tevent_req_nterror(req, status);
10709 for (i=0; i<num_parallel; i++) {
10710 if (subreq == state->reqs[i]) {
10714 if (i == num_parallel) {
10715 DEBUG(10, ("received something we did not send\n"));
10716 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
10719 TALLOC_FREE(state->reqs[i]);
10721 if (state->sent >= state->num_files) {
10722 tevent_req_done(req);
10726 name = talloc_asprintf(state, "%s%8.8d", state->base_name,
10728 if (tevent_req_nomem(name, req)) {
10731 state->reqs[i] = torture_createdel_send(state->reqs, state->ev,
10733 if (tevent_req_nomem(state->reqs[i], req)) {
10736 name = talloc_move(state->reqs[i], &name);
10737 tevent_req_set_callback(state->reqs[i], torture_createdels_done, req);
10741 static NTSTATUS torture_createdels_recv(struct tevent_req *req)
10743 return tevent_req_simple_recv_ntstatus(req);
10746 struct swallow_notify_state {
10747 struct tevent_context *ev;
10748 struct cli_state *cli;
10750 uint32_t completion_filter;
10752 bool (*fn)(uint32_t action, const char *name, void *priv);
10756 static void swallow_notify_done(struct tevent_req *subreq);
10758 static struct tevent_req *swallow_notify_send(TALLOC_CTX *mem_ctx,
10759 struct tevent_context *ev,
10760 struct cli_state *cli,
10762 uint32_t completion_filter,
10764 bool (*fn)(uint32_t action,
10769 struct tevent_req *req, *subreq;
10770 struct swallow_notify_state *state;
10772 req = tevent_req_create(mem_ctx, &state,
10773 struct swallow_notify_state);
10779 state->fnum = fnum;
10780 state->completion_filter = completion_filter;
10781 state->recursive = recursive;
10783 state->priv = priv;
10785 subreq = cli_notify_send(state, state->ev, state->cli, state->fnum,
10786 0xffff, state->completion_filter,
10788 if (tevent_req_nomem(subreq, req)) {
10789 return tevent_req_post(req, ev);
10791 tevent_req_set_callback(subreq, swallow_notify_done, req);
10795 static void swallow_notify_done(struct tevent_req *subreq)
10797 struct tevent_req *req = tevent_req_callback_data(
10798 subreq, struct tevent_req);
10799 struct swallow_notify_state *state = tevent_req_data(
10800 req, struct swallow_notify_state);
10802 uint32_t i, num_changes;
10803 struct notify_change *changes;
10805 status = cli_notify_recv(subreq, state, &num_changes, &changes);
10806 TALLOC_FREE(subreq);
10807 if (!NT_STATUS_IS_OK(status)) {
10808 DEBUG(10, ("cli_notify_recv returned %s\n",
10809 nt_errstr(status)));
10810 tevent_req_nterror(req, status);
10814 for (i=0; i<num_changes; i++) {
10815 state->fn(changes[i].action, changes[i].name, state->priv);
10817 TALLOC_FREE(changes);
10819 subreq = cli_notify_send(state, state->ev, state->cli, state->fnum,
10820 0xffff, state->completion_filter,
10822 if (tevent_req_nomem(subreq, req)) {
10825 tevent_req_set_callback(subreq, swallow_notify_done, req);
10828 static bool print_notifies(uint32_t action, const char *name, void *priv)
10830 if (DEBUGLEVEL > 5) {
10831 d_printf("%d %s\n", (int)action, name);
10836 static void notify_bench_done(struct tevent_req *req)
10838 int *num_finished = (int *)tevent_req_callback_data_void(req);
10839 *num_finished += 1;
10842 static bool run_notify_bench(int dummy)
10844 const char *dname = "\\notify-bench";
10845 struct tevent_context *ev;
10848 struct tevent_req *req1;
10849 struct tevent_req *req2 = NULL;
10850 int i, num_unc_names;
10851 int num_finished = 0;
10853 printf("starting notify-bench test\n");
10855 if (use_multishare_conn) {
10857 unc_list = file_lines_load(multishare_conn_fname,
10858 &num_unc_names, 0, NULL);
10859 if (!unc_list || num_unc_names <= 0) {
10860 d_printf("Failed to load unc names list from '%s'\n",
10861 multishare_conn_fname);
10864 TALLOC_FREE(unc_list);
10869 ev = samba_tevent_context_init(talloc_tos());
10871 d_printf("tevent_context_init failed\n");
10875 for (i=0; i<num_unc_names; i++) {
10876 struct cli_state *cli;
10879 base_fname = talloc_asprintf(talloc_tos(), "%s\\file%3.3d.",
10881 if (base_fname == NULL) {
10885 if (!torture_open_connection(&cli, i)) {
10889 status = cli_ntcreate(cli, dname, 0,
10890 MAXIMUM_ALLOWED_ACCESS,
10891 0, FILE_SHARE_READ|FILE_SHARE_WRITE|
10893 FILE_OPEN_IF, FILE_DIRECTORY_FILE, 0,
10896 if (!NT_STATUS_IS_OK(status)) {
10897 d_printf("Could not create %s: %s\n", dname,
10898 nt_errstr(status));
10902 req1 = swallow_notify_send(talloc_tos(), ev, cli, dnum,
10903 FILE_NOTIFY_CHANGE_FILE_NAME |
10904 FILE_NOTIFY_CHANGE_DIR_NAME |
10905 FILE_NOTIFY_CHANGE_ATTRIBUTES |
10906 FILE_NOTIFY_CHANGE_LAST_WRITE,
10907 false, print_notifies, NULL);
10908 if (req1 == NULL) {
10909 d_printf("Could not create notify request\n");
10913 req2 = torture_createdels_send(talloc_tos(), ev, cli,
10914 base_fname, 10, torture_numops);
10915 if (req2 == NULL) {
10916 d_printf("Could not create createdels request\n");
10919 TALLOC_FREE(base_fname);
10921 tevent_req_set_callback(req2, notify_bench_done,
10925 while (num_finished < num_unc_names) {
10927 ret = tevent_loop_once(ev);
10929 d_printf("tevent_loop_once failed\n");
10934 if (!tevent_req_poll(req2, ev)) {
10935 d_printf("tevent_req_poll failed\n");
10938 status = torture_createdels_recv(req2);
10939 d_printf("torture_createdels_recv returned %s\n", nt_errstr(status));
10944 static bool run_mangle1(int dummy)
10946 struct cli_state *cli;
10947 const char *fname = "this_is_a_long_fname_to_be_mangled.txt";
10951 time_t change_time, access_time, write_time;
10955 printf("starting mangle1 test\n");
10956 if (!torture_open_connection(&cli, 0)) {
10960 smbXcli_conn_set_sockopt(cli->conn, sockops);
10962 status = cli_ntcreate(cli, fname, 0, GENERIC_ALL_ACCESS|DELETE_ACCESS,
10963 FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
10964 0, 0, &fnum, NULL);
10965 if (!NT_STATUS_IS_OK(status)) {
10966 d_printf("open %s failed: %s\n", fname, nt_errstr(status));
10969 cli_close(cli, fnum);
10971 status = cli_qpathinfo_alt_name(cli, fname, alt_name);
10972 if (!NT_STATUS_IS_OK(status)) {
10973 d_printf("cli_qpathinfo_alt_name failed: %s\n",
10974 nt_errstr(status));
10977 d_printf("alt_name: %s\n", alt_name);
10979 status = cli_openx(cli, alt_name, O_RDONLY, DENY_NONE, &fnum);
10980 if (!NT_STATUS_IS_OK(status)) {
10981 d_printf("cli_openx(%s) failed: %s\n", alt_name,
10982 nt_errstr(status));
10985 cli_close(cli, fnum);
10987 status = cli_qpathinfo1(cli, alt_name, &change_time, &access_time,
10988 &write_time, &size, &attr);
10989 if (!NT_STATUS_IS_OK(status)) {
10990 d_printf("cli_qpathinfo1(%s) failed: %s\n", alt_name,
10991 nt_errstr(status));
10998 static NTSTATUS mangle_illegal_list_shortname_fn(struct file_info *f,
11002 if (f->short_name == NULL) {
11003 return NT_STATUS_OK;
11006 if (strlen(f->short_name) == 0) {
11007 return NT_STATUS_OK;
11010 printf("unexpected shortname: %s\n", f->short_name);
11012 return NT_STATUS_OBJECT_NAME_INVALID;
11015 static NTSTATUS mangle_illegal_list_name_fn(struct file_info *f,
11019 char *name = state;
11021 printf("name: %s\n", f->name);
11022 fstrcpy(name, f->name);
11023 return NT_STATUS_OK;
11026 static bool run_mangle_illegal(int dummy)
11028 struct cli_state *cli = NULL;
11029 struct cli_state *cli_posix = NULL;
11030 const char *fname = "\\MANGLE_ILLEGAL\\this_is_a_long_fname_to_be_mangled.txt";
11031 const char *illegal_fname = "MANGLE_ILLEGAL/foo:bar";
11032 char *mangled_path = NULL;
11038 printf("starting mangle-illegal test\n");
11040 if (!torture_open_connection(&cli, 0)) {
11044 smbXcli_conn_set_sockopt(cli->conn, sockops);
11046 if (!torture_open_connection(&cli_posix, 0)) {
11050 smbXcli_conn_set_sockopt(cli_posix->conn, sockops);
11052 status = torture_setup_unix_extensions(cli_posix);
11053 if (!NT_STATUS_IS_OK(status)) {
11057 cli_rmdir(cli, "\\MANGLE_ILLEGAL");
11058 status = cli_mkdir(cli, "\\MANGLE_ILLEGAL");
11059 if (!NT_STATUS_IS_OK(status)) {
11060 printf("mkdir1 failed : %s\n", nt_errstr(status));
11065 * Create a file with illegal NTFS characters and test that we
11066 * get a usable mangled name
11069 cli_setatr(cli_posix, illegal_fname, 0, 0);
11070 cli_posix_unlink(cli_posix, illegal_fname);
11072 status = cli_posix_open(cli_posix, illegal_fname, O_RDWR|O_CREAT|O_EXCL,
11074 if (!NT_STATUS_IS_OK(status)) {
11075 printf("POSIX create of %s failed (%s)\n",
11076 illegal_fname, nt_errstr(status));
11080 status = cli_close(cli_posix, fnum);
11081 if (!NT_STATUS_IS_OK(status)) {
11082 printf("close failed (%s)\n", nt_errstr(status));
11086 status = cli_list(cli, "\\MANGLE_ILLEGAL\\*", 0, mangle_illegal_list_name_fn, &name);
11087 if (!NT_STATUS_IS_OK(status)) {
11088 d_printf("cli_list failed: %s\n", nt_errstr(status));
11092 mangled_path = talloc_asprintf(talloc_tos(), "\\MANGLE_ILLEGAL\\%s", name);
11093 if (mangled_path == NULL) {
11097 status = cli_openx(cli, mangled_path, O_RDONLY, DENY_NONE, &fnum);
11098 if (!NT_STATUS_IS_OK(status)) {
11099 d_printf("cli_openx(%s) failed: %s\n", mangled_path, nt_errstr(status));
11100 TALLOC_FREE(mangled_path);
11103 TALLOC_FREE(mangled_path);
11104 cli_close(cli, fnum);
11106 cli_setatr(cli_posix, illegal_fname, 0, 0);
11107 cli_posix_unlink(cli_posix, illegal_fname);
11110 * Create a file with a long name and check that we got *no* short name.
11113 status = cli_ntcreate(cli, fname, 0, GENERIC_ALL_ACCESS|DELETE_ACCESS,
11114 FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
11115 0, 0, &fnum, NULL);
11116 if (!NT_STATUS_IS_OK(status)) {
11117 d_printf("open %s failed: %s\n", fname, nt_errstr(status));
11120 cli_close(cli, fnum);
11122 status = cli_list(cli, fname, 0, mangle_illegal_list_shortname_fn, &alt_name);
11123 if (!NT_STATUS_IS_OK(status)) {
11124 d_printf("cli_list failed\n");
11128 cli_unlink(cli, fname, 0);
11129 cli_rmdir(cli, "\\MANGLE_ILLEGAL");
11131 if (!torture_close_connection(cli_posix)) {
11135 if (!torture_close_connection(cli)) {
11142 static size_t null_source(uint8_t *buf, size_t n, void *priv)
11144 size_t *to_pull = (size_t *)priv;
11145 size_t thistime = *to_pull;
11147 thistime = MIN(thistime, n);
11148 if (thistime == 0) {
11152 memset(buf, 0, thistime);
11153 *to_pull -= thistime;
11157 static bool run_windows_write(int dummy)
11159 struct cli_state *cli1;
11163 const char *fname = "\\writetest.txt";
11164 struct timeval start_time;
11169 printf("starting windows_write test\n");
11170 if (!torture_open_connection(&cli1, 0)) {
11174 status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
11175 if (!NT_STATUS_IS_OK(status)) {
11176 printf("open failed (%s)\n", nt_errstr(status));
11180 smbXcli_conn_set_sockopt(cli1->conn, sockops);
11182 start_time = timeval_current();
11184 for (i=0; i<torture_numops; i++) {
11186 off_t start = i * torture_blocksize;
11187 size_t to_pull = torture_blocksize - 1;
11189 status = cli_writeall(cli1, fnum, 0, &c,
11190 start + torture_blocksize - 1, 1, NULL);
11191 if (!NT_STATUS_IS_OK(status)) {
11192 printf("cli_write failed: %s\n", nt_errstr(status));
11196 status = cli_push(cli1, fnum, 0, i * torture_blocksize, torture_blocksize,
11197 null_source, &to_pull);
11198 if (!NT_STATUS_IS_OK(status)) {
11199 printf("cli_push returned: %s\n", nt_errstr(status));
11204 seconds = timeval_elapsed(&start_time);
11205 kbytes = (double)torture_blocksize * torture_numops;
11208 printf("Wrote %d kbytes in %.2f seconds: %d kb/sec\n", (int)kbytes,
11209 (double)seconds, (int)(kbytes/seconds));
11213 cli_close(cli1, fnum);
11214 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
11215 torture_close_connection(cli1);
11219 static size_t calc_expected_return(struct cli_state *cli, size_t len_requested)
11221 size_t max_pdu = 0x1FFFF;
11223 if (cli->server_posix_capabilities & CIFS_UNIX_LARGE_READ_CAP) {
11224 max_pdu = 0xFFFFFF;
11227 if (smb1cli_conn_signing_is_active(cli->conn)) {
11231 if (smb1cli_conn_encryption_on(cli->conn)) {
11232 max_pdu = CLI_BUFFER_SIZE;
11235 if ((len_requested & 0xFFFF0000) == 0xFFFF0000) {
11236 len_requested &= 0xFFFF;
11239 return MIN(len_requested,
11240 max_pdu - (MIN_SMB_SIZE + VWV(12) + 1 /* padding byte */));
11243 static bool check_read_call(struct cli_state *cli,
11246 size_t len_requested)
11249 struct tevent_req *subreq = NULL;
11250 ssize_t len_read = 0;
11251 size_t len_expected = 0;
11252 struct tevent_context *ev = NULL;
11254 ev = samba_tevent_context_init(talloc_tos());
11259 subreq = cli_read_andx_send(talloc_tos(),
11266 if (!tevent_req_poll_ntstatus(subreq, ev, &status)) {
11270 status = cli_read_andx_recv(subreq, &len_read, &buf);
11271 if (!NT_STATUS_IS_OK(status)) {
11272 d_printf("cli_read_andx_recv failed: %s\n", nt_errstr(status));
11276 TALLOC_FREE(subreq);
11279 len_expected = calc_expected_return(cli, len_requested);
11281 if (len_expected > 0x10000 && len_read == 0x10000) {
11282 /* Windows servers only return a max of 0x10000,
11283 doesn't matter if you set CAP_LARGE_READX in
11284 the client sessionsetupX call or not. */
11285 d_printf("Windows server - returned 0x10000 on a read of 0x%x\n",
11286 (unsigned int)len_requested);
11287 } else if (len_read != len_expected) {
11288 d_printf("read of 0x%x failed: got 0x%x, expected 0x%x\n",
11289 (unsigned int)len_requested,
11290 (unsigned int)len_read,
11291 (unsigned int)len_expected);
11294 d_printf("Correct read reply.\n");
11300 /* Test large readX variants. */
11301 static bool large_readx_tests(struct cli_state *cli,
11305 /* A read of 0xFFFF0001 should *always* return 1 byte. */
11306 if (check_read_call(cli, fnum, buf, 0xFFFF0001) == false) {
11309 /* A read of 0x10000 should return 0x10000 bytes. */
11310 if (check_read_call(cli, fnum, buf, 0x10000) == false) {
11313 /* A read of 0x10000 should return 0x10001 bytes. */
11314 if (check_read_call(cli, fnum, buf, 0x10001) == false) {
11317 /* A read of 0x1FFFF - (MIN_SMB_SIZE + VWV(12) should return
11318 the requested number of bytes. */
11319 if (check_read_call(cli, fnum, buf, 0x1FFFF - (MIN_SMB_SIZE + VWV(12))) == false) {
11322 /* A read of 1MB should return 1MB bytes (on Samba). */
11323 if (check_read_call(cli, fnum, buf, 0x100000) == false) {
11327 if (check_read_call(cli, fnum, buf, 0x20001) == false) {
11330 if (check_read_call(cli, fnum, buf, 0x22000001) == false) {
11333 if (check_read_call(cli, fnum, buf, 0xFFFE0001) == false) {
11339 static bool run_large_readx(int dummy)
11341 uint8_t *buf = NULL;
11342 struct cli_state *cli1 = NULL;
11343 struct cli_state *cli2 = NULL;
11344 bool correct = false;
11345 const char *fname = "\\large_readx.dat";
11347 uint16_t fnum1 = UINT16_MAX;
11348 uint32_t normal_caps = 0;
11349 size_t file_size = 20*1024*1024;
11350 TALLOC_CTX *frame = talloc_stackframe();
11354 enum smb_signing_setting signing_setting;
11355 enum protocol_types protocol;
11359 .signing_setting = SMB_SIGNING_IF_REQUIRED,
11360 .protocol = PROTOCOL_NT1,
11362 .name = "NT1 - SIGNING_REQUIRED",
11363 .signing_setting = SMB_SIGNING_REQUIRED,
11364 .protocol = PROTOCOL_NT1,
11368 printf("starting large_readx test\n");
11370 if (!torture_open_connection(&cli1, 0)) {
11374 normal_caps = smb1cli_conn_capabilities(cli1->conn);
11376 if (!(normal_caps & CAP_LARGE_READX)) {
11377 d_printf("Server doesn't have CAP_LARGE_READX 0x%x\n",
11378 (unsigned int)normal_caps);
11382 /* Create a file of size 4MB. */
11383 status = cli_ntcreate(cli1, fname, 0, GENERIC_ALL_ACCESS,
11384 FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
11385 0, 0, &fnum1, NULL);
11387 if (!NT_STATUS_IS_OK(status)) {
11388 d_printf("open %s failed: %s\n", fname, nt_errstr(status));
11392 /* Write file_size bytes. */
11393 buf = talloc_zero_array(frame, uint8_t, file_size);
11398 status = cli_writeall(cli1,
11405 if (!NT_STATUS_IS_OK(status)) {
11406 d_printf("cli_writeall failed: %s\n", nt_errstr(status));
11410 status = cli_close(cli1, fnum1);
11411 if (!NT_STATUS_IS_OK(status)) {
11412 d_printf("cli_close failed: %s\n", nt_errstr(status));
11416 fnum1 = UINT16_MAX;
11418 for (i=0; i < ARRAY_SIZE(runs); i++) {
11419 enum smb_signing_setting saved_signing_setting = signing_state;
11420 uint16_t fnum2 = -1;
11423 (runs[i].signing_setting == SMB_SIGNING_REQUIRED))
11425 d_printf("skip[%u] - %s\n", (unsigned)i, runs[i].name);
11429 d_printf("run[%u] - %s\n", (unsigned)i, runs[i].name);
11431 signing_state = runs[i].signing_setting;
11432 cli2 = open_nbt_connection();
11433 signing_state = saved_signing_setting;
11434 if (cli2 == NULL) {
11438 status = smbXcli_negprot(cli2->conn,
11442 if (!NT_STATUS_IS_OK(status)) {
11446 status = cli_session_setup_creds(cli2, torture_creds);
11447 if (!NT_STATUS_IS_OK(status)) {
11451 status = cli_tree_connect(cli2,
11455 if (!NT_STATUS_IS_OK(status)) {
11459 cli_set_timeout(cli2, 120000); /* set a really long timeout (2 minutes) */
11461 normal_caps = smb1cli_conn_capabilities(cli2->conn);
11463 if (!(normal_caps & CAP_LARGE_READX)) {
11464 d_printf("Server doesn't have CAP_LARGE_READX 0x%x\n",
11465 (unsigned int)normal_caps);
11470 if (force_cli_encryption(cli2, share) == false) {
11473 } else if (SERVER_HAS_UNIX_CIFS(cli2)) {
11474 uint16_t major, minor;
11475 uint32_t caplow, caphigh;
11477 status = cli_unix_extensions_version(cli2,
11479 &caplow, &caphigh);
11480 if (!NT_STATUS_IS_OK(status)) {
11485 status = cli_ntcreate(cli2, fname, 0, FILE_READ_DATA,
11486 FILE_ATTRIBUTE_NORMAL, 0, FILE_OPEN,
11487 0, 0, &fnum2, NULL);
11488 if (!NT_STATUS_IS_OK(status)) {
11489 d_printf("Second open %s failed: %s\n", fname, nt_errstr(status));
11493 /* All reads must return less than file_size bytes. */
11494 if (!large_readx_tests(cli2, fnum2, buf)) {
11498 status = cli_close(cli2, fnum2);
11499 if (!NT_STATUS_IS_OK(status)) {
11500 d_printf("cli_close failed: %s\n", nt_errstr(status));
11505 if (!torture_close_connection(cli2)) {
11512 printf("Success on large_readx test\n");
11517 if (!torture_close_connection(cli2)) {
11523 if (fnum1 != UINT16_MAX) {
11524 status = cli_close(cli1, fnum1);
11525 if (!NT_STATUS_IS_OK(status)) {
11526 d_printf("cli_close failed: %s\n", nt_errstr(status));
11528 fnum1 = UINT16_MAX;
11531 status = cli_unlink(cli1, fname,
11532 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
11533 if (!NT_STATUS_IS_OK(status)) {
11534 printf("unlink failed (%s)\n", nt_errstr(status));
11537 if (!torture_close_connection(cli1)) {
11542 TALLOC_FREE(frame);
11544 printf("finished large_readx test\n");
11548 static NTSTATUS msdfs_attribute_list_fn(struct file_info *finfo,
11550 void *private_data)
11552 uint32_t *p_attr = (uint32_t *)private_data;
11554 if (strequal(finfo->name, test_filename)) {
11555 *p_attr = finfo->attr;
11558 return NT_STATUS_OK;
11561 static bool run_msdfs_attribute(int dummy)
11563 static struct cli_state *cli;
11564 bool correct = false;
11568 printf("Starting MSDFS-ATTRIBUTE test\n");
11570 if (test_filename == NULL || test_filename[0] == '\0') {
11571 printf("MSDFS-ATTRIBUTE test "
11572 "needs -f filename-of-msdfs-link\n");
11577 * NB. We use torture_open_connection_flags() not
11578 * torture_open_connection() as the latter forces
11581 if (!torture_open_connection_flags(&cli, 0, 0)) {
11585 smbXcli_conn_set_sockopt(cli->conn, sockops);
11587 status = cli_list(cli,
11589 FILE_ATTRIBUTE_DIRECTORY,
11590 msdfs_attribute_list_fn,
11593 if (!NT_STATUS_IS_OK(status)) {
11594 printf("cli_list failed with %s\n",
11595 nt_errstr(status));
11598 if ((attr & FILE_ATTRIBUTE_REPARSE_POINT) == 0) {
11599 printf("file %s should have "
11600 "FILE_ATTRIBUTE_REPARSE_POINT set. attr = 0x%x\n",
11602 (unsigned int)attr);
11606 if ((attr & FILE_ATTRIBUTE_DIRECTORY) == 0) {
11607 printf("file %s should have "
11608 "FILE_ATTRIBUTE_DIRECTORY set. attr = 0x%x\n",
11610 (unsigned int)attr);
11618 torture_close_connection(cli);
11622 static bool run_cli_echo(int dummy)
11624 struct cli_state *cli;
11627 printf("starting cli_echo test\n");
11628 if (!torture_open_connection(&cli, 0)) {
11631 smbXcli_conn_set_sockopt(cli->conn, sockops);
11633 status = cli_echo(cli, 5, data_blob_const("hello", 5));
11635 d_printf("cli_echo returned %s\n", nt_errstr(status));
11637 torture_close_connection(cli);
11638 return NT_STATUS_IS_OK(status);
11641 static int splice_status(off_t written, void *priv)
11646 static bool run_cli_splice(int dummy)
11648 uint8_t *buf = NULL;
11649 struct cli_state *cli1 = NULL;
11650 bool correct = false;
11651 const char *fname_src = "\\splice_src.dat";
11652 const char *fname_dst = "\\splice_dst.dat";
11654 uint16_t fnum1 = UINT16_MAX;
11655 uint16_t fnum2 = UINT16_MAX;
11656 size_t file_size = 2*1024*1024;
11657 size_t splice_size = 1*1024*1024 + 713;
11658 uint8_t digest1[16], digest2[16];
11661 TALLOC_CTX *frame = talloc_stackframe();
11663 printf("starting cli_splice test\n");
11665 if (!torture_open_connection(&cli1, 0)) {
11669 cli_unlink(cli1, fname_src,
11670 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
11671 cli_unlink(cli1, fname_dst,
11672 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
11674 /* Create a file */
11675 status = cli_ntcreate(cli1, fname_src, 0, GENERIC_ALL_ACCESS,
11676 FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
11677 0, 0, &fnum1, NULL);
11679 if (!NT_STATUS_IS_OK(status)) {
11680 d_printf("open %s failed: %s\n", fname_src, nt_errstr(status));
11684 /* Write file_size bytes - must be bigger than splice_size. */
11685 buf = talloc_zero_array(frame, uint8_t, file_size);
11687 d_printf("talloc_fail\n");
11691 /* Fill it with random numbers. */
11692 generate_random_buffer(buf, file_size);
11694 /* MD5 the first 1MB + 713 bytes. */
11695 gnutls_hash_fast(GNUTLS_DIG_MD5,
11700 status = cli_writeall(cli1,
11707 if (!NT_STATUS_IS_OK(status)) {
11708 d_printf("cli_writeall failed: %s\n", nt_errstr(status));
11712 status = cli_ntcreate(cli1, fname_dst, 0, GENERIC_ALL_ACCESS,
11713 FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
11714 0, 0, &fnum2, NULL);
11716 if (!NT_STATUS_IS_OK(status)) {
11717 d_printf("open %s failed: %s\n", fname_dst, nt_errstr(status));
11721 /* Now splice 1MB + 713 bytes. */
11722 status = cli_splice(cli1,
11733 if (!NT_STATUS_IS_OK(status)) {
11734 d_printf("cli_splice failed: %s\n", nt_errstr(status));
11738 /* Clear the old buffer. */
11739 memset(buf, '\0', file_size);
11741 /* Read the new file. */
11742 status = cli_read(cli1, fnum2, (char *)buf, 0, splice_size, &nread);
11743 if (!NT_STATUS_IS_OK(status)) {
11744 d_printf("cli_read failed: %s\n", nt_errstr(status));
11747 if (nread != splice_size) {
11748 d_printf("bad read of 0x%x, should be 0x%x\n",
11749 (unsigned int)nread,
11750 (unsigned int)splice_size);
11754 /* MD5 the first 1MB + 713 bytes. */
11755 gnutls_hash_fast(GNUTLS_DIG_MD5,
11760 /* Must be the same. */
11761 if (memcmp(digest1, digest2, 16) != 0) {
11762 d_printf("bad MD5 compare\n");
11767 printf("Success on cli_splice test\n");
11772 if (fnum1 != UINT16_MAX) {
11773 cli_close(cli1, fnum1);
11775 if (fnum2 != UINT16_MAX) {
11776 cli_close(cli1, fnum2);
11779 cli_unlink(cli1, fname_src,
11780 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
11781 cli_unlink(cli1, fname_dst,
11782 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
11784 if (!torture_close_connection(cli1)) {
11789 TALLOC_FREE(frame);
11793 static bool run_uid_regression_test(int dummy)
11795 static struct cli_state *cli;
11798 bool correct = True;
11799 struct smbXcli_tcon *tcon_copy = NULL;
11802 printf("starting uid regression test\n");
11804 if (!torture_open_connection(&cli, 0)) {
11808 smbXcli_conn_set_sockopt(cli->conn, sockops);
11810 /* Ok - now save then logoff our current user. */
11811 old_vuid = cli_state_get_uid(cli);
11813 status = cli_ulogoff(cli);
11814 if (!NT_STATUS_IS_OK(status)) {
11815 d_printf("(%s) cli_ulogoff failed: %s\n",
11816 __location__, nt_errstr(status));
11821 cli_state_set_uid(cli, old_vuid);
11823 /* Try an operation. */
11824 status = cli_mkdir(cli, "\\uid_reg_test");
11825 if (NT_STATUS_IS_OK(status)) {
11826 d_printf("(%s) cli_mkdir succeeded\n",
11831 /* Should be bad uid. */
11832 if (!check_error(__LINE__, status, ERRSRV, ERRbaduid,
11833 NT_STATUS_USER_SESSION_DELETED)) {
11839 old_cnum = cli_state_get_tid(cli);
11841 * This is an SMB1-only test.
11842 * Copy the tcon, not "save/restore".
11844 * In SMB1 the cli_tdis() below frees
11845 * cli->smb1.tcon so we need a copy
11846 * of the struct to put back for the
11847 * second tdis call with invalid vuid.
11849 * This is a test-only hack. Real client code
11850 * uses cli_state_save_tcon()/cli_state_restore_tcon().
11852 tcon_copy = smbXcli_tcon_copy(cli, cli->smb1.tcon);
11853 if (tcon_copy == NULL) {
11858 /* Now try a SMBtdis with the invalid vuid set to zero. */
11859 cli_state_set_uid(cli, 0);
11861 /* This should succeed. */
11862 status = cli_tdis(cli);
11864 if (NT_STATUS_IS_OK(status)) {
11865 d_printf("First tdis with invalid vuid should succeed.\n");
11867 d_printf("First tdis failed (%s)\n", nt_errstr(status));
11869 cli->smb1.tcon = tcon_copy;
11873 cli->smb1.tcon = tcon_copy;
11874 cli_state_set_uid(cli, old_vuid);
11875 cli_state_set_tid(cli, old_cnum);
11877 /* This should fail. */
11878 status = cli_tdis(cli);
11879 if (NT_STATUS_IS_OK(status)) {
11880 d_printf("Second tdis with invalid vuid should fail - succeeded instead !.\n");
11884 /* Should be bad tid. */
11885 if (!check_error(__LINE__, status, ERRSRV, ERRinvnid,
11886 NT_STATUS_NETWORK_NAME_DELETED)) {
11892 cli_rmdir(cli, "\\uid_reg_test");
11901 static const char *illegal_chars = "*\\/?<>|\":";
11902 static char force_shortname_chars[] = " +,.[];=\177";
11904 static NTSTATUS shortname_del_fn(struct file_info *finfo,
11905 const char *mask, void *state)
11907 struct cli_state *pcli = (struct cli_state *)state;
11909 NTSTATUS status = NT_STATUS_OK;
11911 slprintf(fname, sizeof(fname), "\\shortname\\%s", finfo->name);
11913 if (strcmp(finfo->name, ".") == 0 || strcmp(finfo->name, "..") == 0)
11914 return NT_STATUS_OK;
11916 if (finfo->attr & FILE_ATTRIBUTE_DIRECTORY) {
11917 status = cli_rmdir(pcli, fname);
11918 if (!NT_STATUS_IS_OK(status)) {
11919 printf("del_fn: failed to rmdir %s\n,", fname );
11922 status = cli_unlink(pcli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
11923 if (!NT_STATUS_IS_OK(status)) {
11924 printf("del_fn: failed to unlink %s\n,", fname );
11936 static NTSTATUS shortname_list_fn(struct file_info *finfo,
11937 const char *name, void *state)
11939 struct sn_state *s = (struct sn_state *)state;
11943 printf("shortname list: i = %d, name = |%s|, shortname = |%s|\n",
11944 i, finfo->name, finfo->short_name);
11947 if (strchr(force_shortname_chars, i)) {
11948 if (!finfo->short_name) {
11949 /* Shortname not created when it should be. */
11950 d_printf("(%s) ERROR: Shortname was not created for file %s containing %d\n",
11951 __location__, finfo->name, i);
11954 } else if (finfo->short_name){
11955 /* Shortname created when it should not be. */
11956 d_printf("(%s) ERROR: Shortname %s was created for file %s\n",
11957 __location__, finfo->short_name, finfo->name);
11961 return NT_STATUS_OK;
11964 static bool run_shortname_test(int dummy)
11966 static struct cli_state *cli;
11967 bool correct = True;
11973 printf("starting shortname test\n");
11975 if (!torture_open_connection(&cli, 0)) {
11979 smbXcli_conn_set_sockopt(cli->conn, sockops);
11981 cli_list(cli, "\\shortname\\*", 0, shortname_del_fn, cli);
11982 cli_list(cli, "\\shortname\\*", FILE_ATTRIBUTE_DIRECTORY, shortname_del_fn, cli);
11983 cli_rmdir(cli, "\\shortname");
11985 status = cli_mkdir(cli, "\\shortname");
11986 if (!NT_STATUS_IS_OK(status)) {
11987 d_printf("(%s) cli_mkdir of \\shortname failed: %s\n",
11988 __location__, nt_errstr(status));
11993 if (strlcpy(fname, "\\shortname\\", sizeof(fname)) >= sizeof(fname)) {
11997 if (strlcat(fname, "test .txt", sizeof(fname)) >= sizeof(fname)) {
12004 for (i = 32; i < 128; i++) {
12005 uint16_t fnum = (uint16_t)-1;
12009 if (strchr(illegal_chars, i)) {
12014 status = cli_ntcreate(cli, fname, 0, GENERIC_ALL_ACCESS, FILE_ATTRIBUTE_NORMAL,
12015 FILE_SHARE_READ|FILE_SHARE_WRITE,
12016 FILE_OVERWRITE_IF, 0, 0, &fnum, NULL);
12017 if (!NT_STATUS_IS_OK(status)) {
12018 d_printf("(%s) cli_nt_create of %s failed: %s\n",
12019 __location__, fname, nt_errstr(status));
12023 cli_close(cli, fnum);
12026 status = cli_list(cli, "\\shortname\\test*.*", 0,
12027 shortname_list_fn, &s);
12028 if (s.matched != 1) {
12029 d_printf("(%s) failed to list %s: %s\n",
12030 __location__, fname, nt_errstr(status));
12035 status = cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
12036 if (!NT_STATUS_IS_OK(status)) {
12037 d_printf("(%s) failed to delete %s: %s\n",
12038 __location__, fname, nt_errstr(status));
12051 cli_list(cli, "\\shortname\\*", 0, shortname_del_fn, cli);
12052 cli_list(cli, "\\shortname\\*", FILE_ATTRIBUTE_DIRECTORY, shortname_del_fn, cli);
12053 cli_rmdir(cli, "\\shortname");
12054 torture_close_connection(cli);
12058 TLDAPRC callback_code;
12060 static void pagedsearch_cb(struct tevent_req *req)
12063 struct tldap_message *msg;
12066 rc = tldap_search_paged_recv(req, talloc_tos(), &msg);
12067 if (!TLDAP_RC_IS_SUCCESS(rc)) {
12068 d_printf("tldap_search_paged_recv failed: %s\n",
12069 tldap_rc2string(rc));
12070 callback_code = rc;
12073 if (tldap_msg_type(msg) != TLDAP_RES_SEARCH_ENTRY) {
12077 if (!tldap_entry_dn(msg, &dn)) {
12078 d_printf("tldap_entry_dn failed\n");
12081 d_printf("%s\n", dn);
12085 enum tldap_extended_val {
12092 * Construct an extended dn control with either no value, 0 or 1
12094 * No value and 0 are equivalent (non-hyphenated GUID)
12095 * 1 has the hyphenated GUID
12097 static struct tldap_control *
12098 tldap_build_extended_control(enum tldap_extended_val val)
12100 struct tldap_control empty_control;
12101 struct asn1_data *data;
12103 ZERO_STRUCT(empty_control);
12105 if (val != EXTENDED_NONE) {
12106 data = asn1_init(talloc_tos(), ASN1_MAX_TREE_DEPTH);
12112 if (!asn1_push_tag(data, ASN1_SEQUENCE(0))) {
12116 if (!asn1_write_Integer(data, (int)val)) {
12120 if (!asn1_pop_tag(data)) {
12124 if (!asn1_blob(data, &empty_control.value)) {
12129 empty_control.oid = "1.2.840.113556.1.4.529";
12130 empty_control.critical = true;
12132 return tldap_add_control(talloc_tos(), NULL, 0, &empty_control);
12136 static bool tldap_test_dn_guid_format(struct tldap_context *ld, const char *basedn,
12137 enum tldap_extended_val control_val)
12139 struct tldap_control *control = tldap_build_extended_control(control_val);
12141 struct tldap_message **msg;
12144 rc = tldap_search(ld, basedn, TLDAP_SCOPE_BASE,
12145 "(objectClass=*)", NULL, 0, 0,
12147 0, 0, 0, 0, talloc_tos(), &msg);
12148 if (!TLDAP_RC_IS_SUCCESS(rc)) {
12149 d_printf("tldap_search for domain DN failed: %s\n",
12150 tldap_errstr(talloc_tos(), ld, rc));
12154 if (!tldap_entry_dn(msg[0], &dn)) {
12155 d_printf("tldap_search domain DN fetch failed: %s\n",
12156 tldap_errstr(talloc_tos(), ld, rc));
12160 d_printf("%s\n", dn);
12163 uint32_t time_mid, time_hi_and_version;
12164 uint32_t clock_seq[2];
12168 switch (control_val) {
12169 case EXTENDED_NONE:
12170 case EXTENDED_ZERO:
12172 * When reading GUIDs with hyphens, scanf will treat
12173 * hyphen as a hex character (and counts as part of the
12174 * width). This creates leftover GUID string which we
12175 * check will for with 'next' and closing '>'.
12177 if (12 == sscanf(dn, "<GUID=%08x%04x%04x%02x%02x%02x%02x%02x%02x%02x%02x>%c",
12178 &time_low, &time_mid,
12179 &time_hi_and_version, &clock_seq[0],
12180 &clock_seq[1], &node[0], &node[1],
12181 &node[2], &node[3], &node[4],
12182 &node[5], &next)) {
12183 /* This GUID is good */
12185 d_printf("GUID format in control (no hyphens) doesn't match output\n");
12191 if (12 == sscanf(dn,
12192 "<GUID=%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x>%c",
12193 &time_low, &time_mid,
12194 &time_hi_and_version, &clock_seq[0],
12195 &clock_seq[1], &node[0], &node[1],
12196 &node[2], &node[3], &node[4],
12197 &node[5], &next)) {
12198 /* This GUID is good */
12200 d_printf("GUID format in control (with hyphens) doesn't match output\n");
12213 static bool run_tldap(int dummy)
12215 struct tldap_context *ld;
12219 struct sockaddr_storage addr;
12220 struct tevent_context *ev;
12221 struct tevent_req *req;
12223 const char *filter;
12225 if (!resolve_name(host, &addr, 0, false)) {
12226 d_printf("could not find host %s\n", host);
12229 status = open_socket_out(&addr, 389, 9999, &fd);
12230 if (!NT_STATUS_IS_OK(status)) {
12231 d_printf("open_socket_out failed: %s\n", nt_errstr(status));
12235 ld = tldap_context_create(talloc_tos(), fd);
12238 d_printf("tldap_context_create failed\n");
12242 rc = tldap_fetch_rootdse(ld);
12243 if (!TLDAP_RC_IS_SUCCESS(rc)) {
12244 d_printf("tldap_fetch_rootdse failed: %s\n",
12245 tldap_errstr(talloc_tos(), ld, rc));
12249 basedn = tldap_talloc_single_attribute(
12250 tldap_rootdse(ld), "defaultNamingContext", talloc_tos());
12251 if (basedn == NULL) {
12252 d_printf("no defaultNamingContext\n");
12255 d_printf("defaultNamingContext: %s\n", basedn);
12257 ev = samba_tevent_context_init(talloc_tos());
12259 d_printf("tevent_context_init failed\n");
12263 rc = tldap_gensec_bind(ld, torture_creds, "ldap", host, NULL,
12264 loadparm_init_s3(talloc_tos(),
12265 loadparm_s3_helpers()),
12266 GENSEC_FEATURE_SIGN | GENSEC_FEATURE_SEAL);
12268 if (!TLDAP_RC_IS_SUCCESS(rc)) {
12269 d_printf("tldap_gensec_bind failed\n");
12273 callback_code = TLDAP_SUCCESS;
12275 req = tldap_search_paged_send(talloc_tos(), ev, ld, basedn,
12276 TLDAP_SCOPE_SUB, "(objectclass=*)",
12278 NULL, 0, NULL, 0, 0, 0, 0, 5);
12280 d_printf("tldap_search_paged_send failed\n");
12283 tevent_req_set_callback(req, pagedsearch_cb, NULL);
12285 tevent_req_poll(req, ev);
12289 rc = callback_code;
12291 if (!TLDAP_RC_IS_SUCCESS(rc)) {
12292 d_printf("tldap_search with paging failed: %s\n",
12293 tldap_errstr(talloc_tos(), ld, rc));
12297 /* test search filters against rootDSE */
12298 filter = "(&(|(name=samba)(nextRid<=10000000)(usnChanged>=10)(samba~=ambas)(!(name=s*m*a)))"
12299 "(|(name:=samba)(name:dn:2.5.13.5:=samba)(:dn:2.5.13.5:=samba)(!(name=*samba))))";
12301 rc = tldap_search(ld, "", TLDAP_SCOPE_BASE, filter,
12302 NULL, 0, 0, NULL, 0, NULL, 0, 0, 0, 0,
12303 talloc_tos(), NULL);
12304 if (!TLDAP_RC_IS_SUCCESS(rc)) {
12305 d_printf("tldap_search with complex filter failed: %s\n",
12306 tldap_errstr(talloc_tos(), ld, rc));
12311 * Tests to check for regression of:
12313 * https://bugzilla.samba.org/show_bug.cgi?id=14029
12315 * TLDAP used here to pick apart the original string DN (with GUID)
12317 if (!tldap_test_dn_guid_format(ld, basedn, EXTENDED_NONE)) {
12318 d_printf("tldap_search with extended dn (no val) failed: %s\n",
12319 tldap_errstr(talloc_tos(), ld, rc));
12322 if (!tldap_test_dn_guid_format(ld, basedn, EXTENDED_ZERO)) {
12323 d_printf("tldap_search with extended dn (0) failed: %s\n",
12324 tldap_errstr(talloc_tos(), ld, rc));
12327 if (!tldap_test_dn_guid_format(ld, basedn, EXTENDED_ONE)) {
12328 d_printf("tldap_search with extended dn (1) failed: %s\n",
12329 tldap_errstr(talloc_tos(), ld, rc));
12337 /* Torture test to ensure no regression of :
12338 https://bugzilla.samba.org/show_bug.cgi?id=7084
12341 static bool run_dir_createtime(int dummy)
12343 struct cli_state *cli;
12344 const char *dname = "\\testdir_createtime";
12345 const char *fname = "\\testdir_createtime\\testfile";
12347 struct timespec create_time;
12348 struct timespec create_time1;
12353 if (!torture_open_connection(&cli, 0)) {
12357 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
12358 /* Ensure ino is zero, SMB2 gets a real one. */
12361 /* Ensure ino is -1, SMB1 never gets a real one. */
12362 ino = (uint64_t)-1;
12365 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
12366 cli_rmdir(cli, dname);
12368 status = cli_mkdir(cli, dname);
12369 if (!NT_STATUS_IS_OK(status)) {
12370 printf("mkdir failed: %s\n", nt_errstr(status));
12374 status = cli_qpathinfo2(cli, dname, &create_time, NULL, NULL, NULL,
12376 if (!NT_STATUS_IS_OK(status)) {
12377 printf("cli_qpathinfo2 returned %s\n",
12378 nt_errstr(status));
12382 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
12383 /* SMB2 should always return an inode. */
12385 printf("SMB2 bad inode (0)\n");
12389 /* SMB1 must always return zero here. */
12391 printf("SMB1 bad inode (!0)\n");
12396 /* Sleep 3 seconds, then create a file. */
12399 status = cli_openx(cli, fname, O_RDWR | O_CREAT | O_EXCL,
12401 if (!NT_STATUS_IS_OK(status)) {
12402 printf("cli_openx failed: %s\n", nt_errstr(status));
12406 status = cli_qpathinfo2(cli, dname, &create_time1, NULL, NULL, NULL,
12408 if (!NT_STATUS_IS_OK(status)) {
12409 printf("cli_qpathinfo2 (2) returned %s\n",
12410 nt_errstr(status));
12414 if (timespec_compare(&create_time1, &create_time)) {
12415 printf("run_dir_createtime: create time was updated (error)\n");
12417 printf("run_dir_createtime: create time was not updated (correct)\n");
12423 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
12424 cli_rmdir(cli, dname);
12425 if (!torture_close_connection(cli)) {
12432 static bool run_streamerror(int dummy)
12434 struct cli_state *cli;
12435 const char *dname = "\\testdir_streamerror";
12436 const char *streamname =
12437 "testdir_streamerror:{4c8cc155-6c1e-11d1-8e41-00c04fb9386d}:$DATA";
12439 time_t change_time, access_time, write_time;
12445 if (!torture_open_connection(&cli, 0)) {
12449 torture_deltree(cli, dname);
12451 status = cli_mkdir(cli, dname);
12452 if (!NT_STATUS_IS_OK(status)) {
12453 printf("mkdir failed: %s\n", nt_errstr(status));
12457 status = cli_qpathinfo1(cli, streamname, &change_time, &access_time,
12458 &write_time, &size, &attr);
12459 if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
12460 printf("pathinfo returned %s, expected "
12461 "NT_STATUS_OBJECT_NAME_NOT_FOUND\n",
12462 nt_errstr(status));
12466 status = cli_ntcreate(cli, streamname, 0x16,
12467 FILE_READ_DATA|FILE_READ_EA|
12468 FILE_READ_ATTRIBUTES|READ_CONTROL_ACCESS,
12469 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ,
12470 FILE_OPEN, 0, 0, &fnum, NULL);
12472 if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
12473 printf("ntcreate returned %s, expected "
12474 "NT_STATUS_OBJECT_NAME_NOT_FOUND\n",
12475 nt_errstr(status));
12480 cli_rmdir(cli, dname);
12484 struct pidtest_state {
12490 static void pid_echo_done(struct tevent_req *subreq);
12492 static struct tevent_req *pid_echo_send(TALLOC_CTX *mem_ctx,
12493 struct tevent_context *ev,
12494 struct cli_state *cli)
12496 struct tevent_req *req, *subreq;
12497 struct pidtest_state *state;
12499 req = tevent_req_create(mem_ctx, &state, struct pidtest_state);
12504 SSVAL(state->vwv, 0, 1);
12505 state->data = data_blob_const("hello", 5);
12507 subreq = smb1cli_req_send(state,
12511 0, 0, /* *_flags */
12512 0, 0, /* *_flags2 */
12514 0xDEADBEEF, /* pid */
12516 NULL, /* session */
12517 ARRAY_SIZE(state->vwv), state->vwv,
12518 state->data.length, state->data.data);
12520 if (tevent_req_nomem(subreq, req)) {
12521 return tevent_req_post(req, ev);
12523 tevent_req_set_callback(subreq, pid_echo_done, req);
12527 static void pid_echo_done(struct tevent_req *subreq)
12529 struct tevent_req *req = tevent_req_callback_data(
12530 subreq, struct tevent_req);
12531 struct pidtest_state *state = tevent_req_data(
12532 req, struct pidtest_state);
12534 uint32_t num_bytes;
12535 uint8_t *bytes = NULL;
12536 struct iovec *recv_iov = NULL;
12537 uint8_t *phdr = NULL;
12538 uint16_t pidlow = 0;
12539 uint16_t pidhigh = 0;
12540 struct smb1cli_req_expected_response expected[] = {
12542 .status = NT_STATUS_OK,
12547 status = smb1cli_req_recv(subreq, state,
12552 NULL, /* pvwv_offset */
12555 NULL, /* pbytes_offset */
12557 expected, ARRAY_SIZE(expected));
12559 TALLOC_FREE(subreq);
12561 if (!NT_STATUS_IS_OK(status)) {
12562 tevent_req_nterror(req, status);
12566 if (num_bytes != state->data.length) {
12567 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
12571 if (memcmp(bytes, state->data.data, num_bytes) != 0) {
12572 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
12576 /* Check pid low/high == DEADBEEF */
12577 pidlow = SVAL(phdr, HDR_PID);
12578 if (pidlow != 0xBEEF){
12579 printf("Incorrect pidlow 0x%x, should be 0xBEEF\n",
12580 (unsigned int)pidlow);
12581 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
12584 pidhigh = SVAL(phdr, HDR_PIDHIGH);
12585 if (pidhigh != 0xDEAD){
12586 printf("Incorrect pidhigh 0x%x, should be 0xDEAD\n",
12587 (unsigned int)pidhigh);
12588 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
12592 tevent_req_done(req);
12595 static NTSTATUS pid_echo_recv(struct tevent_req *req)
12597 return tevent_req_simple_recv_ntstatus(req);
12600 static bool run_pidhigh(int dummy)
12602 bool success = false;
12603 struct cli_state *cli = NULL;
12605 struct tevent_context *ev = NULL;
12606 struct tevent_req *req = NULL;
12607 TALLOC_CTX *frame = talloc_stackframe();
12609 printf("starting pid high test\n");
12610 if (!torture_open_connection(&cli, 0)) {
12613 smbXcli_conn_set_sockopt(cli->conn, sockops);
12615 ev = samba_tevent_context_init(frame);
12620 req = pid_echo_send(frame, ev, cli);
12625 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
12629 status = pid_echo_recv(req);
12630 if (NT_STATUS_IS_OK(status)) {
12631 printf("pid high test ok\n");
12637 TALLOC_FREE(frame);
12638 torture_close_connection(cli);
12643 Test Windows open on a bad POSIX symlink.
12645 static bool run_symlink_open_test(int dummy)
12647 static struct cli_state *cli;
12648 const char *fname = "non_existant_file";
12649 const char *sname = "dangling_symlink";
12650 uint16_t fnum = (uint16_t)-1;
12651 bool correct = false;
12653 TALLOC_CTX *frame = NULL;
12655 frame = talloc_stackframe();
12657 printf("Starting Windows bad symlink open test\n");
12659 if (!torture_open_connection(&cli, 0)) {
12660 TALLOC_FREE(frame);
12664 smbXcli_conn_set_sockopt(cli->conn, sockops);
12666 status = torture_setup_unix_extensions(cli);
12667 if (!NT_STATUS_IS_OK(status)) {
12668 TALLOC_FREE(frame);
12672 /* Ensure nothing exists. */
12673 cli_setatr(cli, fname, 0, 0);
12674 cli_posix_unlink(cli, fname);
12675 cli_setatr(cli, sname, 0, 0);
12676 cli_posix_unlink(cli, sname);
12678 /* Create a symlink pointing nowhere. */
12679 status = cli_posix_symlink(cli, fname, sname);
12680 if (!NT_STATUS_IS_OK(status)) {
12681 printf("cli_posix_symlink of %s -> %s failed (%s)\n",
12684 nt_errstr(status));
12688 /* Now ensure that a Windows open doesn't hang. */
12689 status = cli_ntcreate(cli,
12692 FILE_READ_DATA|FILE_WRITE_DATA,
12694 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
12702 * We get either NT_STATUS_OBJECT_NAME_NOT_FOUND or
12703 * NT_STATUS_OBJECT_PATH_NOT_FOUND depending on if
12704 * we use O_NOFOLLOW on the server or not.
12706 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND) ||
12707 NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_PATH_NOT_FOUND))
12711 printf("cli_ntcreate of %s returned %s - should return"
12712 " either (%s) or (%s)\n",
12715 nt_errstr(NT_STATUS_OBJECT_NAME_NOT_FOUND),
12716 nt_errstr(NT_STATUS_OBJECT_PATH_NOT_FOUND));
12724 if (fnum != (uint16_t)-1) {
12725 cli_close(cli, fnum);
12726 fnum = (uint16_t)-1;
12729 cli_setatr(cli, sname, 0, 0);
12730 cli_posix_unlink(cli, sname);
12731 cli_setatr(cli, fname, 0, 0);
12732 cli_posix_unlink(cli, fname);
12734 if (!torture_close_connection(cli)) {
12738 TALLOC_FREE(frame);
12742 static NTSTATUS smb1_wild_mangle_list_fn(struct file_info *finfo,
12746 char **mangled_name_return = (char **)state;
12747 bool is_mangled = strchr(finfo->name, '~');
12750 *mangled_name_return = talloc_strdup(NULL, finfo->name);
12751 if (*mangled_name_return == NULL) {
12752 return NT_STATUS_NO_MEMORY;
12755 return NT_STATUS_OK;
12758 static bool run_smb1_wild_mangle_unlink_test(int dummy)
12760 static struct cli_state *cli_posix = NULL;
12761 static struct cli_state *cli = NULL;
12762 uint16_t fnum = (uint16_t)-1;
12763 bool correct = false;
12764 const char *dname = "smb1_wild_mangle_unlink";
12765 const char *aname = "smb1_wild_mangle_unlink/a";
12766 const char *star_name = "smb1_wild_mangle_unlink/*";
12767 char *windows_unlink_name = NULL;
12768 char *mangled_name = NULL;
12771 printf("Starting SMB1 wild mangle unlink test\n");
12773 /* Open a Windows connection. */
12774 if (!torture_open_connection(&cli, 0)) {
12778 smbXcli_conn_set_sockopt(cli->conn, sockops);
12780 /* Open a POSIX connection. */
12781 if (!torture_open_connection(&cli_posix, 0)) {
12785 smbXcli_conn_set_sockopt(cli_posix->conn, sockops);
12787 status = torture_setup_unix_extensions(cli_posix);
12788 if (!NT_STATUS_IS_OK(status)) {
12789 printf("server doesn't support POSIX\n");
12794 torture_deltree(cli, dname);
12797 * Create two files - 'a' and '*'.
12798 * We need POSIX extensions for this as '*'
12799 * is not a valid Windows name.
12802 status = cli_mkdir(cli, dname);
12803 if (!NT_STATUS_IS_OK(status)) {
12804 printf("cli_mkdir of %s returned %s\n",
12806 nt_errstr(status));
12810 status = cli_posix_open(cli_posix,
12812 O_RDWR|O_CREAT|O_EXCL,
12815 if (!NT_STATUS_IS_OK(status)) {
12816 printf("cli_posix_open (create) of %s returned %s\n",
12818 nt_errstr(status));
12821 status = cli_close(cli_posix, fnum);
12822 if (!NT_STATUS_IS_OK(status)) {
12825 status = cli_posix_open(cli_posix,
12827 O_RDWR|O_CREAT|O_EXCL,
12830 if (!NT_STATUS_IS_OK(status)) {
12831 printf("cli_posix_open (create) of %s returned %s\n",
12833 nt_errstr(status));
12836 status = cli_close(cli_posix, fnum);
12837 if (!NT_STATUS_IS_OK(status)) {
12841 status = cli_list(cli,
12844 smb1_wild_mangle_list_fn,
12846 if (!NT_STATUS_IS_OK(status)) {
12847 printf("cli_list of %s returned %s\n",
12849 nt_errstr(status));
12853 if (mangled_name == NULL) {
12857 printf("mangled_name = %s\n",
12861 * Try a Windows unlink with the mangled name.
12862 * This should *NOT* unlink the 'a' name.
12865 windows_unlink_name = talloc_asprintf(cli_posix,
12870 status = cli_unlink(cli, windows_unlink_name, 0);
12871 if (!NT_STATUS_IS_OK(status)) {
12872 printf("cli_unlink of %s returned %s\n",
12873 windows_unlink_name,
12874 nt_errstr(status));
12878 /* Does 'a' still exist ? */
12879 status = cli_posix_open(cli_posix,
12884 if (!NT_STATUS_IS_OK(status)) {
12885 printf("cli_posix_open O_RNONLY of %s returned %s\n",
12887 nt_errstr(status));
12891 status = cli_close(cli_posix, fnum);
12892 if (!NT_STATUS_IS_OK(status)) {
12900 TALLOC_FREE(windows_unlink_name);
12901 TALLOC_FREE(mangled_name);
12904 torture_deltree(cli, dname);
12905 torture_close_connection(cli);
12908 if (cli_posix != NULL) {
12909 torture_close_connection(cli_posix);
12915 static bool run_smb1_wild_mangle_rename_test(int dummy)
12917 static struct cli_state *cli_posix = NULL;
12918 static struct cli_state *cli = NULL;
12919 uint16_t fnum = (uint16_t)-1;
12920 bool correct = false;
12921 const char *dname = "smb1_wild_mangle_rename";
12922 const char *fooname = "smb1_wild_mangle_rename/foo";
12923 const char *foostar_name = "smb1_wild_mangle_rename/fo*";
12924 const char *wild_name = "smb1_wild_mangle_rename/*";
12925 char *windows_rename_src = NULL;
12926 const char *windows_rename_dst = "smb1_wild_mangle_rename\\bar";
12927 char *mangled_name = NULL;
12930 printf("Starting SMB1 wild mangle rename test\n");
12932 if (!torture_open_connection(&cli_posix, 0)) {
12936 smbXcli_conn_set_sockopt(cli_posix->conn, sockops);
12938 status = torture_setup_unix_extensions(cli_posix);
12939 if (!NT_STATUS_IS_OK(status)) {
12940 printf("server doesn't support POSIX\n");
12944 /* Open a Windows connection. */
12945 if (!torture_open_connection(&cli, 0)) {
12949 smbXcli_conn_set_sockopt(cli->conn, sockops);
12951 /* Ensure we start from fresh. */
12952 torture_deltree(cli, dname);
12955 * Create two files - 'foo' and 'fo*'.
12956 * We need POSIX extensions for this as 'fo*'
12957 * is not a valid Windows name.
12960 status = cli_posix_mkdir(cli_posix, dname, 0770);
12961 if (!NT_STATUS_IS_OK(status)) {
12962 printf("cli_posix_mkdir of %s returned %s\n",
12964 nt_errstr(status));
12968 status = cli_posix_open(cli_posix,
12970 O_RDWR|O_CREAT|O_EXCL,
12973 if (!NT_STATUS_IS_OK(status)) {
12974 printf("cli_posix_open (create) of %s returned %s\n",
12976 nt_errstr(status));
12979 status = cli_close(cli_posix, fnum);
12980 if (!NT_STATUS_IS_OK(status)) {
12983 status = cli_posix_open(cli_posix,
12985 O_RDWR|O_CREAT|O_EXCL,
12988 if (!NT_STATUS_IS_OK(status)) {
12989 printf("cli_posix_open (create) of %s returned %s\n",
12991 nt_errstr(status));
12994 status = cli_close(cli_posix, fnum);
12995 if (!NT_STATUS_IS_OK(status)) {
13000 * Get the mangled name. We can re-use the
13001 * previous smb1_wild_mangle_list_fn for this.
13004 status = cli_list(cli,
13007 smb1_wild_mangle_list_fn,
13009 if (!NT_STATUS_IS_OK(status)) {
13010 printf("cli_list of %s returned %s\n",
13012 nt_errstr(status));
13016 if (mangled_name == NULL) {
13020 printf("mangled_name = %s\n",
13024 * Try a Windows rename with the mangled name.
13025 * This should *NOT* rename the 'foo' name.
13028 windows_rename_src = talloc_asprintf(cli_posix,
13033 status = cli_rename(cli,
13034 windows_rename_src,
13035 windows_rename_dst,
13037 if (!NT_STATUS_IS_OK(status)) {
13038 printf("cli_rename of %s -> %s returned %s\n",
13039 windows_rename_src,
13040 windows_rename_dst,
13041 nt_errstr(status));
13045 /* Does 'foo' still exist ? */
13046 status = cli_posix_open(cli_posix,
13051 if (!NT_STATUS_IS_OK(status)) {
13052 printf("cli_posix_open O_RNONLY of %s returned %s\n",
13054 nt_errstr(status));
13058 status = cli_close(cli_posix, fnum);
13059 if (!NT_STATUS_IS_OK(status)) {
13067 TALLOC_FREE(mangled_name);
13068 TALLOC_FREE(windows_rename_src);
13071 torture_deltree(cli, dname);
13072 torture_close_connection(cli);
13075 torture_close_connection(cli_posix);
13081 * Only testing minimal time strings, as the others
13082 * need (locale-dependent) guessing at what strftime does and
13083 * even may differ in builds.
13085 static bool timesubst_test(void)
13087 TALLOC_CTX *ctx = NULL;
13088 /* Sa 23. Dez 04:33:20 CET 2017 */
13089 const struct timeval tv = { 1514000000, 123 };
13090 const char* expect_minimal = "20171223_033320";
13091 const char* expect_minus = "20171223_033320_000123";
13093 char *env_tz, *orig_tz = NULL;
13094 bool result = true;
13096 ctx = talloc_new(NULL);
13098 env_tz = getenv("TZ");
13100 orig_tz = talloc_strdup(ctx, env_tz);
13102 setenv("TZ", "UTC", 1);
13104 s = minimal_timeval_string(ctx, &tv, false);
13106 if(!s || strcmp(s, expect_minimal)) {
13107 printf("minimal_timeval_string(ctx, tv, false) returned [%s], expected "
13108 "[%s]\n", s ? s : "<nil>", expect_minimal);
13112 s = minimal_timeval_string(ctx, &tv, true);
13113 if(!s || strcmp(s, expect_minus)) {
13114 printf("minimal_timeval_string(ctx, tv, true) returned [%s], expected "
13115 "[%s]\n", s ? s : "<nil>", expect_minus);
13121 setenv("TZ", orig_tz, 1);
13128 static bool run_local_substitute(int dummy)
13132 ok &= subst_test("%U", "bla", "", -1, -1, "bla");
13133 ok &= subst_test("%u%U", "bla", "", -1, -1, "blabla");
13134 ok &= subst_test("%g", "", "", -1, -1, "NO_GROUP");
13135 ok &= subst_test("%G", "", "", -1, -1, "NO_GROUP");
13136 ok &= subst_test("%g", "", "", -1, 0, gidtoname(0));
13137 ok &= subst_test("%G", "", "", -1, 0, gidtoname(0));
13138 ok &= subst_test("%D%u", "u", "dom", -1, 0, "domu");
13139 ok &= subst_test("%i %I", "", "", -1, -1, "0.0.0.0 0.0.0.0");
13140 ok &= subst_test("%j %J", "", "", -1, -1, "0_0_0_0 0_0_0_0");
13141 /* Substitution depends on current time, so better test the underlying
13142 formatting function. At least covers %t. */
13143 ok &= timesubst_test();
13145 /* Different captialization rules in sub_basic... */
13147 ok &= (strcmp(talloc_sub_basic(talloc_tos(), "BLA", "dom", "%U%D"),
13153 static bool run_local_base64(int dummy)
13158 for (i=1; i<2000; i++) {
13159 DATA_BLOB blob1, blob2;
13162 blob1.data = talloc_array(talloc_tos(), uint8_t, i);
13164 generate_random_buffer(blob1.data, blob1.length);
13166 b64 = base64_encode_data_blob(talloc_tos(), blob1);
13168 d_fprintf(stderr, "base64_encode_data_blob failed "
13169 "for %d bytes\n", i);
13172 blob2 = base64_decode_data_blob(b64);
13175 if (data_blob_cmp(&blob1, &blob2)) {
13176 d_fprintf(stderr, "data_blob_cmp failed for %d "
13180 TALLOC_FREE(blob1.data);
13181 data_blob_free(&blob2);
13186 static void parse_fn(const struct gencache_timeout *t,
13188 void *private_data)
13193 static bool run_local_gencache(int dummy)
13199 struct memcache *mem;
13202 mem = memcache_init(NULL, 0);
13204 d_printf("%s: memcache_init failed\n", __location__);
13207 memcache_set_global(mem);
13209 if (!gencache_set("foo", "bar", time(NULL) + 1000)) {
13210 d_printf("%s: gencache_set() failed\n", __location__);
13214 if (!gencache_get("foo", NULL, NULL, NULL)) {
13215 d_printf("%s: gencache_get() failed\n", __location__);
13219 for (i=0; i<1000000; i++) {
13220 gencache_parse("foo", parse_fn, NULL);
13223 if (!gencache_get("foo", talloc_tos(), &val, &tm)) {
13224 d_printf("%s: gencache_get() failed\n", __location__);
13229 if (!gencache_get("foo", talloc_tos(), &val, &tm)) {
13230 d_printf("%s: gencache_get() failed\n", __location__);
13234 if (strcmp(val, "bar") != 0) {
13235 d_printf("%s: gencache_get() returned %s, expected %s\n",
13236 __location__, val, "bar");
13243 if (!gencache_del("foo")) {
13244 d_printf("%s: gencache_del() failed\n", __location__);
13247 if (gencache_del("foo")) {
13248 d_printf("%s: second gencache_del() succeeded\n",
13253 if (gencache_get("foo", talloc_tos(), &val, &tm)) {
13254 d_printf("%s: gencache_get() on deleted entry "
13255 "succeeded\n", __location__);
13259 blob = data_blob_string_const_null("bar");
13260 tm = time(NULL) + 60;
13262 if (!gencache_set_data_blob("foo", blob, tm)) {
13263 d_printf("%s: gencache_set_data_blob() failed\n", __location__);
13267 if (!gencache_get_data_blob("foo", talloc_tos(), &blob, NULL, NULL)) {
13268 d_printf("%s: gencache_get_data_blob() failed\n", __location__);
13272 if (strcmp((const char *)blob.data, "bar") != 0) {
13273 d_printf("%s: gencache_get_data_blob() returned %s, expected %s\n",
13274 __location__, (const char *)blob.data, "bar");
13275 data_blob_free(&blob);
13279 data_blob_free(&blob);
13281 if (!gencache_del("foo")) {
13282 d_printf("%s: gencache_del() failed\n", __location__);
13285 if (gencache_del("foo")) {
13286 d_printf("%s: second gencache_del() succeeded\n",
13291 if (gencache_get_data_blob("foo", talloc_tos(), &blob, NULL, NULL)) {
13292 d_printf("%s: gencache_get_data_blob() on deleted entry "
13293 "succeeded\n", __location__);
13298 blob.data = (uint8_t *)&v;
13299 blob.length = sizeof(v);
13301 if (!gencache_set_data_blob("blob", blob, tm)) {
13302 d_printf("%s: gencache_set_data_blob() failed\n",
13306 if (gencache_get("blob", talloc_tos(), &val, &tm)) {
13307 d_printf("%s: gencache_get succeeded\n", __location__);
13314 static bool rbt_testflags(struct db_context *db, const char *key,
13319 struct db_record *rec;
13321 rec = dbwrap_fetch_locked(db, db, string_tdb_data(key));
13323 d_fprintf(stderr, "fetch_locked failed\n");
13327 status = dbwrap_record_store(rec, string_tdb_data(value), TDB_MODIFY);
13328 if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
13329 d_fprintf(stderr, "store TDB_MODIFY unexpected status: %s\n",
13330 nt_errstr(status));
13334 status = dbwrap_record_store(rec, string_tdb_data("overwriteme"),
13336 if (!NT_STATUS_IS_OK(status)) {
13337 d_fprintf(stderr, "store TDB_INSERT failed: %s\n",
13338 nt_errstr(status));
13342 status = dbwrap_record_store(rec, string_tdb_data(value), TDB_INSERT);
13343 if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_COLLISION)) {
13344 d_fprintf(stderr, "store TDB_INSERT unexpected status: %s\n",
13345 nt_errstr(status));
13349 status = dbwrap_record_store(rec, string_tdb_data(value), TDB_MODIFY);
13350 if (!NT_STATUS_IS_OK(status)) {
13351 d_fprintf(stderr, "store TDB_MODIFY failed: %s\n",
13352 nt_errstr(status));
13362 static bool rbt_testval(struct db_context *db, const char *key,
13365 struct db_record *rec;
13366 TDB_DATA data = string_tdb_data(value);
13371 rec = dbwrap_fetch_locked(db, db, string_tdb_data(key));
13373 d_fprintf(stderr, "fetch_locked failed\n");
13376 status = dbwrap_record_store(rec, data, 0);
13377 if (!NT_STATUS_IS_OK(status)) {
13378 d_fprintf(stderr, "store failed: %s\n", nt_errstr(status));
13383 rec = dbwrap_fetch_locked(db, db, string_tdb_data(key));
13385 d_fprintf(stderr, "second fetch_locked failed\n");
13389 dbvalue = dbwrap_record_get_value(rec);
13390 if ((dbvalue.dsize != data.dsize)
13391 || (memcmp(dbvalue.dptr, data.dptr, data.dsize) != 0)) {
13392 d_fprintf(stderr, "Got wrong data back\n");
13402 static int local_rbtree_traverse_read(struct db_record *rec, void *private_data)
13404 int *count2 = (int *)private_data;
13409 static int local_rbtree_traverse_delete(struct db_record *rec, void *private_data)
13411 int *count2 = (int *)private_data;
13413 dbwrap_record_delete(rec);
13417 static bool run_local_rbtree(int dummy)
13419 struct db_context *db;
13426 db = db_open_rbt(NULL);
13429 d_fprintf(stderr, "db_open_rbt failed\n");
13433 if (!rbt_testflags(db, "firstkey", "firstval")) {
13437 for (i = 0; i < 999; i++) {
13438 char key[sizeof("key-9223372036854775807")];
13439 char value[sizeof("value-9223372036854775807")];
13441 snprintf(key, sizeof(key), "key%ld", random());
13442 snprintf(value, sizeof(value) ,"value%ld", random());
13444 if (!rbt_testval(db, key, value)) {
13448 snprintf(value, sizeof(value) ,"value%ld", random());
13450 if (!rbt_testval(db, key, value)) {
13456 count = 0; count2 = 0;
13457 status = dbwrap_traverse_read(db, local_rbtree_traverse_read,
13459 printf("%s: read1: %d %d, %s\n", __func__, count, count2, nt_errstr(status));
13460 if ((count != count2) || (count != 1000)) {
13463 count = 0; count2 = 0;
13464 status = dbwrap_traverse(db, local_rbtree_traverse_delete,
13466 printf("%s: delete: %d %d, %s\n", __func__, count, count2, nt_errstr(status));
13467 if ((count != count2) || (count != 1000)) {
13470 count = 0; count2 = 0;
13471 status = dbwrap_traverse_read(db, local_rbtree_traverse_read,
13473 printf("%s: read2: %d %d, %s\n", __func__, count, count2, nt_errstr(status));
13474 if ((count != count2) || (count != 0)) {
13485 local test for character set functions
13487 This is a very simple test for the functionality in convert_string_error()
13489 static bool run_local_convert_string(int dummy)
13491 TALLOC_CTX *tmp_ctx = talloc_new(NULL);
13492 const char *test_strings[2] = { "March", "M\303\244rz" };
13496 for (i=0; i<2; i++) {
13497 const char *str = test_strings[i];
13498 int len = strlen(str);
13499 size_t converted_size;
13502 memset(dst, 'X', sizeof(dst));
13504 /* first try with real source length */
13505 ret = convert_string_error(CH_UNIX, CH_UTF8,
13510 d_fprintf(stderr, "Failed to convert '%s' to CH_DISPLAY\n", str);
13514 if (converted_size != len) {
13515 d_fprintf(stderr, "Converted size of '%s' should be %d - got %d\n",
13516 str, len, (int)converted_size);
13520 if (strncmp(str, dst, converted_size) != 0) {
13521 d_fprintf(stderr, "Expected '%s' to match '%s'\n", str, dst);
13525 if (strlen(str) != converted_size) {
13526 d_fprintf(stderr, "Expected '%s' length %d - got %d\n", str,
13527 (int)strlen(str), (int)converted_size);
13531 if (dst[converted_size] != 'X') {
13532 d_fprintf(stderr, "Expected no termination of '%s'\n", dst);
13536 /* now with srclen==-1, this causes the nul to be
13538 ret = convert_string_error(CH_UNIX, CH_UTF8,
13543 d_fprintf(stderr, "Failed to convert '%s' to CH_DISPLAY\n", str);
13547 if (converted_size != len+1) {
13548 d_fprintf(stderr, "Converted size of '%s' should be %d - got %d\n",
13549 str, len, (int)converted_size);
13553 if (strncmp(str, dst, converted_size) != 0) {
13554 d_fprintf(stderr, "Expected '%s' to match '%s'\n", str, dst);
13558 if (len+1 != converted_size) {
13559 d_fprintf(stderr, "Expected '%s' length %d - got %d\n", str,
13560 len+1, (int)converted_size);
13564 if (dst[converted_size] != 'X') {
13565 d_fprintf(stderr, "Expected no termination of '%s'\n", dst);
13572 TALLOC_FREE(tmp_ctx);
13575 TALLOC_FREE(tmp_ctx);
13579 static bool run_local_string_to_sid(int dummy) {
13580 struct dom_sid sid;
13582 if (string_to_sid(&sid, "S--1-5-32-545")) {
13583 printf("allowing S--1-5-32-545\n");
13586 if (string_to_sid(&sid, "S-1-5-32-+545")) {
13587 printf("allowing S-1-5-32-+545\n");
13590 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")) {
13591 printf("allowing S-1-2-3-4-5-6-7-8-9-0-1-2-3-4-5-6-7-8-9-0\n");
13594 if (string_to_sid(&sid, "S-1-5-32-545-abc")) {
13595 printf("allowing S-1-5-32-545-abc\n");
13598 if (string_to_sid(&sid, "S-300-5-32-545")) {
13599 printf("allowing S-300-5-32-545\n");
13602 if (string_to_sid(&sid, "S-1-0xfffffffffffffe-32-545")) {
13603 printf("allowing S-1-0xfffffffffffffe-32-545\n");
13606 if (string_to_sid(&sid, "S-1-0xffffffffffff-5294967297-545")) {
13607 printf("allowing S-1-0xffffffffffff-5294967297-545\n");
13610 if (!string_to_sid(&sid, "S-1-0xfffffffffffe-32-545")) {
13611 printf("could not parse S-1-0xfffffffffffe-32-545\n");
13614 if (!string_to_sid(&sid, "S-1-5-32-545")) {
13615 printf("could not parse S-1-5-32-545\n");
13618 if (!dom_sid_equal(&sid, &global_sid_Builtin_Users)) {
13619 struct dom_sid_buf buf;
13620 printf("mis-parsed S-1-5-32-545 as %s\n",
13621 dom_sid_str_buf(&sid, &buf));
13627 static bool sid_to_string_test(const char *expected) {
13630 struct dom_sid sid;
13632 if (!string_to_sid(&sid, expected)) {
13633 printf("could not parse %s\n", expected);
13637 str = dom_sid_string(NULL, &sid);
13638 if (strcmp(str, expected)) {
13639 printf("Comparison failed (%s != %s)\n", str, expected);
13646 static bool run_local_sid_to_string(int dummy) {
13647 if (!sid_to_string_test("S-1-0xffffffffffff-1-1-1-1-1-1-1-1-1-1-1-1"))
13649 if (!sid_to_string_test("S-1-545"))
13651 if (!sid_to_string_test("S-255-3840-1-1-1-1"))
13656 static bool run_local_binary_to_sid(int dummy) {
13658 struct dom_sid *sid = talloc(NULL, struct dom_sid);
13659 static const uint8_t good_binary_sid[] = {
13660 0x1, /* revision number */
13661 15, /* num auths */
13662 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, /* id_auth */
13663 0x1, 0x1, 0x1, 0x1, /* auth[0] */
13664 0x1, 0x1, 0x1, 0x1, /* auth[1] */
13665 0x1, 0x1, 0x1, 0x1, /* auth[2] */
13666 0x1, 0x1, 0x1, 0x1, /* auth[3] */
13667 0x1, 0x1, 0x1, 0x1, /* auth[4] */
13668 0x1, 0x1, 0x1, 0x1, /* auth[5] */
13669 0x1, 0x1, 0x1, 0x1, /* auth[6] */
13670 0x1, 0x1, 0x1, 0x1, /* auth[7] */
13671 0x1, 0x1, 0x1, 0x1, /* auth[8] */
13672 0x1, 0x1, 0x1, 0x1, /* auth[9] */
13673 0x1, 0x1, 0x1, 0x1, /* auth[10] */
13674 0x1, 0x1, 0x1, 0x1, /* auth[11] */
13675 0x1, 0x1, 0x1, 0x1, /* auth[12] */
13676 0x1, 0x1, 0x1, 0x1, /* auth[13] */
13677 0x1, 0x1, 0x1, 0x1, /* auth[14] */
13680 static const uint8_t long_binary_sid[] = {
13681 0x1, /* revision number */
13682 15, /* num auths */
13683 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, /* id_auth */
13684 0x1, 0x1, 0x1, 0x1, /* auth[0] */
13685 0x1, 0x1, 0x1, 0x1, /* auth[1] */
13686 0x1, 0x1, 0x1, 0x1, /* auth[2] */
13687 0x1, 0x1, 0x1, 0x1, /* auth[3] */
13688 0x1, 0x1, 0x1, 0x1, /* auth[4] */
13689 0x1, 0x1, 0x1, 0x1, /* auth[5] */
13690 0x1, 0x1, 0x1, 0x1, /* auth[6] */
13691 0x1, 0x1, 0x1, 0x1, /* auth[7] */
13692 0x1, 0x1, 0x1, 0x1, /* auth[8] */
13693 0x1, 0x1, 0x1, 0x1, /* auth[9] */
13694 0x1, 0x1, 0x1, 0x1, /* auth[10] */
13695 0x1, 0x1, 0x1, 0x1, /* auth[11] */
13696 0x1, 0x1, 0x1, 0x1, /* auth[12] */
13697 0x1, 0x1, 0x1, 0x1, /* auth[13] */
13698 0x1, 0x1, 0x1, 0x1, /* auth[14] */
13699 0x1, 0x1, 0x1, 0x1, /* auth[15] */
13700 0x1, 0x1, 0x1, 0x1, /* auth[16] */
13701 0x1, 0x1, 0x1, 0x1, /* auth[17] */
13704 static const uint8_t long_binary_sid2[] = {
13705 0x1, /* revision number */
13706 32, /* num auths */
13707 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, /* id_auth */
13708 0x1, 0x1, 0x1, 0x1, /* auth[0] */
13709 0x1, 0x1, 0x1, 0x1, /* auth[1] */
13710 0x1, 0x1, 0x1, 0x1, /* auth[2] */
13711 0x1, 0x1, 0x1, 0x1, /* auth[3] */
13712 0x1, 0x1, 0x1, 0x1, /* auth[4] */
13713 0x1, 0x1, 0x1, 0x1, /* auth[5] */
13714 0x1, 0x1, 0x1, 0x1, /* auth[6] */
13715 0x1, 0x1, 0x1, 0x1, /* auth[7] */
13716 0x1, 0x1, 0x1, 0x1, /* auth[8] */
13717 0x1, 0x1, 0x1, 0x1, /* auth[9] */
13718 0x1, 0x1, 0x1, 0x1, /* auth[10] */
13719 0x1, 0x1, 0x1, 0x1, /* auth[11] */
13720 0x1, 0x1, 0x1, 0x1, /* auth[12] */
13721 0x1, 0x1, 0x1, 0x1, /* auth[13] */
13722 0x1, 0x1, 0x1, 0x1, /* auth[14] */
13723 0x1, 0x1, 0x1, 0x1, /* auth[15] */
13724 0x1, 0x1, 0x1, 0x1, /* auth[16] */
13725 0x1, 0x1, 0x1, 0x1, /* auth[17] */
13726 0x1, 0x1, 0x1, 0x1, /* auth[18] */
13727 0x1, 0x1, 0x1, 0x1, /* auth[19] */
13728 0x1, 0x1, 0x1, 0x1, /* auth[20] */
13729 0x1, 0x1, 0x1, 0x1, /* auth[21] */
13730 0x1, 0x1, 0x1, 0x1, /* auth[22] */
13731 0x1, 0x1, 0x1, 0x1, /* auth[23] */
13732 0x1, 0x1, 0x1, 0x1, /* auth[24] */
13733 0x1, 0x1, 0x1, 0x1, /* auth[25] */
13734 0x1, 0x1, 0x1, 0x1, /* auth[26] */
13735 0x1, 0x1, 0x1, 0x1, /* auth[27] */
13736 0x1, 0x1, 0x1, 0x1, /* auth[28] */
13737 0x1, 0x1, 0x1, 0x1, /* auth[29] */
13738 0x1, 0x1, 0x1, 0x1, /* auth[30] */
13739 0x1, 0x1, 0x1, 0x1, /* auth[31] */
13742 ret = sid_parse(good_binary_sid, sizeof(good_binary_sid), sid);
13746 ret = sid_parse(long_binary_sid2, sizeof(long_binary_sid2), sid);
13750 ret = sid_parse(long_binary_sid, sizeof(long_binary_sid), sid);
13757 /* Split a path name into filename and stream name components. Canonicalise
13758 * such that an implicit $DATA token is always explicit.
13760 * The "specification" of this function can be found in the
13761 * run_local_stream_name() function in torture.c, I've tried those
13762 * combinations against a W2k3 server.
13765 static NTSTATUS split_ntfs_stream_name(TALLOC_CTX *mem_ctx, const char *fname,
13766 char **pbase, char **pstream)
13769 char *stream = NULL;
13770 char *sname; /* stream name */
13771 const char *stype; /* stream type */
13773 DEBUG(10, ("split_ntfs_stream_name called for [%s]\n", fname));
13775 sname = strchr_m(fname, ':');
13777 if (sname == NULL) {
13778 if (pbase != NULL) {
13779 base = talloc_strdup(mem_ctx, fname);
13780 NT_STATUS_HAVE_NO_MEMORY(base);
13785 if (pbase != NULL) {
13786 base = talloc_strndup(mem_ctx, fname, PTR_DIFF(sname, fname));
13787 NT_STATUS_HAVE_NO_MEMORY(base);
13792 stype = strchr_m(sname, ':');
13794 if (stype == NULL) {
13795 sname = talloc_strdup(mem_ctx, sname);
13799 if (strcasecmp_m(stype, ":$DATA") != 0) {
13801 * If there is an explicit stream type, so far we only
13802 * allow $DATA. Is there anything else allowed? -- vl
13804 DEBUG(10, ("[%s] is an invalid stream type\n", stype));
13806 return NT_STATUS_OBJECT_NAME_INVALID;
13808 sname = talloc_strndup(mem_ctx, sname, PTR_DIFF(stype, sname));
13812 if (sname == NULL) {
13814 return NT_STATUS_NO_MEMORY;
13817 if (sname[0] == '\0') {
13819 * no stream name, so no stream
13824 if (pstream != NULL) {
13825 stream = talloc_asprintf(mem_ctx, "%s:%s", sname, stype);
13826 if (stream == NULL) {
13827 TALLOC_FREE(sname);
13829 return NT_STATUS_NO_MEMORY;
13832 * upper-case the type field
13834 (void)strupper_m(strchr_m(stream, ':')+1);
13838 if (pbase != NULL) {
13841 if (pstream != NULL) {
13844 return NT_STATUS_OK;
13847 static bool test_stream_name(const char *fname, const char *expected_base,
13848 const char *expected_stream,
13849 NTSTATUS expected_status)
13853 char *stream = NULL;
13855 status = split_ntfs_stream_name(talloc_tos(), fname, &base, &stream);
13856 if (!NT_STATUS_EQUAL(status, expected_status)) {
13860 if (!NT_STATUS_IS_OK(status)) {
13864 if (base == NULL) goto error;
13866 if (strcmp(expected_base, base) != 0) goto error;
13868 if ((expected_stream != NULL) && (stream == NULL)) goto error;
13869 if ((expected_stream == NULL) && (stream != NULL)) goto error;
13871 if ((stream != NULL) && (strcmp(expected_stream, stream) != 0))
13875 TALLOC_FREE(stream);
13879 d_fprintf(stderr, "Do test_stream(%s, %s, %s, %s)\n",
13880 fname, expected_base ? expected_base : "<NULL>",
13881 expected_stream ? expected_stream : "<NULL>",
13882 nt_errstr(expected_status));
13883 d_fprintf(stderr, "-> base=%s, stream=%s, status=%s\n",
13884 base ? base : "<NULL>", stream ? stream : "<NULL>",
13885 nt_errstr(status));
13887 TALLOC_FREE(stream);
13891 static bool run_local_stream_name(int dummy)
13895 ret &= test_stream_name(
13896 "bla", "bla", NULL, NT_STATUS_OK);
13897 ret &= test_stream_name(
13898 "bla::$DATA", "bla", NULL, NT_STATUS_OK);
13899 ret &= test_stream_name(
13900 "bla:blub:", "bla", NULL, NT_STATUS_OBJECT_NAME_INVALID);
13901 ret &= test_stream_name(
13902 "bla::", NULL, NULL, NT_STATUS_OBJECT_NAME_INVALID);
13903 ret &= test_stream_name(
13904 "bla::123", "bla", NULL, NT_STATUS_OBJECT_NAME_INVALID);
13905 ret &= test_stream_name(
13906 "bla:$DATA", "bla", "$DATA:$DATA", NT_STATUS_OK);
13907 ret &= test_stream_name(
13908 "bla:x:$DATA", "bla", "x:$DATA", NT_STATUS_OK);
13909 ret &= test_stream_name(
13910 "bla:x", "bla", "x:$DATA", NT_STATUS_OK);
13915 static bool data_blob_equal(DATA_BLOB a, DATA_BLOB b)
13917 if (a.length != b.length) {
13918 printf("a.length=%d != b.length=%d\n",
13919 (int)a.length, (int)b.length);
13922 if (memcmp(a.data, b.data, a.length) != 0) {
13923 printf("a.data and b.data differ\n");
13929 static bool run_local_memcache(int dummy)
13931 struct memcache *cache;
13932 DATA_BLOB k1, k2, k3, k4, k5;
13936 TALLOC_CTX *mem_ctx;
13942 size_t size1, size2;
13945 mem_ctx = talloc_init("foo");
13946 if (mem_ctx == NULL) {
13950 /* STAT_CACHE TESTS */
13952 cache = memcache_init(NULL, sizeof(void *) == 8 ? 200 : 100);
13954 if (cache == NULL) {
13955 printf("memcache_init failed\n");
13959 d1 = data_blob_const("d1", 2);
13960 d3 = data_blob_const("d3", 2);
13962 k1 = data_blob_const("d1", 2);
13963 k2 = data_blob_const("d2", 2);
13964 k3 = data_blob_const("d3", 2);
13965 k4 = data_blob_const("d4", 2);
13966 k5 = data_blob_const("d5", 2);
13968 memcache_add(cache, STAT_CACHE, k1, d1);
13970 if (!memcache_lookup(cache, STAT_CACHE, k1, &v1)) {
13971 printf("could not find k1\n");
13974 if (!data_blob_equal(d1, v1)) {
13978 memcache_add(cache, STAT_CACHE, k1, d3);
13980 if (!memcache_lookup(cache, STAT_CACHE, k1, &v3)) {
13981 printf("could not find replaced k1\n");
13984 if (!data_blob_equal(d3, v3)) {
13988 TALLOC_FREE(cache);
13990 /* GETWD_CACHE TESTS */
13991 str1 = talloc_strdup(mem_ctx, "string1");
13992 if (str1 == NULL) {
13995 ptr2 = str1; /* Keep an alias for comparison. */
13997 str2 = talloc_strdup(mem_ctx, "string2");
13998 if (str2 == NULL) {
14002 cache = memcache_init(NULL, sizeof(void *) == 8 ? 200 : 100);
14003 if (cache == NULL) {
14004 printf("memcache_init failed\n");
14008 memcache_add_talloc(cache, GETWD_CACHE, k2, &str1);
14009 /* str1 == NULL now. */
14010 ptr1 = memcache_lookup_talloc(cache, GETWD_CACHE, k2);
14011 if (ptr1 == NULL) {
14012 printf("could not find k2\n");
14015 if (ptr1 != ptr2) {
14016 printf("fetch of k2 got wrong string\n");
14020 /* Add a blob to ensure k2 gets purged. */
14021 d3 = data_blob_talloc_zero(mem_ctx, 180);
14022 memcache_add(cache, STAT_CACHE, k3, d3);
14024 ptr2 = memcache_lookup_talloc(cache, GETWD_CACHE, k2);
14025 if (ptr2 != NULL) {
14026 printf("Did find k2, should have been purged\n");
14031 * Test that talloc size also is accounted in memcache and
14032 * causes purge of other object.
14035 str1 = talloc_zero_size(mem_ctx, 100);
14036 str2 = talloc_zero_size(mem_ctx, 100);
14038 memcache_add_talloc(cache, GETWD_CACHE, k4, &str1);
14039 memcache_add_talloc(cache, GETWD_CACHE, k5, &str1);
14041 ptr3 = memcache_lookup_talloc(cache, GETWD_CACHE, k4);
14042 if (ptr3 != NULL) {
14043 printf("Did find k4, should have been purged\n");
14048 * Test that adding a duplicate non-talloced
14049 * key/value on top of a talloced key/value takes account
14050 * of the talloc_freed value size.
14052 TALLOC_FREE(cache);
14053 TALLOC_FREE(mem_ctx);
14055 mem_ctx = talloc_init("key_replace");
14056 if (mem_ctx == NULL) {
14060 cache = memcache_init(NULL, sizeof(void *) == 8 ? 200 : 100);
14061 if (cache == NULL) {
14066 * Add a 100 byte talloced string. This will
14067 * store a (4 or 8 byte) pointer and record the
14068 * total talloced size.
14070 str1 = talloc_zero_size(mem_ctx, 100);
14071 memcache_add_talloc(cache, GETWD_CACHE, k4, &str1);
14073 * Now overwrite with a small talloced
14074 * value. This should fit in the existing size
14075 * and the total talloced size should be removed
14076 * from the cache size.
14078 str1 = talloc_zero_size(mem_ctx, 2);
14079 memcache_add_talloc(cache, GETWD_CACHE, k4, &str1);
14081 * Now store a 20 byte string. If the
14082 * total talloced size wasn't accounted for
14083 * and removed in the overwrite, then this
14086 str2 = talloc_zero_size(mem_ctx, 20);
14087 memcache_add_talloc(cache, GETWD_CACHE, k5, &str2);
14089 ptr3 = memcache_lookup_talloc(cache, GETWD_CACHE, k4);
14090 if (ptr3 == NULL) {
14091 printf("Did not find k4, should not have been purged\n");
14095 TALLOC_FREE(cache);
14096 TALLOC_FREE(mem_ctx);
14098 mem_ctx = talloc_init("foo");
14099 if (mem_ctx == NULL) {
14103 cache = memcache_init(NULL, 0);
14104 if (cache == NULL) {
14108 str1 = talloc_strdup(mem_ctx, "string1");
14109 if (str1 == NULL) {
14112 str2 = talloc_strdup(mem_ctx, "string2");
14113 if (str2 == NULL) {
14116 memcache_add_talloc(cache, SINGLETON_CACHE_TALLOC,
14117 data_blob_string_const("torture"), &str1);
14118 size1 = talloc_total_size(cache);
14120 memcache_add_talloc(cache, SINGLETON_CACHE_TALLOC,
14121 data_blob_string_const("torture"), &str2);
14122 size2 = talloc_total_size(cache);
14124 printf("size1=%d, size2=%d\n", (int)size1, (int)size2);
14126 if (size2 > size1) {
14127 printf("memcache leaks memory!\n");
14133 TALLOC_FREE(cache);
14137 static void wbclient_done(struct tevent_req *req)
14140 struct winbindd_response *wb_resp;
14141 int *i = (int *)tevent_req_callback_data_void(req);
14143 wbc_err = wb_trans_recv(req, req, &wb_resp);
14146 d_printf("wb_trans_recv %d returned %s\n", *i, wbcErrorString(wbc_err));
14149 static bool run_wbclient_multi_ping(int dummy)
14151 struct tevent_context *ev;
14152 struct wb_context **wb_ctx;
14153 struct winbindd_request wb_req;
14154 bool result = false;
14157 BlockSignals(True, SIGPIPE);
14159 ev = tevent_context_init(talloc_tos());
14164 wb_ctx = talloc_array(ev, struct wb_context *, torture_nprocs);
14165 if (wb_ctx == NULL) {
14169 ZERO_STRUCT(wb_req);
14170 wb_req.cmd = WINBINDD_PING;
14172 d_printf("torture_nprocs=%d, numops=%d\n", (int)torture_nprocs, (int)torture_numops);
14174 for (i=0; i<torture_nprocs; i++) {
14175 wb_ctx[i] = wb_context_init(ev, NULL);
14176 if (wb_ctx[i] == NULL) {
14179 for (j=0; j<torture_numops; j++) {
14180 struct tevent_req *req;
14181 req = wb_trans_send(ev, ev, wb_ctx[i],
14182 (j % 2) == 0, &wb_req);
14186 tevent_req_set_callback(req, wbclient_done, &i);
14192 while (i < torture_nprocs * torture_numops) {
14193 tevent_loop_once(ev);
14202 static bool dbtrans_inc(struct db_context *db)
14204 struct db_record *rec;
14210 rec = dbwrap_fetch_locked(db, db, string_term_tdb_data("transtest"));
14212 printf(__location__ "fetch_lock failed\n");
14216 value = dbwrap_record_get_value(rec);
14218 if (value.dsize != sizeof(uint32_t)) {
14219 printf(__location__ "value.dsize = %d\n",
14224 memcpy(&val, value.dptr, sizeof(val));
14227 status = dbwrap_record_store(
14228 rec, make_tdb_data((uint8_t *)&val, sizeof(val)), 0);
14229 if (!NT_STATUS_IS_OK(status)) {
14230 printf(__location__ "store failed: %s\n",
14231 nt_errstr(status));
14241 static bool run_local_dbtrans(int dummy)
14243 struct db_context *db;
14244 struct db_record *rec;
14250 db = db_open(talloc_tos(), "transtest.tdb", 0, TDB_DEFAULT,
14251 O_RDWR|O_CREAT, 0600, DBWRAP_LOCK_ORDER_1,
14254 printf("Could not open transtest.db\n");
14258 res = dbwrap_transaction_start(db);
14260 printf(__location__ "transaction_start failed\n");
14264 rec = dbwrap_fetch_locked(db, db, string_term_tdb_data("transtest"));
14266 printf(__location__ "fetch_lock failed\n");
14270 value = dbwrap_record_get_value(rec);
14272 if (value.dptr == NULL) {
14274 status = dbwrap_record_store(
14275 rec, make_tdb_data((uint8_t *)&initial,
14278 if (!NT_STATUS_IS_OK(status)) {
14279 printf(__location__ "store returned %s\n",
14280 nt_errstr(status));
14287 res = dbwrap_transaction_commit(db);
14289 printf(__location__ "transaction_commit failed\n");
14294 uint32_t val, val2;
14297 res = dbwrap_transaction_start(db);
14299 printf(__location__ "transaction_start failed\n");
14303 status = dbwrap_fetch_uint32_bystring(db, "transtest", &val);
14304 if (!NT_STATUS_IS_OK(status)) {
14305 printf(__location__ "dbwrap_fetch_uint32 failed: %s\n",
14306 nt_errstr(status));
14310 for (i=0; i<10; i++) {
14311 if (!dbtrans_inc(db)) {
14316 status = dbwrap_fetch_uint32_bystring(db, "transtest", &val2);
14317 if (!NT_STATUS_IS_OK(status)) {
14318 printf(__location__ "dbwrap_fetch_uint32 failed: %s\n",
14319 nt_errstr(status));
14323 if (val2 != val + 10) {
14324 printf(__location__ "val=%d, val2=%d\n",
14325 (int)val, (int)val2);
14329 printf("val2=%d\r", val2);
14331 res = dbwrap_transaction_commit(db);
14333 printf(__location__ "transaction_commit failed\n");
14343 * Just a dummy test to be run under a debugger. There's no real way
14344 * to inspect the tevent_poll specific function from outside of
14348 static bool run_local_tevent_poll(int dummy)
14350 struct tevent_context *ev;
14351 struct tevent_fd *fd1, *fd2;
14352 bool result = false;
14354 ev = tevent_context_init_byname(NULL, "poll");
14356 d_fprintf(stderr, "tevent_context_init_byname failed\n");
14360 fd1 = tevent_add_fd(ev, ev, 2, 0, NULL, NULL);
14362 d_fprintf(stderr, "tevent_add_fd failed\n");
14365 fd2 = tevent_add_fd(ev, ev, 3, 0, NULL, NULL);
14367 d_fprintf(stderr, "tevent_add_fd failed\n");
14372 fd2 = tevent_add_fd(ev, ev, 1, 0, NULL, NULL);
14374 d_fprintf(stderr, "tevent_add_fd failed\n");
14384 static bool run_local_hex_encode_buf(int dummy)
14390 for (i=0; i<sizeof(src); i++) {
14393 hex_encode_buf(buf, src, sizeof(src));
14394 if (strcmp(buf, "0001020304050607") != 0) {
14397 hex_encode_buf(buf, NULL, 0);
14398 if (buf[0] != '\0') {
14404 static const char *remove_duplicate_addrs2_test_strings_vector[] = {
14426 "1001:1111:1111:1000:0:1111:1111:1111",
14435 static const char *remove_duplicate_addrs2_test_strings_result[] = {
14449 "1001:1111:1111:1000:0:1111:1111:1111"
14452 static bool run_local_remove_duplicate_addrs2(int dummy)
14454 struct samba_sockaddr test_vector[28];
14457 /* Construct the sockaddr_storage test vector. */
14458 for (i = 0; i < 28; i++) {
14459 struct addrinfo hints;
14460 struct addrinfo *res = NULL;
14463 memset(&hints, '\0', sizeof(hints));
14464 hints.ai_flags = AI_NUMERICHOST;
14465 ret = getaddrinfo(remove_duplicate_addrs2_test_strings_vector[i],
14470 fprintf(stderr, "getaddrinfo failed on [%s]\n",
14471 remove_duplicate_addrs2_test_strings_vector[i]);
14474 memset(&test_vector[i], '\0', sizeof(test_vector[i]));
14475 memcpy(&test_vector[i].u.ss,
14481 count = remove_duplicate_addrs2(test_vector, i);
14484 fprintf(stderr, "count wrong (%zu) should be 14\n",
14489 for (i = 0; i < count; i++) {
14490 char addr[INET6_ADDRSTRLEN];
14492 print_sockaddr(addr, sizeof(addr), &test_vector[i].u.ss);
14494 if (strcmp(addr, remove_duplicate_addrs2_test_strings_result[i]) != 0) {
14495 fprintf(stderr, "mismatch on [%zu] [%s] [%s]\n",
14498 remove_duplicate_addrs2_test_strings_result[i]);
14503 printf("run_local_remove_duplicate_addrs2: success\n");
14507 static bool run_local_tdb_opener(int dummy)
14513 t = tdb_open("test.tdb", 1000, TDB_CLEAR_IF_FIRST,
14514 O_RDWR|O_CREAT, 0755);
14516 perror("tdb_open failed");
14527 static bool run_local_tdb_writer(int dummy)
14533 t = tdb_open("test.tdb", 1000, 0, O_RDWR|O_CREAT, 0755);
14535 perror("tdb_open failed");
14539 val.dptr = (uint8_t *)&v;
14540 val.dsize = sizeof(v);
14546 ret = tdb_store(t, val, val, 0);
14548 printf("%s\n", tdb_errorstr(t));
14553 data = tdb_fetch(t, val);
14554 if (data.dptr != NULL) {
14555 SAFE_FREE(data.dptr);
14561 static bool run_local_canonicalize_path(int dummy)
14563 const char *src[] = {
14570 ".././././../../../boo",
14582 "/foo/bar/../baz/",
14583 "////////////////",
14584 "/////////./././././.",
14585 "/./.././../.boo/../baz",
14586 "/a/component/path",
14587 "/a/component/path/",
14588 "/a/component/path/..",
14589 "/a/component/../path/",
14590 "///a/./././///component/../////path/",
14593 const char *dst[] = {
14616 "/a/component/path",
14617 "/a/component/path",
14625 for (i = 0; src[i] != NULL; i++) {
14626 char *d = canonicalize_absolute_path(talloc_tos(), src[i]);
14628 perror("talloc fail\n");
14631 if (strcmp(d, dst[i]) != 0) {
14633 "canonicalize mismatch %s -> %s != %s",
14634 src[i], d, dst[i]);
14642 static bool run_ign_bad_negprot(int dummy)
14644 struct tevent_context *ev;
14645 struct tevent_req *req;
14646 struct smbXcli_conn *conn;
14647 struct sockaddr_storage ss;
14652 printf("starting ignore bad negprot\n");
14654 ok = resolve_name(host, &ss, 0x20, true);
14656 d_fprintf(stderr, "Could not resolve name %s\n", host);
14660 status = open_socket_out(&ss, 445, 10000, &fd);
14661 if (!NT_STATUS_IS_OK(status)) {
14662 d_fprintf(stderr, "open_socket_out failed: %s\n",
14663 nt_errstr(status));
14667 conn = smbXcli_conn_create(talloc_tos(), fd, host, SMB_SIGNING_OFF, 0,
14669 if (conn == NULL) {
14670 d_fprintf(stderr, "smbXcli_conn_create failed\n");
14674 status = smbXcli_negprot(conn, 0, PROTOCOL_CORE, PROTOCOL_CORE);
14675 if (NT_STATUS_IS_OK(status)) {
14676 d_fprintf(stderr, "smbXcli_negprot succeeded!\n");
14680 ev = samba_tevent_context_init(talloc_tos());
14682 d_fprintf(stderr, "samba_tevent_context_init failed\n");
14686 req = smb1cli_session_setup_nt1_send(
14687 ev, ev, conn, 0, getpid(), NULL, 65503, 2, 1, 0, "", "",
14688 data_blob_null, data_blob_null, 0x40,
14689 "Windows 2000 2195", "Windows 2000 5.0");
14691 d_fprintf(stderr, "smb1cli_session_setup_nt1_send failed\n");
14695 ok = tevent_req_poll_ntstatus(req, ev, &status);
14697 d_fprintf(stderr, "tevent_req_poll failed\n");
14701 status = smb1cli_session_setup_nt1_recv(req, NULL, NULL, NULL, NULL,
14703 if (!NT_STATUS_EQUAL(status, NT_STATUS_CONNECTION_RESET)) {
14704 d_fprintf(stderr, "smb1cli_session_setup_nt1_recv returned "
14705 "%s, expected NT_STATUS_CONNECTION_RESET\n",
14706 nt_errstr(status));
14712 printf("starting ignore bad negprot\n");
14717 static double create_procs(bool (*fn)(int), bool *result)
14720 volatile pid_t *child_status;
14721 volatile bool *child_status_out;
14724 struct timeval start;
14728 child_status = (volatile pid_t *)anonymous_shared_allocate(sizeof(pid_t)*torture_nprocs);
14729 if (!child_status) {
14730 printf("Failed to setup shared memory\n");
14734 child_status_out = (volatile bool *)anonymous_shared_allocate(sizeof(bool)*torture_nprocs);
14735 if (!child_status_out) {
14736 printf("Failed to setup result status shared memory\n");
14740 for (i = 0; i < torture_nprocs; i++) {
14741 child_status[i] = 0;
14742 child_status_out[i] = True;
14745 start = timeval_current();
14747 for (i=0;i<torture_nprocs;i++) {
14750 pid_t mypid = getpid();
14751 sys_srandom(((int)mypid) ^ ((int)time(NULL)));
14753 slprintf(myname,sizeof(myname),"CLIENT%d", i);
14756 if (torture_open_connection(¤t_cli, i)) break;
14757 if (tries-- == 0) {
14758 printf("pid %d failed to start\n", (int)getpid());
14764 child_status[i] = getpid();
14766 while (child_status[i] && timeval_elapsed(&start) < 5) smb_msleep(2);
14768 child_status_out[i] = fn(i);
14775 for (i=0;i<torture_nprocs;i++) {
14776 if (child_status[i]) synccount++;
14778 if (synccount == torture_nprocs) break;
14780 } while (timeval_elapsed(&start) < 30);
14782 if (synccount != torture_nprocs) {
14783 printf("FAILED TO START %d CLIENTS (started %d)\n", torture_nprocs, synccount);
14785 return timeval_elapsed(&start);
14788 /* start the client load */
14789 start = timeval_current();
14791 for (i=0;i<torture_nprocs;i++) {
14792 child_status[i] = 0;
14795 printf("%d clients started\n", torture_nprocs);
14797 for (i=0;i<torture_nprocs;i++) {
14798 while (waitpid(0, &status, 0) == -1 && errno == EINTR) /* noop */ ;
14803 for (i=0;i<torture_nprocs;i++) {
14804 if (!child_status_out[i]) {
14808 return timeval_elapsed(&start);
14811 #define FLAG_MULTIPROC 1
14817 } torture_ops[] = {
14820 .fn = run_fdpasstest,
14824 .fn = run_locktest1,
14828 .fn = run_locktest2,
14832 .fn = run_locktest3,
14836 .fn = run_locktest4,
14840 .fn = run_locktest5,
14844 .fn = run_locktest6,
14848 .fn = run_locktest7,
14852 .fn = run_locktest8,
14856 .fn = run_locktest9a,
14860 .fn = run_locktest9b,
14864 .fn = run_locktest10,
14868 .fn = run_locktest11,
14872 .fn = run_locktest12,
14876 .fn = run_locktest13,
14880 .fn = run_unlinktest,
14884 .fn = run_browsetest,
14888 .fn = run_attrtest,
14892 .fn = run_trans2test,
14896 .fn = run_maxfidtest,
14897 .flags = FLAG_MULTIPROC,
14902 .flags = FLAG_MULTIPROC,
14905 .name = "RANDOMIPC",
14906 .fn = run_randomipc,
14909 .name = "NEGNOWAIT",
14910 .fn = run_negprot_nowait,
14932 #ifdef HAVE_KERNEL_OPLOCKS_LINUX
14944 .fn = run_dirtest1,
14947 .name = "DIR-CREATETIME",
14948 .fn = run_dir_createtime,
14952 .fn = torture_denytest1,
14956 .fn = torture_denytest2,
14960 .fn = run_tcon_test,
14964 .fn = run_tcon_devtype_test,
14968 .fn = run_readwritetest,
14972 .fn = run_readwritemulti,
14973 .flags = FLAG_MULTIPROC
14977 .fn = run_readwritelarge,
14980 .name = "RW-SIGNING",
14981 .fn = run_readwritelarge_signtest,
14985 .fn = run_opentest,
14989 .fn = run_simple_posix_open_test,
14992 .name = "POSIX-APPEND",
14993 .fn = run_posix_append,
14996 .name = "POSIX-SYMLINK-ACL",
14997 .fn = run_acl_symlink_test,
15000 .name = "POSIX-SYMLINK-EA",
15001 .fn = run_ea_symlink_test,
15004 .name = "POSIX-STREAM-DELETE",
15005 .fn = run_posix_stream_delete,
15008 .name = "POSIX-OFD-LOCK",
15009 .fn = run_posix_ofd_lock_test,
15012 .name = "POSIX-BLOCKING-LOCK",
15013 .fn = run_posix_blocking_lock,
15016 .name = "POSIX-MKDIR",
15017 .fn = run_posix_mkdir_test,
15020 .name = "POSIX-ACL-OPLOCK",
15021 .fn = run_posix_acl_oplock_test,
15024 .name = "POSIX-ACL-SHAREROOT",
15025 .fn = run_posix_acl_shareroot_test,
15028 .name = "POSIX-LS-WILDCARD",
15029 .fn = run_posix_ls_wildcard_test,
15032 .name = "POSIX-LS-SINGLE",
15033 .fn = run_posix_ls_single_test,
15036 .name = "POSIX-READLINK",
15037 .fn = run_posix_readlink_test,
15040 .name = "POSIX-STAT",
15041 .fn = run_posix_stat_test,
15044 .name = "POSIX-SYMLINK-PARENT",
15045 .fn = run_posix_symlink_parent_test,
15048 .name = "POSIX-SYMLINK-CHMOD",
15049 .fn = run_posix_symlink_chmod_test,
15052 .name = "POSIX-SYMLINK-RENAME",
15053 .fn = run_posix_symlink_rename_test,
15056 .name = "POSIX-DIR-DEFAULT-ACL",
15057 .fn = run_posix_dir_default_acl_test,
15060 .name = "POSIX-SYMLINK-GETPATHINFO",
15061 .fn = run_posix_symlink_getpathinfo_test,
15064 .name = "POSIX-SYMLINK-SETPATHINFO",
15065 .fn = run_posix_symlink_setpathinfo_test,
15068 .name = "WINDOWS-BAD-SYMLINK",
15069 .fn = run_symlink_open_test,
15072 .name = "SMB1-WILD-MANGLE-UNLINK",
15073 .fn = run_smb1_wild_mangle_unlink_test,
15076 .name = "SMB1-WILD-MANGLE-RENAME",
15077 .fn = run_smb1_wild_mangle_rename_test,
15080 .name = "CASE-INSENSITIVE-CREATE",
15081 .fn = run_case_insensitive_create,
15084 .name = "ASYNC-ECHO",
15085 .fn = run_async_echo,
15088 .name = "UID-REGRESSION-TEST",
15089 .fn = run_uid_regression_test,
15092 .name = "SHORTNAME-TEST",
15093 .fn = run_shortname_test,
15096 .name = "ADDRCHANGE",
15097 .fn = run_addrchange,
15101 .name = "OPENATTR",
15102 .fn = run_openattrtest,
15114 .name = "RENAME-ACCESS",
15115 .fn = run_rename_access,
15118 .name = "OWNER-RIGHTS",
15119 .fn = run_owner_rights,
15123 .fn = run_deletetest,
15126 .name = "DELETE-STREAM",
15127 .fn = run_delete_stream,
15130 .name = "DELETE-PRINT",
15131 .fn = run_delete_print_test,
15134 .name = "DELETE-LN",
15135 .fn = run_deletetest_ln,
15138 .name = "PROPERTIES",
15139 .fn = run_properties,
15143 .fn = torture_mangle,
15150 .name = "MANGLE-ILLEGAL",
15151 .fn = run_mangle_illegal,
15158 .name = "TRANS2SCAN",
15159 .fn = torture_trans2_scan,
15162 .name = "NTTRANSSCAN",
15163 .fn = torture_nttrans_scan,
15167 .fn = torture_utable,
15170 .name = "CASETABLE",
15171 .fn = torture_casetable,
15174 .name = "ERRMAPEXTRACT",
15175 .fn = run_error_map_extract,
15178 .name = "PIPE_NUMBER",
15179 .fn = run_pipe_number,
15183 .fn = run_tcon2_test,
15187 .fn = torture_ioctl_test,
15191 .fn = torture_chkpath_test,
15195 .fn = run_fdsesstest,
15202 .name = "SESSSETUP_BENCH",
15203 .fn = run_sesssetup_bench,
15218 .name = "WINDOWS-WRITE",
15219 .fn = run_windows_write,
15222 .name = "LARGE_READX",
15223 .fn = run_large_readx,
15226 .name = "MSDFS-ATTRIBUTE",
15227 .fn = run_msdfs_attribute,
15230 .name = "NTTRANS-CREATE",
15231 .fn = run_nttrans_create,
15234 .name = "NTTRANS-FSCTL",
15235 .fn = run_nttrans_fsctl,
15238 .name = "CLI_ECHO",
15239 .fn = run_cli_echo,
15242 .name = "CLI_SPLICE",
15243 .fn = run_cli_splice,
15250 .name = "STREAMERROR",
15251 .fn = run_streamerror,
15254 .name = "NOTIFY-BENCH",
15255 .fn = run_notify_bench,
15258 .name = "NOTIFY-BENCH2",
15259 .fn = run_notify_bench2,
15262 .name = "NOTIFY-BENCH3",
15263 .fn = run_notify_bench3,
15266 .name = "BAD-NBT-SESSION",
15267 .fn = run_bad_nbt_session,
15270 .name = "IGN-BAD-NEGPROT",
15271 .fn = run_ign_bad_negprot,
15274 .name = "SMB-ANY-CONNECT",
15275 .fn = run_smb_any_connect,
15278 .name = "NOTIFY-ONLINE",
15279 .fn = run_notify_online,
15282 .name = "SMB2-BASIC",
15283 .fn = run_smb2_basic,
15286 .name = "SMB2-NEGPROT",
15287 .fn = run_smb2_negprot,
15290 .name = "SMB2-ANONYMOUS",
15291 .fn = run_smb2_anonymous,
15294 .name = "SMB2-SESSION-RECONNECT",
15295 .fn = run_smb2_session_reconnect,
15298 .name = "SMB2-TCON-DEPENDENCE",
15299 .fn = run_smb2_tcon_dependence,
15302 .name = "SMB2-MULTI-CHANNEL",
15303 .fn = run_smb2_multi_channel,
15306 .name = "SMB2-SESSION-REAUTH",
15307 .fn = run_smb2_session_reauth,
15310 .name = "SMB2-FTRUNCATE",
15311 .fn = run_smb2_ftruncate,
15314 .name = "SMB2-DIR-FSYNC",
15315 .fn = run_smb2_dir_fsync,
15318 .name = "SMB2-PATH-SLASH",
15319 .fn = run_smb2_path_slash,
15322 .name = "SMB1-SYSTEM-SECURITY",
15323 .fn = run_smb1_system_security,
15326 .name = "SMB2-SACL",
15327 .fn = run_smb2_sacl,
15330 .name = "SMB2-QUOTA1",
15331 .fn = run_smb2_quota1,
15334 .name = "SMB2-STREAM-ACL",
15335 .fn = run_smb2_stream_acl,
15338 .name = "SMB2-LIST-DIR-ASYNC",
15339 .fn = run_list_dir_async_test,
15342 .name = "SMB2-DEL-ON-CLOSE-NONEMPTY",
15343 .fn = run_delete_on_close_non_empty,
15346 .name = "SMB2-DEL-ON-CLOSE-NONWRITE-DELETE-YES",
15347 .fn = run_delete_on_close_nonwrite_delete_yes_test,
15350 .name = "SMB2-DEL-ON-CLOSE-NONWRITE-DELETE-NO",
15351 .fn = run_delete_on_close_nonwrite_delete_no_test,
15354 .name = "CLEANUP1",
15355 .fn = run_cleanup1,
15358 .name = "CLEANUP2",
15359 .fn = run_cleanup2,
15362 .name = "CLEANUP4",
15363 .fn = run_cleanup4,
15366 .name = "OPLOCK-CANCEL",
15367 .fn = run_oplock_cancel,
15374 .name = "LOCAL-SUBSTITUTE",
15375 .fn = run_local_substitute,
15378 .name = "LOCAL-GENCACHE",
15379 .fn = run_local_gencache,
15382 .name = "LOCAL-DBWRAP-WATCH1",
15383 .fn = run_dbwrap_watch1,
15386 .name = "LOCAL-DBWRAP-WATCH2",
15387 .fn = run_dbwrap_watch2,
15390 .name = "LOCAL-DBWRAP-WATCH3",
15391 .fn = run_dbwrap_watch3,
15394 .name = "LOCAL-DBWRAP-WATCH4",
15395 .fn = run_dbwrap_watch4,
15398 .name = "LOCAL-DBWRAP-DO-LOCKED1",
15399 .fn = run_dbwrap_do_locked1,
15402 .name = "LOCAL-MESSAGING-READ1",
15403 .fn = run_messaging_read1,
15406 .name = "LOCAL-MESSAGING-READ2",
15407 .fn = run_messaging_read2,
15410 .name = "LOCAL-MESSAGING-READ3",
15411 .fn = run_messaging_read3,
15414 .name = "LOCAL-MESSAGING-READ4",
15415 .fn = run_messaging_read4,
15418 .name = "LOCAL-MESSAGING-FDPASS1",
15419 .fn = run_messaging_fdpass1,
15422 .name = "LOCAL-MESSAGING-FDPASS2",
15423 .fn = run_messaging_fdpass2,
15426 .name = "LOCAL-MESSAGING-FDPASS2a",
15427 .fn = run_messaging_fdpass2a,
15430 .name = "LOCAL-MESSAGING-FDPASS2b",
15431 .fn = run_messaging_fdpass2b,
15434 .name = "LOCAL-MESSAGING-SEND-ALL",
15435 .fn = run_messaging_send_all,
15438 .name = "LOCAL-BASE64",
15439 .fn = run_local_base64,
15442 .name = "LOCAL-RBTREE",
15443 .fn = run_local_rbtree,
15446 .name = "LOCAL-MEMCACHE",
15447 .fn = run_local_memcache,
15450 .name = "LOCAL-STREAM-NAME",
15451 .fn = run_local_stream_name,
15454 .name = "LOCAL-STR-MATCH-MSWILD",
15455 .fn = run_str_match_mswild,
15458 .name = "LOCAL-STR-MATCH-REGEX-SUB1",
15459 .fn = run_str_match_regex_sub1,
15462 .name = "WBCLIENT-MULTI-PING",
15463 .fn = run_wbclient_multi_ping,
15466 .name = "LOCAL-string_to_sid",
15467 .fn = run_local_string_to_sid,
15470 .name = "LOCAL-sid_to_string",
15471 .fn = run_local_sid_to_string,
15474 .name = "LOCAL-binary_to_sid",
15475 .fn = run_local_binary_to_sid,
15478 .name = "LOCAL-DBTRANS",
15479 .fn = run_local_dbtrans,
15482 .name = "LOCAL-TEVENT-POLL",
15483 .fn = run_local_tevent_poll,
15486 .name = "LOCAL-CONVERT-STRING",
15487 .fn = run_local_convert_string,
15490 .name = "LOCAL-CONV-AUTH-INFO",
15491 .fn = run_local_conv_auth_info,
15494 .name = "LOCAL-hex_encode_buf",
15495 .fn = run_local_hex_encode_buf,
15498 .name = "LOCAL-IDMAP-TDB-COMMON",
15499 .fn = run_idmap_tdb_common_test,
15502 .name = "LOCAL-remove_duplicate_addrs2",
15503 .fn = run_local_remove_duplicate_addrs2,
15506 .name = "local-tdb-opener",
15507 .fn = run_local_tdb_opener,
15510 .name = "local-tdb-writer",
15511 .fn = run_local_tdb_writer,
15514 .name = "LOCAL-DBWRAP-CTDB1",
15515 .fn = run_local_dbwrap_ctdb1,
15518 .name = "LOCAL-BENCH-PTHREADPOOL",
15519 .fn = run_bench_pthreadpool,
15522 .name = "LOCAL-PTHREADPOOL-TEVENT",
15523 .fn = run_pthreadpool_tevent,
15526 .name = "LOCAL-G-LOCK1",
15530 .name = "LOCAL-G-LOCK2",
15534 .name = "LOCAL-G-LOCK3",
15538 .name = "LOCAL-G-LOCK4",
15542 .name = "LOCAL-G-LOCK4A",
15543 .fn = run_g_lock4a,
15546 .name = "LOCAL-G-LOCK5",
15550 .name = "LOCAL-G-LOCK6",
15554 .name = "LOCAL-G-LOCK7",
15558 .name = "LOCAL-G-LOCK8",
15562 .name = "LOCAL-G-LOCK-PING-PONG",
15563 .fn = run_g_lock_ping_pong,
15566 .name = "LOCAL-CANONICALIZE-PATH",
15567 .fn = run_local_canonicalize_path,
15570 .name = "LOCAL-NAMEMAP-CACHE1",
15571 .fn = run_local_namemap_cache1,
15574 .name = "LOCAL-IDMAP-CACHE1",
15575 .fn = run_local_idmap_cache1,
15578 .name = "qpathinfo-bufsize",
15579 .fn = run_qpathinfo_bufsize,
15582 .name = "hide-new-files-timeout",
15583 .fn = run_hidenewfiles,
15585 #ifdef CLUSTER_SUPPORT
15587 .name = "ctdbd-conn1",
15588 .fn = run_ctdbd_conn1,
15592 .name = "readdir-timestamp",
15593 .fn = run_readdir_timestamp,
15600 /****************************************************************************
15601 run a specified test or "ALL"
15602 ****************************************************************************/
15603 static bool run_test(const char *name)
15606 bool result = True;
15607 bool found = False;
15610 if (strequal(name,"ALL")) {
15611 for (i=0;torture_ops[i].name;i++) {
15612 run_test(torture_ops[i].name);
15617 for (i=0;torture_ops[i].name;i++) {
15618 fstr_sprintf(randomfname, "\\XX%x",
15619 (unsigned)random());
15621 if (strequal(name, torture_ops[i].name)) {
15623 printf("Running %s\n", name);
15624 if (torture_ops[i].flags & FLAG_MULTIPROC) {
15625 t = create_procs(torture_ops[i].fn, &result);
15628 printf("TEST %s FAILED!\n", name);
15631 struct timeval start;
15632 start = timeval_current();
15633 if (!torture_ops[i].fn(0)) {
15635 printf("TEST %s FAILED!\n", name);
15637 t = timeval_elapsed(&start);
15639 printf("%s took %g secs\n\n", name, t);
15644 printf("Did not find a test named %s\n", name);
15652 static void usage(void)
15656 printf("WARNING samba4 test suite is much more complete nowadays.\n");
15657 printf("Please use samba4 torture.\n\n");
15659 printf("Usage: smbtorture //server/share <options> TEST1 TEST2 ...\n");
15661 printf("\t-d debuglevel\n");
15662 printf("\t-U user%%pass\n");
15663 printf("\t-k use kerberos\n");
15664 printf("\t-N numprocs\n");
15665 printf("\t-n my_netbios_name\n");
15666 printf("\t-W workgroup\n");
15667 printf("\t-o num_operations\n");
15668 printf("\t-O socket_options\n");
15669 printf("\t-m maximum protocol\n");
15670 printf("\t-L use oplocks\n");
15671 printf("\t-c CLIENT.TXT specify client load file for NBENCH\n");
15672 printf("\t-A showall\n");
15673 printf("\t-p port\n");
15674 printf("\t-s seed\n");
15675 printf("\t-b unclist_filename specify multiple shares for multiple connections\n");
15676 printf("\t-f filename filename to test\n");
15677 printf("\t-e encrypt\n");
15680 printf("tests are:");
15681 for (i=0;torture_ops[i].name;i++) {
15682 printf(" %s", torture_ops[i].name);
15686 printf("default test is ALL\n");
15691 /****************************************************************************
15693 ****************************************************************************/
15694 int main(int argc,char *argv[])
15700 bool correct = True;
15701 TALLOC_CTX *frame = talloc_stackframe();
15702 int seed = time(NULL);
15704 #ifdef HAVE_SETBUFFER
15705 setbuffer(stdout, NULL, 0);
15708 setup_logging("smbtorture", DEBUG_STDOUT);
15713 if (is_default_dyn_CONFIGFILE()) {
15714 if(getenv("SMB_CONF_PATH")) {
15715 set_dyn_CONFIGFILE(getenv("SMB_CONF_PATH"));
15718 lp_load_global(get_dyn_CONFIGFILE());
15725 for(p = argv[1]; *p; p++)
15729 if (strncmp(argv[1], "//", 2)) {
15733 fstrcpy(host, &argv[1][2]);
15734 p = strchr_m(&host[2],'/');
15739 fstrcpy(share, p+1);
15741 fstrcpy(myname, get_myname(talloc_tos()));
15743 fprintf(stderr, "Failed to get my hostname.\n");
15747 if (*username == 0 && getenv("LOGNAME")) {
15748 fstrcpy(username,getenv("LOGNAME"));
15754 fstrcpy(workgroup, lp_workgroup());
15756 while ((opt = getopt(argc, argv, "p:hW:U:n:N:O:o:m:Ll:d:Aec:ks:b:B:f:"))
15760 port_to_use = atoi(optarg);
15763 seed = atoi(optarg);
15766 fstrcpy(workgroup,optarg);
15769 lp_set_cmdline("client max protocol", optarg);
15772 torture_nprocs = atoi(optarg);
15775 torture_numops = atoi(optarg);
15778 lp_set_cmdline("log level", optarg);
15784 use_oplocks = True;
15787 local_path = optarg;
15790 torture_showall = True;
15793 fstrcpy(myname, optarg);
15796 client_txt = optarg;
15803 use_kerberos = True;
15805 d_printf("No kerberos support compiled in\n");
15811 fstrcpy(username,optarg);
15812 p = strchr_m(username,'%');
15815 fstrcpy(password, p+1);
15820 fstrcpy(multishare_conn_fname, optarg);
15821 use_multishare_conn = True;
15824 torture_blocksize = atoi(optarg);
15827 test_filename = SMB_STRDUP(optarg);
15830 printf("Unknown option %c (%d)\n", (char)opt, opt);
15835 d_printf("using seed %d\n", seed);
15839 if(use_kerberos && !gotuser) gotpass = True;
15842 char pwd[256] = {0};
15845 rc = samba_getpass("Password:", pwd, sizeof(pwd), false, false);
15847 fstrcpy(password, pwd);
15852 printf("host=%s share=%s user=%s myname=%s\n",
15853 host, share, username, myname);
15855 torture_creds = cli_session_creds_init(frame,
15861 false, /* fallback_after_kerberos */
15862 false, /* use_ccache */
15863 false); /* password_is_nt_hash */
15864 if (torture_creds == NULL) {
15865 d_printf("cli_session_creds_init() failed.\n");
15869 if (argc == optind) {
15870 correct = run_test("ALL");
15872 for (i=optind;i<argc;i++) {
15873 if (!run_test(argv[i])) {
15879 TALLOC_FREE(frame);