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(
3969 if (!tevent_req_poll(req, ev)) {
3970 d_fprintf(stderr, "tevent_req_poll failed: %s\n",
3978 if (torture_close_connection(cli)) {
3982 printf("finished negprot nowait test\n");
3987 /* send smb negprot commands, not reading the response */
3988 static bool run_bad_nbt_session(int dummy)
3990 struct nmb_name called, calling;
3991 struct sockaddr_storage ss;
3996 printf("starting bad nbt session test\n");
3998 make_nmb_name(&calling, myname, 0x0);
3999 make_nmb_name(&called , host, 0x20);
4001 if (!resolve_name(host, &ss, 0x20, true)) {
4002 d_fprintf(stderr, "Could not resolve name %s\n", host);
4006 status = open_socket_out(&ss, NBT_SMB_PORT, 10000, &fd);
4007 if (!NT_STATUS_IS_OK(status)) {
4008 d_fprintf(stderr, "open_socket_out failed: %s\n",
4013 ret = cli_bad_session_request(fd, &calling, &called);
4016 d_fprintf(stderr, "open_socket_out failed: %s\n",
4021 printf("finished bad nbt session test\n");
4025 /* send random IPC commands */
4026 static bool run_randomipc(int dummy)
4028 char *rparam = NULL;
4030 unsigned int rdrcnt,rprcnt;
4032 int api, param_len, i;
4033 struct cli_state *cli;
4034 bool correct = True;
4037 printf("starting random ipc test\n");
4039 if (!torture_open_connection(&cli, 0)) {
4043 for (i=0;i<count;i++) {
4044 api = sys_random() % 500;
4045 param_len = (sys_random() % 64);
4047 rand_buf(param, param_len);
4052 param, param_len, 8,
4053 NULL, 0, CLI_BUFFER_SIZE,
4057 printf("%d/%d\r", i,count);
4060 printf("%d/%d\n", i, count);
4062 if (!torture_close_connection(cli)) {
4069 printf("finished random ipc test\n");
4076 static void browse_callback(const char *sname, uint32_t stype,
4077 const char *comment, void *state)
4079 printf("\t%20.20s %08x %s\n", sname, stype, comment);
4085 This test checks the browse list code
4088 static bool run_browsetest(int dummy)
4090 static struct cli_state *cli;
4091 bool correct = True;
4093 printf("starting browse test\n");
4095 if (!torture_open_connection(&cli, 0)) {
4099 printf("domain list:\n");
4100 cli_NetServerEnum(cli, cli->server_domain,
4101 SV_TYPE_DOMAIN_ENUM,
4102 browse_callback, NULL);
4104 printf("machine list:\n");
4105 cli_NetServerEnum(cli, cli->server_domain,
4107 browse_callback, NULL);
4109 if (!torture_close_connection(cli)) {
4113 printf("browse test finished\n");
4119 static bool check_attributes(struct cli_state *cli,
4121 uint32_t expected_attrs)
4124 NTSTATUS status = cli_getatr(cli,
4129 if (!NT_STATUS_IS_OK(status)) {
4130 printf("cli_getatr failed with %s\n",
4134 if (attrs != expected_attrs) {
4135 printf("Attributes incorrect 0x%x, should be 0x%x\n",
4136 (unsigned int)attrs,
4137 (unsigned int)expected_attrs);
4144 This checks how the getatr calls works
4146 static bool run_attrtest(int dummy)
4148 struct cli_state *cli;
4151 const char *fname = "\\attrib123456789.tst";
4152 bool correct = True;
4155 printf("starting attrib test\n");
4157 if (!torture_open_connection(&cli, 0)) {
4161 /* Ensure we can't unlink with out-of-range (unknown) attribute. */
4162 status = cli_unlink(cli, fname, 0x20000);
4163 if (!NT_STATUS_EQUAL(status, NT_STATUS_INVALID_PARAMETER)) {
4168 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4169 cli_openx(cli, fname,
4170 O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum);
4171 cli_close(cli, fnum);
4173 status = cli_getatr(cli, fname, NULL, NULL, &t);
4174 if (!NT_STATUS_IS_OK(status)) {
4175 printf("getatr failed (%s)\n", nt_errstr(status));
4179 if (labs(t - time(NULL)) > 60*60*24*10) {
4180 printf("ERROR: SMBgetatr bug. time is %s",
4186 t2 = t-60*60*24; /* 1 day ago */
4188 /* Ensure we can't set with out-of-range (unknown) attribute. */
4189 status = cli_setatr(cli, fname, 0x20000, t2);
4190 if (!NT_STATUS_EQUAL(status, NT_STATUS_INVALID_PARAMETER)) {
4195 status = cli_setatr(cli, fname, 0, t2);
4196 if (!NT_STATUS_IS_OK(status)) {
4197 printf("setatr failed (%s)\n", nt_errstr(status));
4201 status = cli_getatr(cli, fname, NULL, NULL, &t);
4202 if (!NT_STATUS_IS_OK(status)) {
4203 printf("getatr failed (%s)\n", nt_errstr(status));
4208 printf("ERROR: getatr/setatr bug. times are\n%s",
4210 printf("%s", ctime(&t2));
4214 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4216 /* Check cli_setpathinfo_ext() */
4217 /* Re-create the file. */
4218 status = cli_openx(cli, fname,
4219 O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum);
4220 if (!NT_STATUS_IS_OK(status)) {
4221 printf("Failed to recreate %s (%s)\n",
4222 fname, nt_errstr(status));
4225 cli_close(cli, fnum);
4227 status = cli_setpathinfo_ext(
4230 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* create */
4231 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* access */
4232 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* write */
4233 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* change */
4234 FILE_ATTRIBUTE_SYSTEM |
4235 FILE_ATTRIBUTE_HIDDEN |
4236 FILE_ATTRIBUTE_READONLY);
4237 if (!NT_STATUS_IS_OK(status)) {
4238 printf("cli_setpathinfo_ext failed with %s\n",
4243 /* Check attributes are correct. */
4244 correct = check_attributes(cli,
4246 FILE_ATTRIBUTE_SYSTEM |
4247 FILE_ATTRIBUTE_HIDDEN |
4248 FILE_ATTRIBUTE_READONLY);
4249 if (correct == false) {
4253 /* Setting to FILE_ATTRIBUTE_NORMAL should be ignored. */
4254 status = cli_setpathinfo_ext(
4257 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* create */
4258 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* access */
4259 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* write */
4260 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* change */
4261 FILE_ATTRIBUTE_NORMAL);
4262 if (!NT_STATUS_IS_OK(status)) {
4263 printf("cli_setpathinfo_ext failed with %s\n",
4268 /* Check attributes are correct. */
4269 correct = check_attributes(cli,
4271 FILE_ATTRIBUTE_SYSTEM |
4272 FILE_ATTRIBUTE_HIDDEN |
4273 FILE_ATTRIBUTE_READONLY);
4274 if (correct == false) {
4278 /* Setting to (uint16_t)-1 should also be ignored. */
4279 status = cli_setpathinfo_ext(
4282 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* create */
4283 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* access */
4284 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* write */
4285 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* change */
4287 if (!NT_STATUS_IS_OK(status)) {
4288 printf("cli_setpathinfo_ext failed with %s\n",
4293 /* Check attributes are correct. */
4294 correct = check_attributes(cli,
4296 FILE_ATTRIBUTE_SYSTEM |
4297 FILE_ATTRIBUTE_HIDDEN |
4298 FILE_ATTRIBUTE_READONLY);
4299 if (correct == false) {
4303 /* Setting to 0 should clear them all. */
4304 status = cli_setpathinfo_ext(
4307 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* create */
4308 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* access */
4309 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* write */
4310 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* change */
4312 if (!NT_STATUS_IS_OK(status)) {
4313 printf("cli_setpathinfo_ext failed with %s\n",
4318 /* Check attributes are correct. */
4319 correct = check_attributes(cli,
4321 FILE_ATTRIBUTE_NORMAL);
4322 if (correct == false) {
4330 FILE_ATTRIBUTE_SYSTEM |
4331 FILE_ATTRIBUTE_HIDDEN|
4332 FILE_ATTRIBUTE_READONLY);
4334 if (!torture_close_connection(cli)) {
4338 printf("attrib test finished\n");
4343 static NTSTATUS cli_qfilename(
4344 struct cli_state *cli,
4346 TALLOC_CTX *mem_ctx,
4349 uint16_t recv_flags2;
4356 status = cli_qfileinfo(talloc_tos(), cli, fnum,
4357 SMB_QUERY_FILE_NAME_INFO,
4358 4, CLI_BUFFER_SIZE, &recv_flags2,
4359 &rdata, &num_rdata);
4360 if (!NT_STATUS_IS_OK(status)) {
4364 namelen = IVAL(rdata, 0);
4365 if (namelen > (num_rdata - 4)) {
4367 return NT_STATUS_INVALID_NETWORK_RESPONSE;
4370 pull_string_talloc(mem_ctx,
4371 (const char *)rdata,
4378 status = map_nt_error_from_unix(errno);
4385 return NT_STATUS_OK;
4389 This checks a couple of trans2 calls
4391 static bool run_trans2test(int dummy)
4393 struct cli_state *cli;
4396 time_t c_time, a_time, m_time;
4397 struct timespec c_time_ts, a_time_ts, m_time_ts, w_time_ts, m_time2_ts;
4398 const char *fname = "\\trans2.tst";
4399 const char *dname = "\\trans2";
4400 const char *fname2 = "\\trans2\\trans2.tst";
4402 bool correct = True;
4407 printf("starting trans2 test\n");
4409 if (!torture_open_connection(&cli, 0)) {
4413 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
4414 /* Ensure ino is zero, SMB2 gets a real one. */
4417 /* Ensure ino is -1, SMB1 never gets a real one. */
4421 status = cli_get_fs_attr_info(cli, &fs_attr);
4422 if (!NT_STATUS_IS_OK(status)) {
4423 printf("ERROR: cli_get_fs_attr_info returned %s\n",
4428 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4429 cli_openx(cli, fname, O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum);
4430 status = cli_qfileinfo_basic(cli, fnum, NULL, &size, &c_time_ts,
4431 &a_time_ts, &w_time_ts, &m_time_ts, NULL);
4432 if (!NT_STATUS_IS_OK(status)) {
4433 printf("ERROR: qfileinfo failed (%s)\n", nt_errstr(status));
4437 status = cli_qfilename(cli, fnum, talloc_tos(), &pname);
4438 if (!NT_STATUS_IS_OK(status)) {
4439 printf("ERROR: qfilename failed (%s)\n", nt_errstr(status));
4442 else if (strcmp(pname, fname)) {
4443 printf("qfilename gave different name? [%s] [%s]\n",
4448 cli_close(cli, fnum);
4452 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4453 status = cli_openx(cli, fname, O_RDWR | O_CREAT | O_TRUNC, DENY_NONE,
4455 if (!NT_STATUS_IS_OK(status)) {
4456 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
4459 cli_close(cli, fnum);
4461 status = cli_qpathinfo1(cli, fname, &c_time, &a_time, &m_time, &size,
4463 if (!NT_STATUS_IS_OK(status)) {
4464 printf("ERROR: qpathinfo failed (%s)\n", nt_errstr(status));
4467 time_t t = time(NULL);
4469 if (c_time != m_time) {
4470 printf("create time=%s", ctime(&c_time));
4471 printf("modify time=%s", ctime(&m_time));
4472 printf("This system appears to have sticky create times\n");
4474 if ((labs(a_time - t) > 60) && (a_time % (60*60) == 0)) {
4475 printf("access time=%s", ctime(&a_time));
4476 printf("This system appears to set a midnight access time\n");
4480 if (labs(m_time - t) > 60*60*24*7) {
4481 printf("ERROR: totally incorrect times - maybe word reversed? mtime=%s", ctime(&m_time));
4487 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4488 cli_openx(cli, fname,
4489 O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum);
4490 cli_close(cli, fnum);
4491 status = cli_qpathinfo2(cli, fname, &c_time_ts, &a_time_ts, &w_time_ts,
4492 &m_time_ts, &size, NULL, &ino);
4493 if (!NT_STATUS_IS_OK(status)) {
4494 printf("ERROR: qpathinfo2 failed (%s)\n", nt_errstr(status));
4497 if (w_time_ts.tv_sec < 60*60*24*2) {
4498 printf("write time=%s", ctime(&w_time_ts.tv_sec));
4499 printf("This system appears to set a initial 0 write time\n");
4502 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
4503 /* SMB2 should always return an inode. */
4505 printf("SMB2 bad inode (0)\n");
4509 /* SMB1 must always return zero here. */
4511 printf("SMB1 bad inode (!0)\n");
4517 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4520 /* check if the server updates the directory modification time
4521 when creating a new file */
4522 status = cli_mkdir(cli, dname);
4523 if (!NT_STATUS_IS_OK(status)) {
4524 printf("ERROR: mkdir failed (%s)\n", nt_errstr(status));
4528 status = cli_qpathinfo2(cli, "\\trans2\\", &c_time_ts, &a_time_ts,
4529 &w_time_ts, &m_time_ts, &size, NULL, NULL);
4530 if (!NT_STATUS_IS_OK(status)) {
4531 printf("ERROR: qpathinfo2 failed (%s)\n", nt_errstr(status));
4535 cli_openx(cli, fname2,
4536 O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum);
4537 cli_writeall(cli, fnum, 0, (uint8_t *)&fnum, 0, sizeof(fnum), NULL);
4538 cli_close(cli, fnum);
4539 status = cli_qpathinfo2(cli, "\\trans2\\", &c_time_ts, &a_time_ts,
4540 &w_time_ts, &m_time2_ts, &size, NULL, NULL);
4541 if (!NT_STATUS_IS_OK(status)) {
4542 printf("ERROR: qpathinfo2 failed (%s)\n", nt_errstr(status));
4545 if (memcmp(&m_time_ts, &m_time2_ts, sizeof(struct timespec))
4547 printf("This system does not update directory modification times\n");
4551 cli_unlink(cli, fname2, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4552 cli_rmdir(cli, dname);
4554 if (!torture_close_connection(cli)) {
4558 printf("trans2 test finished\n");
4564 This checks new W2K calls.
4567 static NTSTATUS new_trans(struct cli_state *pcli, int fnum, int level)
4569 uint8_t *buf = NULL;
4573 status = cli_qfileinfo(talloc_tos(), pcli, fnum, level, 0,
4574 CLI_BUFFER_SIZE, NULL, &buf, &len);
4575 if (!NT_STATUS_IS_OK(status)) {
4576 printf("ERROR: qfileinfo (%d) failed (%s)\n", level,
4579 printf("qfileinfo: level %d, len = %u\n", level, len);
4580 dump_data(0, (uint8_t *)buf, len);
4587 static bool run_w2ktest(int dummy)
4589 struct cli_state *cli;
4591 const char *fname = "\\w2ktest\\w2k.tst";
4593 bool correct = True;
4595 printf("starting w2k test\n");
4597 if (!torture_open_connection(&cli, 0)) {
4601 cli_openx(cli, fname,
4602 O_RDWR | O_CREAT , DENY_NONE, &fnum);
4604 for (level = 1004; level < 1040; level++) {
4605 new_trans(cli, fnum, level);
4608 cli_close(cli, fnum);
4610 if (!torture_close_connection(cli)) {
4614 printf("w2k test finished\n");
4621 this is a harness for some oplock tests
4623 static bool run_oplock1(int dummy)
4625 struct cli_state *cli1;
4626 const char *fname = "\\lockt1.lck";
4628 bool correct = True;
4631 printf("starting oplock test 1\n");
4633 if (!torture_open_connection(&cli1, 0)) {
4637 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4639 smbXcli_conn_set_sockopt(cli1->conn, sockops);
4641 cli1->use_oplocks = True;
4643 status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
4645 if (!NT_STATUS_IS_OK(status)) {
4646 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
4650 cli1->use_oplocks = False;
4652 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4653 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4655 status = cli_close(cli1, fnum1);
4656 if (!NT_STATUS_IS_OK(status)) {
4657 printf("close2 failed (%s)\n", nt_errstr(status));
4661 status = cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4662 if (!NT_STATUS_IS_OK(status)) {
4663 printf("unlink failed (%s)\n", nt_errstr(status));
4667 if (!torture_close_connection(cli1)) {
4671 printf("finished oplock test 1\n");
4676 static bool run_oplock2(int dummy)
4678 struct cli_state *cli1, *cli2;
4679 const char *fname = "\\lockt2.lck";
4680 uint16_t fnum1, fnum2;
4681 int saved_use_oplocks = use_oplocks;
4683 bool correct = True;
4684 volatile bool *shared_correct;
4688 shared_correct = (volatile bool *)anonymous_shared_allocate(sizeof(bool));
4689 *shared_correct = True;
4691 use_level_II_oplocks = True;
4694 printf("starting oplock test 2\n");
4696 if (!torture_open_connection(&cli1, 0)) {
4697 use_level_II_oplocks = False;
4698 use_oplocks = saved_use_oplocks;
4702 if (!torture_open_connection(&cli2, 1)) {
4703 use_level_II_oplocks = False;
4704 use_oplocks = saved_use_oplocks;
4708 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4710 smbXcli_conn_set_sockopt(cli1->conn, sockops);
4711 smbXcli_conn_set_sockopt(cli2->conn, sockops);
4713 status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
4715 if (!NT_STATUS_IS_OK(status)) {
4716 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
4720 /* Don't need the globals any more. */
4721 use_level_II_oplocks = False;
4722 use_oplocks = saved_use_oplocks;
4726 status = cli_openx(cli2, fname, O_RDWR, DENY_NONE, &fnum2);
4727 if (!NT_STATUS_IS_OK(status)) {
4728 printf("second open of %s failed (%s)\n", fname, nt_errstr(status));
4729 *shared_correct = False;
4735 status = cli_close(cli2, fnum2);
4736 if (!NT_STATUS_IS_OK(status)) {
4737 printf("close2 failed (%s)\n", nt_errstr(status));
4738 *shared_correct = False;
4746 /* Ensure cli1 processes the break. Empty file should always return 0
4748 status = cli_read(cli1, fnum1, buf, 0, 4, &nread);
4749 if (!NT_STATUS_IS_OK(status)) {
4750 printf("read on fnum1 failed (%s)\n", nt_errstr(status));
4752 } else if (nread != 0) {
4753 printf("read on empty fnum1 failed. recv %ld expected %d\n",
4754 (unsigned long)nread, 0);
4758 /* Should now be at level II. */
4759 /* Test if sending a write locks causes a break to none. */
4760 status = cli_lock32(cli1, fnum1, 0, 4, 0, READ_LOCK);
4761 if (!NT_STATUS_IS_OK(status)) {
4762 printf("lock failed (%s)\n", nt_errstr(status));
4766 cli_unlock(cli1, fnum1, 0, 4);
4770 status = cli_lock32(cli1, fnum1, 0, 4, 0, WRITE_LOCK);
4771 if (!NT_STATUS_IS_OK(status)) {
4772 printf("lock failed (%s)\n", nt_errstr(status));
4776 cli_unlock(cli1, fnum1, 0, 4);
4780 cli_read(cli1, fnum1, buf, 0, 4, NULL);
4782 status = cli_close(cli1, fnum1);
4783 if (!NT_STATUS_IS_OK(status)) {
4784 printf("close1 failed (%s)\n", nt_errstr(status));
4790 status = cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4791 if (!NT_STATUS_IS_OK(status)) {
4792 printf("unlink failed (%s)\n", nt_errstr(status));
4796 if (!torture_close_connection(cli1)) {
4800 if (!*shared_correct) {
4804 printf("finished oplock test 2\n");
4809 struct oplock4_state {
4810 struct tevent_context *ev;
4811 struct cli_state *cli;
4816 static void oplock4_got_break(struct tevent_req *req);
4817 static void oplock4_got_open(struct tevent_req *req);
4819 static bool run_oplock4(int dummy)
4821 struct tevent_context *ev;
4822 struct cli_state *cli1, *cli2;
4823 struct tevent_req *oplock_req, *open_req;
4824 const char *fname = "\\lockt4.lck";
4825 const char *fname_ln = "\\lockt4_ln.lck";
4826 uint16_t fnum1, fnum2;
4827 int saved_use_oplocks = use_oplocks;
4829 bool correct = true;
4833 struct oplock4_state *state;
4835 printf("starting oplock test 4\n");
4837 if (!torture_open_connection(&cli1, 0)) {
4838 use_level_II_oplocks = false;
4839 use_oplocks = saved_use_oplocks;
4843 if (!torture_open_connection(&cli2, 1)) {
4844 use_level_II_oplocks = false;
4845 use_oplocks = saved_use_oplocks;
4849 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4850 cli_unlink(cli1, fname_ln, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4852 smbXcli_conn_set_sockopt(cli1->conn, sockops);
4853 smbXcli_conn_set_sockopt(cli2->conn, sockops);
4855 /* Create the file. */
4856 status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
4858 if (!NT_STATUS_IS_OK(status)) {
4859 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
4863 status = cli_close(cli1, fnum1);
4864 if (!NT_STATUS_IS_OK(status)) {
4865 printf("close1 failed (%s)\n", nt_errstr(status));
4869 /* Now create a hardlink. */
4870 status = cli_hardlink(cli1, fname, fname_ln);
4871 if (!NT_STATUS_IS_OK(status)) {
4872 printf("nt hardlink failed (%s)\n", nt_errstr(status));
4876 /* Prove that opening hardlinks cause deny modes to conflict. */
4877 status = cli_openx(cli1, fname, O_RDWR, DENY_ALL, &fnum1);
4878 if (!NT_STATUS_IS_OK(status)) {
4879 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
4883 status = cli_openx(cli1, fname_ln, O_RDWR, DENY_NONE, &fnum2);
4884 if (NT_STATUS_IS_OK(status)) {
4885 printf("open of %s succeeded - should fail with sharing violation.\n",
4890 if (!NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
4891 printf("open of %s should fail with sharing violation. Got %s\n",
4892 fname_ln, nt_errstr(status));
4896 status = cli_close(cli1, fnum1);
4897 if (!NT_STATUS_IS_OK(status)) {
4898 printf("close1 failed (%s)\n", nt_errstr(status));
4902 cli1->use_oplocks = true;
4903 cli2->use_oplocks = true;
4905 status = cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
4906 if (!NT_STATUS_IS_OK(status)) {
4907 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
4911 ev = samba_tevent_context_init(talloc_tos());
4913 printf("tevent_context_init failed\n");
4917 state = talloc(ev, struct oplock4_state);
4918 if (state == NULL) {
4919 printf("talloc failed\n");
4924 state->got_break = &got_break;
4925 state->fnum2 = &fnum2;
4927 oplock_req = cli_smb_oplock_break_waiter_send(
4928 talloc_tos(), ev, cli1);
4929 if (oplock_req == NULL) {
4930 printf("cli_smb_oplock_break_waiter_send failed\n");
4933 tevent_req_set_callback(oplock_req, oplock4_got_break, state);
4935 open_req = cli_openx_send(
4936 talloc_tos(), ev, cli2, fname_ln, O_RDWR, DENY_NONE);
4937 if (open_req == NULL) {
4938 printf("cli_openx_send failed\n");
4941 tevent_req_set_callback(open_req, oplock4_got_open, state);
4946 while (!got_break || fnum2 == 0xffff) {
4948 ret = tevent_loop_once(ev);
4950 printf("tevent_loop_once failed: %s\n",
4956 status = cli_close(cli2, fnum2);
4957 if (!NT_STATUS_IS_OK(status)) {
4958 printf("close2 failed (%s)\n", nt_errstr(status));
4962 status = cli_close(cli1, fnum1);
4963 if (!NT_STATUS_IS_OK(status)) {
4964 printf("close1 failed (%s)\n", nt_errstr(status));
4968 status = cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4969 if (!NT_STATUS_IS_OK(status)) {
4970 printf("unlink failed (%s)\n", nt_errstr(status));
4974 status = cli_unlink(cli1, fname_ln, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4975 if (!NT_STATUS_IS_OK(status)) {
4976 printf("unlink failed (%s)\n", nt_errstr(status));
4980 if (!torture_close_connection(cli1)) {
4988 printf("finished oplock test 4\n");
4993 static void oplock4_got_break(struct tevent_req *req)
4995 struct oplock4_state *state = tevent_req_callback_data(
4996 req, struct oplock4_state);
5001 status = cli_smb_oplock_break_waiter_recv(req, &fnum, &level);
5003 if (!NT_STATUS_IS_OK(status)) {
5004 printf("cli_smb_oplock_break_waiter_recv returned %s\n",
5008 *state->got_break = true;
5010 req = cli_oplock_ack_send(state, state->ev, state->cli, fnum,
5013 printf("cli_oplock_ack_send failed\n");
5018 static void oplock4_got_open(struct tevent_req *req)
5020 struct oplock4_state *state = tevent_req_callback_data(
5021 req, struct oplock4_state);
5024 status = cli_openx_recv(req, state->fnum2);
5025 if (!NT_STATUS_IS_OK(status)) {
5026 printf("cli_openx_recv returned %s\n", nt_errstr(status));
5027 *state->fnum2 = 0xffff;
5031 #ifdef HAVE_KERNEL_OPLOCKS_LINUX
5033 struct oplock5_state {
5038 * Async open the file that has a kernel oplock, do an echo to get
5039 * that 100% across, close the file to signal to the child fd that the
5040 * oplock can be dropped, wait for the open reply.
5043 static void oplock5_opened(struct tevent_req *subreq);
5044 static void oplock5_pong(struct tevent_req *subreq);
5045 static void oplock5_timedout(struct tevent_req *subreq);
5047 static struct tevent_req *oplock5_send(
5048 TALLOC_CTX *mem_ctx,
5049 struct tevent_context *ev,
5050 struct cli_state *cli,
5054 struct tevent_req *req = NULL, *subreq = NULL;
5055 struct oplock5_state *state = NULL;
5056 static uint8_t data = 0;
5058 req = tevent_req_create(mem_ctx, &state, struct oplock5_state);
5062 state->pipe_down_fd = pipe_down_fd;
5064 subreq = cli_ntcreate_send(
5070 SEC_FILE_READ_DATA, /* DesiredAccess */
5071 FILE_ATTRIBUTE_NORMAL, /* FileAttributes */
5072 FILE_SHARE_WRITE|FILE_SHARE_READ, /* ShareAccess */
5073 FILE_OPEN, /* CreateDisposition */
5074 FILE_NON_DIRECTORY_FILE, /* CreateOptions */
5075 0, /* Impersonation */
5076 0); /* SecurityFlags */
5077 if (tevent_req_nomem(subreq, req)) {
5078 return tevent_req_post(req, ev);
5080 tevent_req_set_callback(subreq, oplock5_opened, req);
5082 subreq = cli_echo_send(
5087 (DATA_BLOB) { .data = &data, .length = sizeof(data) });
5088 if (tevent_req_nomem(subreq, req)) {
5089 return tevent_req_post(req, ev);
5091 tevent_req_set_callback(subreq, oplock5_pong, req);
5093 subreq = tevent_wakeup_send(state, ev, timeval_current_ofs(20, 0));
5094 if (tevent_req_nomem(subreq, req)) {
5095 return tevent_req_post(req, ev);
5097 tevent_req_set_callback(subreq, oplock5_timedout, req);
5102 static void oplock5_opened(struct tevent_req *subreq)
5104 struct tevent_req *req = tevent_req_callback_data(
5105 subreq, struct tevent_req);
5109 status = cli_ntcreate_recv(subreq, &fnum, NULL);
5110 TALLOC_FREE(subreq);
5111 if (tevent_req_nterror(req, status)) {
5114 tevent_req_done(req);
5117 static void oplock5_pong(struct tevent_req *subreq)
5119 struct tevent_req *req = tevent_req_callback_data(
5120 subreq, struct tevent_req);
5121 struct oplock5_state *state = tevent_req_data(
5122 req, struct oplock5_state);
5125 status = cli_echo_recv(subreq);
5126 TALLOC_FREE(subreq);
5127 if (tevent_req_nterror(req, status)) {
5131 close(state->pipe_down_fd);
5134 static void oplock5_timedout(struct tevent_req *subreq)
5136 struct tevent_req *req = tevent_req_callback_data(
5137 subreq, struct tevent_req);
5140 ok = tevent_wakeup_recv(subreq);
5141 TALLOC_FREE(subreq);
5143 tevent_req_oom(req);
5146 tevent_req_nterror(req, NT_STATUS_TIMEOUT);
5149 static NTSTATUS oplock5_recv(struct tevent_req *req)
5151 return tevent_req_simple_recv_ntstatus(req);
5154 static bool run_oplock5(int dummy)
5156 struct tevent_context *ev = NULL;
5157 struct tevent_req *req = NULL;
5158 struct cli_state *cli = NULL;
5159 const char *fname = "oplock5.txt";
5160 int pipe_down[2], pipe_up[2];
5167 printf("starting oplock5\n");
5169 if (local_path == NULL) {
5170 d_fprintf(stderr, "oplock5 must be given a local path via "
5171 "-l <localpath>\n");
5175 ret = pipe(pipe_down);
5177 d_fprintf(stderr, "pipe() failed: %s\n", strerror(errno));
5180 ret = pipe(pipe_up);
5182 d_fprintf(stderr, "pipe() failed: %s\n", strerror(errno));
5187 if (child_pid == -1) {
5188 d_fprintf(stderr, "fork() failed: %s\n", strerror(errno));
5192 if (child_pid == 0) {
5193 char *local_file = NULL;
5196 close(pipe_down[1]);
5199 local_file = talloc_asprintf(
5200 talloc_tos(), "%s/%s", local_path, fname);
5201 if (local_file == 0) {
5205 fd = open(local_file, O_RDWR|O_CREAT, 0644);
5208 "open(%s) in child failed: %s\n",
5215 signal(SIGIO, SIG_IGN);
5217 ret = fcntl(fd, F_SETLEASE, F_WRLCK);
5220 "SETLEASE in child failed: %s\n",
5227 ret = sys_write(pipe_up[1], &c, sizeof(c));
5230 "sys_write failed: %s\n",
5234 ret = sys_read(pipe_down[0], &c, sizeof(c));
5237 "sys_read failed: %s\n",
5245 close(pipe_down[0]);
5247 ret = sys_read(pipe_up[0], &c, sizeof(c));
5250 "sys_read failed: %s\n",
5255 d_fprintf(stderr, "got error code %"PRIu8"\n", c);
5259 ok = torture_open_connection(&cli, 0);
5261 d_fprintf(stderr, "torture_open_connection failed\n");
5265 ev = samba_tevent_context_init(talloc_tos());
5267 d_fprintf(stderr, "samba_tevent_context_init failed\n");
5271 req = oplock5_send(ev, ev, cli, fname, pipe_down[1]);
5273 d_fprintf(stderr, "oplock5_send failed\n");
5277 ok = tevent_req_poll_ntstatus(req, ev, &status);
5280 "tevent_req_poll_ntstatus failed: %s\n",
5285 status = oplock5_recv(req);
5287 if (!NT_STATUS_IS_OK(status)) {
5289 "oplock5 failed: %s\n",
5297 #endif /* HAVE_KERNEL_OPLOCKS_LINUX */
5300 Test delete on close semantics.
5302 static bool run_deletetest(int dummy)
5304 struct cli_state *cli1 = NULL;
5305 struct cli_state *cli2 = NULL;
5306 const char *fname = "\\delete.file";
5307 uint16_t fnum1 = (uint16_t)-1;
5308 uint16_t fnum2 = (uint16_t)-1;
5309 bool correct = false;
5312 printf("starting delete test\n");
5314 if (!torture_open_connection(&cli1, 0)) {
5318 smbXcli_conn_set_sockopt(cli1->conn, sockops);
5320 /* Test 1 - this should delete the file on close. */
5322 cli_setatr(cli1, fname, 0, 0);
5323 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5325 status = cli_ntcreate(cli1, fname, 0, GENERIC_ALL_ACCESS|DELETE_ACCESS,
5326 FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
5327 FILE_DELETE_ON_CLOSE, 0, &fnum1, NULL);
5328 if (!NT_STATUS_IS_OK(status)) {
5329 printf("[1] open of %s failed (%s)\n", fname, nt_errstr(status));
5333 status = cli_close(cli1, fnum1);
5334 if (!NT_STATUS_IS_OK(status)) {
5335 printf("[1] close failed (%s)\n", nt_errstr(status));
5339 status = cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
5340 if (NT_STATUS_IS_OK(status)) {
5341 printf("[1] open of %s succeeded (should fail)\n", fname);
5345 printf("first delete on close test succeeded.\n");
5347 /* Test 2 - this should delete the file on close. */
5349 cli_setatr(cli1, fname, 0, 0);
5350 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5352 status = cli_ntcreate(cli1, fname, 0, GENERIC_ALL_ACCESS,
5353 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
5354 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
5355 if (!NT_STATUS_IS_OK(status)) {
5356 printf("[2] open of %s failed (%s)\n", fname, nt_errstr(status));
5360 status = cli_nt_delete_on_close(cli1, fnum1, true);
5361 if (!NT_STATUS_IS_OK(status)) {
5362 printf("[2] setting delete_on_close failed (%s)\n", nt_errstr(status));
5366 status = cli_close(cli1, fnum1);
5367 if (!NT_STATUS_IS_OK(status)) {
5368 printf("[2] close failed (%s)\n", nt_errstr(status));
5372 status = cli_openx(cli1, fname, O_RDONLY, DENY_NONE, &fnum1);
5373 if (NT_STATUS_IS_OK(status)) {
5374 printf("[2] open of %s succeeded should have been deleted on close !\n", fname);
5375 status = cli_close(cli1, fnum1);
5376 if (!NT_STATUS_IS_OK(status)) {
5377 printf("[2] close failed (%s)\n", nt_errstr(status));
5379 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5383 printf("second delete on close test succeeded.\n");
5386 cli_setatr(cli1, fname, 0, 0);
5387 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5389 status = cli_ntcreate(cli1, fname, 0, GENERIC_ALL_ACCESS,
5390 FILE_ATTRIBUTE_NORMAL,
5391 FILE_SHARE_READ|FILE_SHARE_WRITE,
5392 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
5393 if (!NT_STATUS_IS_OK(status)) {
5394 printf("[3] open - 1 of %s failed (%s)\n", fname, nt_errstr(status));
5398 /* This should fail with a sharing violation - open for delete is only compatible
5399 with SHARE_DELETE. */
5401 status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
5402 FILE_ATTRIBUTE_NORMAL,
5403 FILE_SHARE_READ|FILE_SHARE_WRITE,
5404 FILE_OPEN, 0, 0, &fnum2, NULL);
5405 if (NT_STATUS_IS_OK(status)) {
5406 printf("[3] open - 2 of %s succeeded - should have failed.\n", fname);
5410 /* This should succeed. */
5411 status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
5412 FILE_ATTRIBUTE_NORMAL,
5413 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5414 FILE_OPEN, 0, 0, &fnum2, NULL);
5415 if (!NT_STATUS_IS_OK(status)) {
5416 printf("[3] open - 3 of %s failed (%s)\n", fname, nt_errstr(status));
5420 status = cli_nt_delete_on_close(cli1, fnum1, true);
5421 if (!NT_STATUS_IS_OK(status)) {
5422 printf("[3] setting delete_on_close failed (%s)\n", nt_errstr(status));
5426 status = cli_close(cli1, fnum1);
5427 if (!NT_STATUS_IS_OK(status)) {
5428 printf("[3] close 1 failed (%s)\n", nt_errstr(status));
5432 status = cli_close(cli1, fnum2);
5433 if (!NT_STATUS_IS_OK(status)) {
5434 printf("[3] close 2 failed (%s)\n", nt_errstr(status));
5438 /* This should fail - file should no longer be there. */
5440 status = cli_openx(cli1, fname, O_RDONLY, DENY_NONE, &fnum1);
5441 if (NT_STATUS_IS_OK(status)) {
5442 printf("[3] open of %s succeeded should have been deleted on close !\n", fname);
5443 status = cli_close(cli1, fnum1);
5444 if (!NT_STATUS_IS_OK(status)) {
5445 printf("[3] close failed (%s)\n", nt_errstr(status));
5447 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5451 printf("third delete on close test succeeded.\n");
5454 cli_setatr(cli1, fname, 0, 0);
5455 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5457 status = cli_ntcreate(cli1, fname, 0,
5458 FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
5459 FILE_ATTRIBUTE_NORMAL,
5460 FILE_SHARE_READ|FILE_SHARE_WRITE,
5461 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
5462 if (!NT_STATUS_IS_OK(status)) {
5463 printf("[4] open of %s failed (%s)\n", fname, nt_errstr(status));
5467 /* This should succeed. */
5468 status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
5469 FILE_ATTRIBUTE_NORMAL,
5470 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5471 FILE_OPEN, 0, 0, &fnum2, NULL);
5472 if (!NT_STATUS_IS_OK(status)) {
5473 printf("[4] open - 2 of %s failed (%s)\n", fname, nt_errstr(status));
5477 status = cli_close(cli1, fnum2);
5478 if (!NT_STATUS_IS_OK(status)) {
5479 printf("[4] close - 1 failed (%s)\n", nt_errstr(status));
5483 status = cli_nt_delete_on_close(cli1, fnum1, true);
5484 if (!NT_STATUS_IS_OK(status)) {
5485 printf("[4] setting delete_on_close failed (%s)\n", nt_errstr(status));
5489 /* This should fail - no more opens once delete on close set. */
5490 status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
5491 FILE_ATTRIBUTE_NORMAL,
5492 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5493 FILE_OPEN, 0, 0, &fnum2, NULL);
5494 if (NT_STATUS_IS_OK(status)) {
5495 printf("[4] open - 3 of %s succeeded ! Should have failed.\n", fname );
5499 status = cli_close(cli1, fnum1);
5500 if (!NT_STATUS_IS_OK(status)) {
5501 printf("[4] close - 2 failed (%s)\n", nt_errstr(status));
5505 printf("fourth delete on close test succeeded.\n");
5508 cli_setatr(cli1, fname, 0, 0);
5509 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5511 status = cli_openx(cli1, fname, O_RDWR|O_CREAT, DENY_NONE, &fnum1);
5512 if (!NT_STATUS_IS_OK(status)) {
5513 printf("[5] open of %s failed (%s)\n", fname, nt_errstr(status));
5517 /* This should fail - only allowed on NT opens with DELETE access. */
5519 status = cli_nt_delete_on_close(cli1, fnum1, true);
5520 if (NT_STATUS_IS_OK(status)) {
5521 printf("[5] setting delete_on_close on OpenX file succeeded - should fail !\n");
5525 status = cli_close(cli1, fnum1);
5526 if (!NT_STATUS_IS_OK(status)) {
5527 printf("[5] close failed (%s)\n", nt_errstr(status));
5531 printf("fifth delete on close test succeeded.\n");
5534 cli_setatr(cli1, fname, 0, 0);
5535 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5537 status = cli_ntcreate(cli1, fname, 0, FILE_READ_DATA|FILE_WRITE_DATA,
5538 FILE_ATTRIBUTE_NORMAL,
5539 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5540 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
5541 if (!NT_STATUS_IS_OK(status)) {
5542 printf("[6] open of %s failed (%s)\n", fname,
5547 /* This should fail - only allowed on NT opens with DELETE access. */
5549 status = cli_nt_delete_on_close(cli1, fnum1, true);
5550 if (NT_STATUS_IS_OK(status)) {
5551 printf("[6] setting delete_on_close on file with no delete access succeeded - should fail !\n");
5555 status = cli_close(cli1, fnum1);
5556 if (!NT_STATUS_IS_OK(status)) {
5557 printf("[6] close failed (%s)\n", nt_errstr(status));
5561 printf("sixth delete on close test succeeded.\n");
5564 cli_setatr(cli1, fname, 0, 0);
5565 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5567 status = cli_ntcreate(cli1, fname, 0,
5568 FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
5569 FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
5570 0, 0, &fnum1, NULL);
5571 if (!NT_STATUS_IS_OK(status)) {
5572 printf("[7] open of %s failed (%s)\n", fname, nt_errstr(status));
5576 status = cli_nt_delete_on_close(cli1, fnum1, true);
5577 if (!NT_STATUS_IS_OK(status)) {
5578 printf("[7] setting delete_on_close on file failed !\n");
5582 status = cli_nt_delete_on_close(cli1, fnum1, false);
5583 if (!NT_STATUS_IS_OK(status)) {
5584 printf("[7] unsetting delete_on_close on file failed !\n");
5588 status = cli_close(cli1, fnum1);
5589 if (!NT_STATUS_IS_OK(status)) {
5590 printf("[7] close - 1 failed (%s)\n", nt_errstr(status));
5594 /* This next open should succeed - we reset the flag. */
5595 status = cli_openx(cli1, fname, O_RDONLY, DENY_NONE, &fnum1);
5596 if (!NT_STATUS_IS_OK(status)) {
5597 printf("[7] open of %s failed (%s)\n", fname, nt_errstr(status));
5601 status = cli_close(cli1, fnum1);
5602 if (!NT_STATUS_IS_OK(status)) {
5603 printf("[7] close - 2 failed (%s)\n", nt_errstr(status));
5607 printf("seventh delete on close test succeeded.\n");
5610 cli_setatr(cli1, fname, 0, 0);
5611 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5613 if (!torture_open_connection(&cli2, 1)) {
5614 printf("[8] failed to open second connection.\n");
5618 smbXcli_conn_set_sockopt(cli1->conn, sockops);
5620 status = cli_ntcreate(cli1, fname, 0,
5621 FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
5622 FILE_ATTRIBUTE_NORMAL,
5623 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5624 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
5625 if (!NT_STATUS_IS_OK(status)) {
5626 printf("[8] open 1 of %s failed (%s)\n", fname, nt_errstr(status));
5630 status = cli_ntcreate(cli2, fname, 0,
5631 FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
5632 FILE_ATTRIBUTE_NORMAL,
5633 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5634 FILE_OPEN, 0, 0, &fnum2, NULL);
5635 if (!NT_STATUS_IS_OK(status)) {
5636 printf("[8] open 2 of %s failed (%s)\n", fname, nt_errstr(status));
5640 status = cli_nt_delete_on_close(cli1, fnum1, true);
5641 if (!NT_STATUS_IS_OK(status)) {
5642 printf("[8] setting delete_on_close on file failed !\n");
5646 status = cli_close(cli1, fnum1);
5647 if (!NT_STATUS_IS_OK(status)) {
5648 printf("[8] close - 1 failed (%s)\n", nt_errstr(status));
5652 status = cli_close(cli2, fnum2);
5653 if (!NT_STATUS_IS_OK(status)) {
5654 printf("[8] close - 2 failed (%s)\n", nt_errstr(status));
5658 /* This should fail.. */
5659 status = cli_openx(cli1, fname, O_RDONLY, DENY_NONE, &fnum1);
5660 if (NT_STATUS_IS_OK(status)) {
5661 printf("[8] open of %s succeeded should have been deleted on close !\n", fname);
5665 printf("eighth delete on close test succeeded.\n");
5669 /* This should fail - we need to set DELETE_ACCESS. */
5670 status = cli_ntcreate(cli1, fname, 0, FILE_READ_DATA|FILE_WRITE_DATA,
5671 FILE_ATTRIBUTE_NORMAL,
5674 FILE_DELETE_ON_CLOSE, 0, &fnum1, NULL);
5675 if (NT_STATUS_IS_OK(status)) {
5676 printf("[9] open of %s succeeded should have failed!\n", fname);
5680 printf("ninth delete on close test succeeded.\n");
5684 status = cli_ntcreate(cli1, fname, 0,
5685 FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
5686 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
5687 FILE_OVERWRITE_IF, FILE_DELETE_ON_CLOSE,
5689 if (!NT_STATUS_IS_OK(status)) {
5690 printf("[10] open of %s failed (%s)\n", fname, nt_errstr(status));
5694 /* This should delete the file. */
5695 status = cli_close(cli1, fnum1);
5696 if (!NT_STATUS_IS_OK(status)) {
5697 printf("[10] close failed (%s)\n", nt_errstr(status));
5701 /* This should fail.. */
5702 status = cli_openx(cli1, fname, O_RDONLY, DENY_NONE, &fnum1);
5703 if (NT_STATUS_IS_OK(status)) {
5704 printf("[10] open of %s succeeded should have been deleted on close !\n", fname);
5708 printf("tenth delete on close test succeeded.\n");
5712 cli_setatr(cli1, fname, 0, 0);
5713 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5715 /* Can we open a read-only file with delete access? */
5717 /* Create a readonly file. */
5718 status = cli_ntcreate(cli1, fname, 0, FILE_READ_DATA|FILE_WRITE_DATA,
5719 FILE_ATTRIBUTE_READONLY, FILE_SHARE_NONE,
5720 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
5721 if (!NT_STATUS_IS_OK(status)) {
5722 printf("[11] open of %s failed (%s)\n", fname, nt_errstr(status));
5726 status = cli_close(cli1, fnum1);
5727 if (!NT_STATUS_IS_OK(status)) {
5728 printf("[11] close failed (%s)\n", nt_errstr(status));
5732 /* Now try open for delete access. */
5733 status = cli_ntcreate(cli1, fname, 0,
5734 FILE_READ_ATTRIBUTES|DELETE_ACCESS,
5736 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5737 FILE_OPEN, 0, 0, &fnum1, NULL);
5738 if (!NT_STATUS_IS_OK(status)) {
5739 printf("[11] open of %s failed: %s\n", fname, nt_errstr(status));
5743 cli_close(cli1, fnum1);
5745 printf("eleventh delete on close test succeeded.\n");
5749 * like test 4 but with initial delete on close
5752 cli_setatr(cli1, fname, 0, 0);
5753 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5755 status = cli_ntcreate(cli1, fname, 0,
5756 FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
5757 FILE_ATTRIBUTE_NORMAL,
5758 FILE_SHARE_READ|FILE_SHARE_WRITE,
5760 FILE_DELETE_ON_CLOSE, 0, &fnum1, NULL);
5761 if (!NT_STATUS_IS_OK(status)) {
5762 printf("[12] open 1 of %s failed (%s)\n", fname, nt_errstr(status));
5766 status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
5767 FILE_ATTRIBUTE_NORMAL,
5768 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5769 FILE_OPEN, 0, 0, &fnum2, NULL);
5770 if (!NT_STATUS_IS_OK(status)) {
5771 printf("[12] open 2 of %s failed(%s).\n", fname, nt_errstr(status));
5775 status = cli_close(cli1, fnum2);
5776 if (!NT_STATUS_IS_OK(status)) {
5777 printf("[12] close 1 failed (%s)\n", nt_errstr(status));
5781 status = cli_nt_delete_on_close(cli1, fnum1, true);
5782 if (!NT_STATUS_IS_OK(status)) {
5783 printf("[12] setting delete_on_close failed (%s)\n", nt_errstr(status));
5787 /* This should fail - no more opens once delete on close set. */
5788 status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
5789 FILE_ATTRIBUTE_NORMAL,
5790 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5791 FILE_OPEN, 0, 0, &fnum2, NULL);
5792 if (NT_STATUS_IS_OK(status)) {
5793 printf("[12] open 3 of %s succeeded - should fail).\n", fname);
5797 status = cli_nt_delete_on_close(cli1, fnum1, false);
5798 if (!NT_STATUS_IS_OK(status)) {
5799 printf("[12] unsetting delete_on_close failed (%s)\n", nt_errstr(status));
5803 status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
5804 FILE_ATTRIBUTE_NORMAL,
5805 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5806 FILE_OPEN, 0, 0, &fnum2, NULL);
5807 if (!NT_STATUS_IS_OK(status)) {
5808 printf("[12] open 4 of %s failed (%s)\n", fname, nt_errstr(status));
5812 status = cli_close(cli1, fnum2);
5813 if (!NT_STATUS_IS_OK(status)) {
5814 printf("[12] close 2 failed (%s)\n", nt_errstr(status));
5818 status = cli_close(cli1, fnum1);
5819 if (!NT_STATUS_IS_OK(status)) {
5820 printf("[12] close 3 failed (%s)\n", nt_errstr(status));
5825 * setting delete on close on the handle does
5826 * not unset the initial delete on close...
5828 status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
5829 FILE_ATTRIBUTE_NORMAL,
5830 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5831 FILE_OPEN, 0, 0, &fnum2, NULL);
5832 if (NT_STATUS_IS_OK(status)) {
5833 printf("[12] open 5 of %s succeeded - should fail).\n", fname);
5835 } else if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
5836 printf("ntcreate returned %s, expected "
5837 "NT_STATUS_OBJECT_NAME_NOT_FOUND\n",
5842 printf("twelfth delete on close test succeeded.\n");
5845 printf("finished delete test\n");
5850 /* FIXME: This will crash if we aborted before cli2 got
5851 * intialized, because these functions don't handle
5852 * uninitialized connections. */
5854 if (fnum1 != (uint16_t)-1) cli_close(cli1, fnum1);
5855 if (fnum2 != (uint16_t)-1) cli_close(cli1, fnum2);
5856 cli_setatr(cli1, fname, 0, 0);
5857 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5859 if (cli1 && !torture_close_connection(cli1)) {
5862 if (cli2 && !torture_close_connection(cli2)) {
5868 struct delete_stream_state {
5872 static void delete_stream_unlinked(struct tevent_req *subreq);
5873 static void delete_stream_closed(struct tevent_req *subreq);
5875 static struct tevent_req *delete_stream_send(
5876 TALLOC_CTX *mem_ctx,
5877 struct tevent_context *ev,
5878 struct cli_state *cli,
5879 const char *base_fname,
5880 uint16_t stream_fnum)
5882 struct tevent_req *req = NULL, *subreq = NULL;
5883 struct delete_stream_state *state = NULL;
5885 req = tevent_req_create(
5886 mem_ctx, &state, struct delete_stream_state);
5891 subreq = cli_unlink_send(
5896 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5897 if (tevent_req_nomem(subreq, req)) {
5898 return tevent_req_post(req, ev);
5900 tevent_req_set_callback(subreq, delete_stream_unlinked, req);
5902 subreq = cli_close_send(state, ev, cli, stream_fnum);
5903 if (tevent_req_nomem(subreq, req)) {
5904 return tevent_req_post(req, ev);
5906 tevent_req_set_callback(subreq, delete_stream_closed, req);
5911 static void delete_stream_unlinked(struct tevent_req *subreq)
5913 struct tevent_req *req = tevent_req_callback_data(
5914 subreq, struct tevent_req);
5915 struct delete_stream_state *state = tevent_req_data(
5916 req, struct delete_stream_state);
5919 status = cli_unlink_recv(subreq);
5920 TALLOC_FREE(subreq);
5921 if (!NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
5922 printf("cli_unlink returned %s\n",
5924 tevent_req_nterror(req, NT_STATUS_UNSUCCESSFUL);
5927 if (!state->closed) {
5928 /* close reply should have come in first */
5929 printf("Not closed\n");
5930 tevent_req_nterror(req, NT_STATUS_UNSUCCESSFUL);
5933 tevent_req_done(req);
5936 static void delete_stream_closed(struct tevent_req *subreq)
5938 struct tevent_req *req = tevent_req_callback_data(
5939 subreq, struct tevent_req);
5940 struct delete_stream_state *state = tevent_req_data(
5941 req, struct delete_stream_state);
5944 status = cli_close_recv(subreq);
5945 TALLOC_FREE(subreq);
5946 if (tevent_req_nterror(req, status)) {
5949 /* also waiting for the unlink to come back */
5950 state->closed = true;
5953 static NTSTATUS delete_stream_recv(struct tevent_req *req)
5955 return tevent_req_simple_recv_ntstatus(req);
5958 static bool run_delete_stream(int dummy)
5960 struct tevent_context *ev = NULL;
5961 struct tevent_req *req = NULL;
5962 struct cli_state *cli = NULL;
5963 const char fname[] = "delete_stream";
5964 const char fname_stream[] = "delete_stream:Zone.Identifier:$DATA";
5965 uint16_t fnum1, fnum2;
5969 printf("Starting stream delete test\n");
5971 ok = torture_open_connection(&cli, 0);
5976 cli_setatr(cli, fname, 0, 0);
5977 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5979 /* Create the file. */
5980 status = cli_ntcreate(
5984 READ_CONTROL_ACCESS,
5986 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5992 if (!NT_STATUS_IS_OK(status)) {
5994 "cli_ntcreate of %s failed (%s)\n",
5999 status = cli_close(cli, fnum1);
6000 if (!NT_STATUS_IS_OK(status)) {
6002 "cli_close of %s failed (%s)\n",
6008 /* Now create the stream. */
6009 status = cli_ntcreate(
6015 FILE_SHARE_READ|FILE_SHARE_WRITE,
6022 if (!NT_STATUS_IS_OK(status)) {
6024 "cli_ntcreate of %s failed (%s)\n",
6030 /* open it a second time */
6032 status = cli_ntcreate(
6038 FILE_SHARE_READ|FILE_SHARE_WRITE,
6045 if (!NT_STATUS_IS_OK(status)) {
6047 "2nd cli_ntcreate of %s failed (%s)\n",
6053 ev = samba_tevent_context_init(talloc_tos());
6055 d_fprintf(stderr, "samba_tevent_context_init failed\n");
6059 req = delete_stream_send(ev, ev, cli, fname, fnum1);
6061 d_fprintf(stderr, "delete_stream_send failed\n");
6065 ok = tevent_req_poll_ntstatus(req, ev, &status);
6068 "tevent_req_poll_ntstatus failed: %s\n",
6073 status = delete_stream_recv(req);
6075 if (!NT_STATUS_IS_OK(status)) {
6077 "delete_stream failed: %s\n",
6082 status = cli_close(cli, fnum2);
6083 if (!NT_STATUS_IS_OK(status)) {
6085 "close failed: %s\n",
6090 status = cli_unlink(
6091 cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6092 if (!NT_STATUS_IS_OK(status)) {
6094 "unlink failed: %s\n",
6103 Exercise delete on close semantics - use on the PRINT1 share in torture
6106 static bool run_delete_print_test(int dummy)
6108 struct cli_state *cli1 = NULL;
6109 const char *fname = "print_delete.file";
6110 uint16_t fnum1 = (uint16_t)-1;
6111 bool correct = false;
6112 const char *buf = "print file data\n";
6115 printf("starting print delete test\n");
6117 if (!torture_open_connection(&cli1, 0)) {
6121 smbXcli_conn_set_sockopt(cli1->conn, sockops);
6123 status = cli_ntcreate(cli1, fname, 0, GENERIC_ALL_ACCESS|DELETE_ACCESS,
6124 FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
6125 0, 0, &fnum1, NULL);
6126 if (!NT_STATUS_IS_OK(status)) {
6127 printf("open of %s failed (%s)\n",
6133 status = cli_writeall(cli1,
6136 (const uint8_t *)buf,
6138 strlen(buf), /* size */
6140 if (!NT_STATUS_IS_OK(status)) {
6141 printf("writing print file data failed (%s)\n",
6146 status = cli_nt_delete_on_close(cli1, fnum1, true);
6147 if (!NT_STATUS_IS_OK(status)) {
6148 printf("setting delete_on_close failed (%s)\n",
6153 status = cli_close(cli1, fnum1);
6154 if (!NT_STATUS_IS_OK(status)) {
6155 printf("close failed (%s)\n", nt_errstr(status));
6159 printf("finished print delete test\n");
6165 if (fnum1 != (uint16_t)-1) {
6166 cli_close(cli1, fnum1);
6169 if (cli1 && !torture_close_connection(cli1)) {
6175 static bool run_deletetest_ln(int dummy)
6177 struct cli_state *cli;
6178 const char *fname = "\\delete1";
6179 const char *fname_ln = "\\delete1_ln";
6183 bool correct = true;
6186 printf("starting deletetest-ln\n");
6188 if (!torture_open_connection(&cli, 0)) {
6192 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6193 cli_unlink(cli, fname_ln, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6195 smbXcli_conn_set_sockopt(cli->conn, sockops);
6197 /* Create the file. */
6198 status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
6199 if (!NT_STATUS_IS_OK(status)) {
6200 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
6204 status = cli_close(cli, fnum);
6205 if (!NT_STATUS_IS_OK(status)) {
6206 printf("close1 failed (%s)\n", nt_errstr(status));
6210 /* Now create a hardlink. */
6211 status = cli_hardlink(cli, fname, fname_ln);
6212 if (!NT_STATUS_IS_OK(status)) {
6213 printf("nt hardlink failed (%s)\n", nt_errstr(status));
6217 /* Open the original file. */
6218 status = cli_ntcreate(cli, fname, 0, FILE_READ_DATA,
6219 FILE_ATTRIBUTE_NORMAL,
6220 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6221 FILE_OPEN_IF, 0, 0, &fnum, NULL);
6222 if (!NT_STATUS_IS_OK(status)) {
6223 printf("ntcreate of %s failed (%s)\n", fname, nt_errstr(status));
6227 /* Unlink the hard link path. */
6228 status = cli_ntcreate(cli, fname_ln, 0, DELETE_ACCESS,
6229 FILE_ATTRIBUTE_NORMAL,
6230 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6231 FILE_OPEN_IF, 0, 0, &fnum1, NULL);
6232 if (!NT_STATUS_IS_OK(status)) {
6233 printf("ntcreate of %s failed (%s)\n", fname_ln, nt_errstr(status));
6236 status = cli_nt_delete_on_close(cli, fnum1, true);
6237 if (!NT_STATUS_IS_OK(status)) {
6238 d_printf("(%s) failed to set delete_on_close %s: %s\n",
6239 __location__, fname_ln, nt_errstr(status));
6243 status = cli_close(cli, fnum1);
6244 if (!NT_STATUS_IS_OK(status)) {
6245 printf("close %s failed (%s)\n",
6246 fname_ln, nt_errstr(status));
6250 status = cli_close(cli, fnum);
6251 if (!NT_STATUS_IS_OK(status)) {
6252 printf("close %s failed (%s)\n",
6253 fname, nt_errstr(status));
6257 /* Ensure the original file is still there. */
6258 status = cli_getatr(cli, fname, NULL, NULL, &t);
6259 if (!NT_STATUS_IS_OK(status)) {
6260 printf("%s getatr on file %s failed (%s)\n",
6267 /* Ensure the link path is gone. */
6268 status = cli_getatr(cli, fname_ln, NULL, NULL, &t);
6269 if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
6270 printf("%s, getatr for file %s returned wrong error code %s "
6271 "- should have been deleted\n",
6273 fname_ln, nt_errstr(status));
6277 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6278 cli_unlink(cli, fname_ln, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6280 if (!torture_close_connection(cli)) {
6284 printf("finished deletetest-ln\n");
6290 print out server properties
6292 static bool run_properties(int dummy)
6294 struct cli_state *cli;
6295 bool correct = True;
6297 printf("starting properties test\n");
6301 if (!torture_open_connection(&cli, 0)) {
6305 smbXcli_conn_set_sockopt(cli->conn, sockops);
6307 d_printf("Capabilities 0x%08x\n", smb1cli_conn_capabilities(cli->conn));
6309 if (!torture_close_connection(cli)) {
6318 /* FIRST_DESIRED_ACCESS 0xf019f */
6319 #define FIRST_DESIRED_ACCESS FILE_READ_DATA|FILE_WRITE_DATA|FILE_APPEND_DATA|\
6320 FILE_READ_EA| /* 0xf */ \
6321 FILE_WRITE_EA|FILE_READ_ATTRIBUTES| /* 0x90 */ \
6322 FILE_WRITE_ATTRIBUTES| /* 0x100 */ \
6323 DELETE_ACCESS|READ_CONTROL_ACCESS|\
6324 WRITE_DAC_ACCESS|WRITE_OWNER_ACCESS /* 0xf0000 */
6325 /* SECOND_DESIRED_ACCESS 0xe0080 */
6326 #define SECOND_DESIRED_ACCESS FILE_READ_ATTRIBUTES| /* 0x80 */ \
6327 READ_CONTROL_ACCESS|WRITE_DAC_ACCESS|\
6328 WRITE_OWNER_ACCESS /* 0xe0000 */
6331 #define THIRD_DESIRED_ACCESS FILE_READ_ATTRIBUTES| /* 0x80 */ \
6332 READ_CONTROL_ACCESS|WRITE_DAC_ACCESS|\
6334 WRITE_OWNER_ACCESS /* */
6338 Test ntcreate calls made by xcopy
6340 static bool run_xcopy(int dummy)
6342 static struct cli_state *cli1;
6343 const char *fname = "\\test.txt";
6344 bool correct = True;
6345 uint16_t fnum1, fnum2;
6348 printf("starting xcopy test\n");
6350 if (!torture_open_connection(&cli1, 0)) {
6354 status = cli_ntcreate(cli1, fname, 0, FIRST_DESIRED_ACCESS,
6355 FILE_ATTRIBUTE_ARCHIVE, FILE_SHARE_NONE,
6356 FILE_OVERWRITE_IF, 0x4044, 0, &fnum1, NULL);
6357 if (!NT_STATUS_IS_OK(status)) {
6358 printf("First open failed - %s\n", nt_errstr(status));
6362 status = cli_ntcreate(cli1, fname, 0, SECOND_DESIRED_ACCESS, 0,
6363 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6364 FILE_OPEN, 0x200000, 0, &fnum2, NULL);
6365 if (!NT_STATUS_IS_OK(status)) {
6366 printf("second open failed - %s\n", nt_errstr(status));
6370 if (!torture_close_connection(cli1)) {
6378 Test rename on files open with share delete and no share delete.
6380 static bool run_rename(int dummy)
6382 static struct cli_state *cli1;
6383 const char *fname = "\\test.txt";
6384 const char *fname1 = "\\test1.txt";
6385 bool correct = True;
6390 printf("starting rename test\n");
6392 if (!torture_open_connection(&cli1, 0)) {
6396 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6397 cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6399 status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
6400 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ,
6401 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
6402 if (!NT_STATUS_IS_OK(status)) {
6403 printf("First open failed - %s\n", nt_errstr(status));
6407 status = cli_rename(cli1, fname, fname1, false);
6408 if (!NT_STATUS_IS_OK(status)) {
6409 printf("First rename failed (SHARE_READ) (this is correct) - %s\n", nt_errstr(status));
6411 printf("First rename succeeded (SHARE_READ) - this should have failed !\n");
6415 status = cli_close(cli1, fnum1);
6416 if (!NT_STATUS_IS_OK(status)) {
6417 printf("close - 1 failed (%s)\n", nt_errstr(status));
6421 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6422 cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6423 status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS, FILE_ATTRIBUTE_NORMAL,
6425 FILE_SHARE_DELETE|FILE_SHARE_NONE,
6427 FILE_SHARE_DELETE|FILE_SHARE_READ,
6429 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
6430 if (!NT_STATUS_IS_OK(status)) {
6431 printf("Second open failed - %s\n", nt_errstr(status));
6435 status = cli_rename(cli1, fname, fname1, false);
6436 if (!NT_STATUS_IS_OK(status)) {
6437 printf("Second rename failed (SHARE_DELETE | SHARE_READ) - this should have succeeded - %s\n", nt_errstr(status));
6440 printf("Second rename succeeded (SHARE_DELETE | SHARE_READ)\n");
6443 status = cli_close(cli1, fnum1);
6444 if (!NT_STATUS_IS_OK(status)) {
6445 printf("close - 2 failed (%s)\n", nt_errstr(status));
6449 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6450 cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6452 status = cli_ntcreate(cli1, fname, 0, READ_CONTROL_ACCESS,
6453 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
6454 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
6455 if (!NT_STATUS_IS_OK(status)) {
6456 printf("Third open failed - %s\n", nt_errstr(status));
6461 status = cli_rename(cli1, fname, fname1, false);
6462 if (!NT_STATUS_IS_OK(status)) {
6463 printf("Third rename failed (SHARE_NONE) - this should have succeeded - %s\n", nt_errstr(status));
6466 printf("Third rename succeeded (SHARE_NONE)\n");
6469 status = cli_close(cli1, fnum1);
6470 if (!NT_STATUS_IS_OK(status)) {
6471 printf("close - 3 failed (%s)\n", nt_errstr(status));
6475 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6476 cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6480 status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
6481 FILE_ATTRIBUTE_NORMAL,
6482 FILE_SHARE_READ | FILE_SHARE_WRITE,
6483 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
6484 if (!NT_STATUS_IS_OK(status)) {
6485 printf("Fourth open failed - %s\n", nt_errstr(status));
6489 status = cli_rename(cli1, fname, fname1, false);
6490 if (!NT_STATUS_IS_OK(status)) {
6491 printf("Fourth rename failed (SHARE_READ | SHARE_WRITE) (this is correct) - %s\n", nt_errstr(status));
6493 printf("Fourth rename succeeded (SHARE_READ | SHARE_WRITE) - this should have failed !\n");
6497 status = cli_close(cli1, fnum1);
6498 if (!NT_STATUS_IS_OK(status)) {
6499 printf("close - 4 failed (%s)\n", nt_errstr(status));
6503 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6504 cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6508 status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
6509 FILE_ATTRIBUTE_NORMAL,
6510 FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
6511 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
6512 if (!NT_STATUS_IS_OK(status)) {
6513 printf("Fifth open failed - %s\n", nt_errstr(status));
6517 status = cli_rename(cli1, fname, fname1, false);
6518 if (!NT_STATUS_IS_OK(status)) {
6519 printf("Fifth rename failed (SHARE_READ | SHARE_WRITE | SHARE_DELETE) - this should have succeeded - %s ! \n", nt_errstr(status));
6522 printf("Fifth rename succeeded (SHARE_READ | SHARE_WRITE | SHARE_DELETE) (this is correct) - %s\n", nt_errstr(status));
6526 status = cli_close(cli1, fnum1);
6527 if (!NT_STATUS_IS_OK(status)) {
6528 printf("close - 5 failed (%s)\n", nt_errstr(status));
6532 /* Check that the renamed file has FILE_ATTRIBUTE_ARCHIVE. */
6533 status = cli_getatr(cli1, fname1, &attr, NULL, NULL);
6534 if (!NT_STATUS_IS_OK(status)) {
6535 printf("getatr on file %s failed - %s ! \n",
6536 fname1, nt_errstr(status));
6539 if (attr != FILE_ATTRIBUTE_ARCHIVE) {
6540 printf("Renamed file %s has wrong attr 0x%x "
6541 "(should be 0x%x)\n",
6544 (unsigned int)FILE_ATTRIBUTE_ARCHIVE);
6547 printf("Renamed file %s has archive bit set\n", fname1);
6551 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6552 cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6554 if (!torture_close_connection(cli1)) {
6562 Test rename into a directory with an ACL denying it.
6564 static bool run_rename_access(int dummy)
6566 static struct cli_state *cli = NULL;
6567 static struct cli_state *posix_cli = NULL;
6568 const char *src = "test.txt";
6569 const char *dname = "dir";
6570 const char *dst = "dir\\test.txt";
6571 const char *dsrc = "test.dir";
6572 const char *ddst = "dir\\test.dir";
6573 uint16_t fnum = (uint16_t)-1;
6574 struct security_descriptor *sd = NULL;
6575 struct security_descriptor *newsd = NULL;
6577 TALLOC_CTX *frame = NULL;
6579 frame = talloc_stackframe();
6580 printf("starting rename access test\n");
6582 /* Windows connection. */
6583 if (!torture_open_connection(&cli, 0)) {
6587 smbXcli_conn_set_sockopt(cli->conn, sockops);
6589 /* Posix connection. */
6590 if (!torture_open_connection(&posix_cli, 0)) {
6594 smbXcli_conn_set_sockopt(posix_cli->conn, sockops);
6596 status = torture_setup_unix_extensions(posix_cli);
6597 if (!NT_STATUS_IS_OK(status)) {
6601 /* Start with a clean slate. */
6602 cli_unlink(cli, src, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6603 cli_unlink(cli, dst, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6604 cli_rmdir(cli, dsrc);
6605 cli_rmdir(cli, ddst);
6606 cli_rmdir(cli, dname);
6609 * Setup the destination directory with a DENY ACE to
6610 * prevent new files within it.
6612 status = cli_ntcreate(cli,
6615 FILE_READ_ATTRIBUTES|READ_CONTROL_ACCESS|
6616 WRITE_DAC_ACCESS|FILE_READ_DATA|
6618 FILE_ATTRIBUTE_DIRECTORY,
6619 FILE_SHARE_READ|FILE_SHARE_WRITE,
6621 FILE_DIRECTORY_FILE,
6625 if (!NT_STATUS_IS_OK(status)) {
6626 printf("Create of %s - %s\n", dname, nt_errstr(status));
6630 status = cli_query_secdesc(cli,
6634 if (!NT_STATUS_IS_OK(status)) {
6635 printf("cli_query_secdesc failed for %s (%s)\n",
6636 dname, nt_errstr(status));
6640 newsd = security_descriptor_dacl_create(frame,
6645 SEC_ACE_TYPE_ACCESS_DENIED,
6646 SEC_DIR_ADD_FILE|SEC_DIR_ADD_SUBDIR,
6649 if (newsd == NULL) {
6652 sd->dacl = security_acl_concatenate(frame,
6655 if (sd->dacl == NULL) {
6658 status = cli_set_secdesc(cli, fnum, sd);
6659 if (!NT_STATUS_IS_OK(status)) {
6660 printf("cli_set_secdesc failed for %s (%s)\n",
6661 dname, nt_errstr(status));
6664 status = cli_close(cli, fnum);
6665 if (!NT_STATUS_IS_OK(status)) {
6666 printf("close failed for %s (%s)\n",
6667 dname, nt_errstr(status));
6670 /* Now go around the back and chmod to 777 via POSIX. */
6671 status = cli_posix_chmod(posix_cli, dname, 0777);
6672 if (!NT_STATUS_IS_OK(status)) {
6673 printf("cli_posix_chmod failed for %s (%s)\n",
6674 dname, nt_errstr(status));
6678 /* Check we can't create a file within dname via Windows. */
6679 status = cli_openx(cli, dst, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
6680 if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
6681 cli_close(posix_cli, fnum);
6682 printf("Create of %s should be ACCESS denied, was %s\n",
6683 dst, nt_errstr(status));
6687 /* Make the sample file/directory. */
6688 status = cli_openx(cli, src, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
6689 if (!NT_STATUS_IS_OK(status)) {
6690 printf("open of %s failed (%s)\n", src, nt_errstr(status));
6693 status = cli_close(cli, fnum);
6694 if (!NT_STATUS_IS_OK(status)) {
6695 printf("cli_close failed (%s)\n", nt_errstr(status));
6699 status = cli_mkdir(cli, dsrc);
6700 if (!NT_STATUS_IS_OK(status)) {
6701 printf("cli_mkdir of %s failed (%s)\n",
6702 dsrc, nt_errstr(status));
6707 * OK - renames of the new file and directory into the
6708 * dst directory should fail.
6711 status = cli_rename(cli, src, dst, false);
6712 if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
6713 printf("rename of %s -> %s should be ACCESS denied, was %s\n",
6714 src, dst, nt_errstr(status));
6717 status = cli_rename(cli, dsrc, ddst, false);
6718 if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
6719 printf("rename of %s -> %s should be ACCESS denied, was %s\n",
6720 src, dst, nt_errstr(status));
6730 torture_close_connection(posix_cli);
6734 if (fnum != (uint16_t)-1) {
6735 cli_close(cli, fnum);
6737 cli_unlink(cli, src,
6738 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6739 cli_unlink(cli, dst,
6740 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6741 cli_rmdir(cli, dsrc);
6742 cli_rmdir(cli, ddst);
6743 cli_rmdir(cli, dname);
6745 torture_close_connection(cli);
6753 Test owner rights ACE.
6755 static bool run_owner_rights(int dummy)
6757 static struct cli_state *cli = NULL;
6758 const char *fname = "owner_rights.txt";
6759 uint16_t fnum = (uint16_t)-1;
6760 struct security_descriptor *sd = NULL;
6761 struct security_descriptor *newsd = NULL;
6763 TALLOC_CTX *frame = NULL;
6765 frame = talloc_stackframe();
6766 printf("starting owner rights test\n");
6768 /* Windows connection. */
6769 if (!torture_open_connection(&cli, 0)) {
6773 smbXcli_conn_set_sockopt(cli->conn, sockops);
6775 /* Start with a clean slate. */
6776 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6778 /* Create the test file. */
6779 /* Now try and open for read and write-dac. */
6780 status = cli_ntcreate(cli,
6784 FILE_ATTRIBUTE_NORMAL,
6785 FILE_SHARE_READ|FILE_SHARE_WRITE|
6792 if (!NT_STATUS_IS_OK(status)) {
6793 printf("Create of %s - %s\n", fname, nt_errstr(status));
6797 /* Get the original SD. */
6798 status = cli_query_secdesc(cli,
6802 if (!NT_STATUS_IS_OK(status)) {
6803 printf("cli_query_secdesc failed for %s (%s)\n",
6804 fname, nt_errstr(status));
6809 * Add an "owner-rights" ACE denying WRITE_DATA,
6810 * and an "owner-rights" ACE allowing READ_DATA.
6813 newsd = security_descriptor_dacl_create(frame,
6818 SEC_ACE_TYPE_ACCESS_DENIED,
6822 SEC_ACE_TYPE_ACCESS_ALLOWED,
6826 if (newsd == NULL) {
6829 sd->dacl = security_acl_concatenate(frame,
6832 if (sd->dacl == NULL) {
6835 status = cli_set_secdesc(cli, fnum, sd);
6836 if (!NT_STATUS_IS_OK(status)) {
6837 printf("cli_set_secdesc failed for %s (%s)\n",
6838 fname, nt_errstr(status));
6841 status = cli_close(cli, fnum);
6842 if (!NT_STATUS_IS_OK(status)) {
6843 printf("close failed for %s (%s)\n",
6844 fname, nt_errstr(status));
6847 fnum = (uint16_t)-1;
6849 /* Try and open for FILE_WRITE_DATA */
6850 status = cli_ntcreate(cli,
6854 FILE_ATTRIBUTE_NORMAL,
6855 FILE_SHARE_READ|FILE_SHARE_WRITE|
6862 if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
6863 printf("Open of %s - %s\n", fname, nt_errstr(status));
6867 /* Now try and open for FILE_READ_DATA */
6868 status = cli_ntcreate(cli,
6872 FILE_ATTRIBUTE_NORMAL,
6873 FILE_SHARE_READ|FILE_SHARE_WRITE|
6880 if (!NT_STATUS_IS_OK(status)) {
6881 printf("Open of %s - %s\n", fname, nt_errstr(status));
6885 status = cli_close(cli, fnum);
6886 if (!NT_STATUS_IS_OK(status)) {
6887 printf("close failed for %s (%s)\n",
6888 fname, nt_errstr(status));
6892 /* Restore clean slate. */
6894 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6896 /* Create the test file. */
6897 status = cli_ntcreate(cli,
6901 FILE_ATTRIBUTE_NORMAL,
6902 FILE_SHARE_READ|FILE_SHARE_WRITE|
6909 if (!NT_STATUS_IS_OK(status)) {
6910 printf("Create of %s - %s\n", fname, nt_errstr(status));
6914 /* Get the original SD. */
6915 status = cli_query_secdesc(cli,
6919 if (!NT_STATUS_IS_OK(status)) {
6920 printf("cli_query_secdesc failed for %s (%s)\n",
6921 fname, nt_errstr(status));
6926 * Add an "owner-rights ACE denying WRITE_DATA,
6927 * and an "owner-rights ACE allowing READ_DATA|WRITE_DATA.
6930 newsd = security_descriptor_dacl_create(frame,
6935 SEC_ACE_TYPE_ACCESS_DENIED,
6939 SEC_ACE_TYPE_ACCESS_ALLOWED,
6940 FILE_READ_DATA|FILE_WRITE_DATA,
6943 if (newsd == NULL) {
6946 sd->dacl = security_acl_concatenate(frame,
6949 if (sd->dacl == NULL) {
6952 status = cli_set_secdesc(cli, fnum, sd);
6953 if (!NT_STATUS_IS_OK(status)) {
6954 printf("cli_set_secdesc failed for %s (%s)\n",
6955 fname, nt_errstr(status));
6958 status = cli_close(cli, fnum);
6959 if (!NT_STATUS_IS_OK(status)) {
6960 printf("close failed for %s (%s)\n",
6961 fname, nt_errstr(status));
6964 fnum = (uint16_t)-1;
6966 /* Try and open for FILE_WRITE_DATA */
6967 status = cli_ntcreate(cli,
6971 FILE_ATTRIBUTE_NORMAL,
6972 FILE_SHARE_READ|FILE_SHARE_WRITE|
6979 if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
6980 printf("Open of %s - %s\n", fname, nt_errstr(status));
6984 /* Now try and open for FILE_READ_DATA */
6985 status = cli_ntcreate(cli,
6989 FILE_ATTRIBUTE_NORMAL,
6990 FILE_SHARE_READ|FILE_SHARE_WRITE|
6997 if (!NT_STATUS_IS_OK(status)) {
6998 printf("Open of %s - %s\n", fname, nt_errstr(status));
7002 status = cli_close(cli, fnum);
7003 if (!NT_STATUS_IS_OK(status)) {
7004 printf("close failed for %s (%s)\n",
7005 fname, nt_errstr(status));
7009 /* Restore clean slate. */
7011 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7014 /* Create the test file. */
7015 status = cli_ntcreate(cli,
7019 FILE_ATTRIBUTE_NORMAL,
7020 FILE_SHARE_READ|FILE_SHARE_WRITE|
7027 if (!NT_STATUS_IS_OK(status)) {
7028 printf("Create of %s - %s\n", fname, nt_errstr(status));
7032 /* Get the original SD. */
7033 status = cli_query_secdesc(cli,
7037 if (!NT_STATUS_IS_OK(status)) {
7038 printf("cli_query_secdesc failed for %s (%s)\n",
7039 fname, nt_errstr(status));
7044 * Add an "authenticated users" ACE allowing READ_DATA,
7045 * add an "owner-rights" denying READ_DATA,
7046 * and an "authenticated users" ACE allowing WRITE_DATA.
7049 newsd = security_descriptor_dacl_create(frame,
7053 SID_NT_AUTHENTICATED_USERS,
7054 SEC_ACE_TYPE_ACCESS_ALLOWED,
7058 SEC_ACE_TYPE_ACCESS_DENIED,
7061 SID_NT_AUTHENTICATED_USERS,
7062 SEC_ACE_TYPE_ACCESS_ALLOWED,
7066 if (newsd == NULL) {
7067 printf("newsd == NULL\n");
7070 sd->dacl = security_acl_concatenate(frame,
7073 if (sd->dacl == NULL) {
7074 printf("sd->dacl == NULL\n");
7077 status = cli_set_secdesc(cli, fnum, sd);
7078 if (!NT_STATUS_IS_OK(status)) {
7079 printf("cli_set_secdesc failed for %s (%s)\n",
7080 fname, nt_errstr(status));
7083 status = cli_close(cli, fnum);
7084 if (!NT_STATUS_IS_OK(status)) {
7085 printf("close failed for %s (%s)\n",
7086 fname, nt_errstr(status));
7089 fnum = (uint16_t)-1;
7091 /* Now try and open for FILE_READ_DATA|FILE_WRITE_DATA */
7092 status = cli_ntcreate(cli,
7095 FILE_READ_DATA|FILE_WRITE_DATA,
7096 FILE_ATTRIBUTE_NORMAL,
7097 FILE_SHARE_READ|FILE_SHARE_WRITE|
7104 if (!NT_STATUS_IS_OK(status)) {
7105 printf("Open of %s - %s\n", fname, nt_errstr(status));
7109 status = cli_close(cli, fnum);
7110 if (!NT_STATUS_IS_OK(status)) {
7111 printf("close failed for %s (%s)\n",
7112 fname, nt_errstr(status));
7116 cli_unlink(cli, fname,
7117 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7125 if (fnum != (uint16_t)-1) {
7126 cli_close(cli, fnum);
7128 cli_unlink(cli, fname,
7129 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7130 torture_close_connection(cli);
7138 * Test SMB1-specific open with SEC_FLAG_SYSTEM_SECURITY.
7139 * Note this test only works with a user with SeSecurityPrivilege set.
7141 * NB. This is also tested in samba3.base.createx_access
7142 * but this makes it very explicit what we're looking for.
7144 static bool run_smb1_system_security(int dummy)
7146 static struct cli_state *cli = NULL;
7147 const char *fname = "system_security.txt";
7148 uint16_t fnum = (uint16_t)-1;
7150 TALLOC_CTX *frame = NULL;
7152 frame = talloc_stackframe();
7153 printf("starting smb1 system security test\n");
7155 /* SMB1 connection - torture_open_connection() forces this. */
7156 if (!torture_open_connection(&cli, 0)) {
7160 smbXcli_conn_set_sockopt(cli->conn, sockops);
7162 /* Start with a clean slate. */
7163 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7165 /* Create the test file. */
7166 status = cli_ntcreate(cli,
7170 FILE_ATTRIBUTE_NORMAL,
7171 FILE_SHARE_READ|FILE_SHARE_WRITE|
7178 if (!NT_STATUS_IS_OK(status)) {
7179 printf("Create of %s - %s\n", fname, nt_errstr(status));
7183 status = cli_close(cli, fnum);
7185 /* Open with SEC_FLAG_SYSTEM_SECURITY only. */
7187 * On SMB1 this succeeds - SMB2 it fails,
7188 * see the SMB2-SACL test.
7190 status = cli_ntcreate(cli,
7193 SEC_FLAG_SYSTEM_SECURITY,
7194 FILE_ATTRIBUTE_NORMAL,
7195 FILE_SHARE_READ|FILE_SHARE_WRITE|
7202 if (!NT_STATUS_IS_OK(status)) {
7203 printf("Open of %s - %s\n", fname, nt_errstr(status));
7207 status = cli_close(cli, fnum);
7209 cli_unlink(cli, fname,
7210 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7212 torture_close_connection(cli);
7219 if (fnum != (uint16_t)-1) {
7220 cli_close(cli, fnum);
7222 cli_unlink(cli, fname,
7223 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7224 torture_close_connection(cli);
7231 static bool run_pipe_number(int dummy)
7233 struct cli_state *cli1;
7234 const char *pipe_name = "\\SPOOLSS";
7239 printf("starting pipenumber test\n");
7240 if (!torture_open_connection(&cli1, 0)) {
7244 smbXcli_conn_set_sockopt(cli1->conn, sockops);
7246 status = cli_ntcreate(cli1, pipe_name, 0, FILE_READ_DATA,
7247 FILE_ATTRIBUTE_NORMAL,
7248 FILE_SHARE_READ|FILE_SHARE_WRITE,
7249 FILE_OPEN_IF, 0, 0, &fnum, NULL);
7250 if (!NT_STATUS_IS_OK(status)) {
7251 printf("Open of pipe %s failed with error (%s)\n", pipe_name, nt_errstr(status));
7255 printf("\r%6d", num_pipes);
7258 printf("pipe_number test - we can open %d %s pipes.\n", num_pipes, pipe_name );
7259 torture_close_connection(cli1);
7264 Test open mode returns on read-only files.
7266 static bool run_opentest(int dummy)
7268 static struct cli_state *cli1;
7269 static struct cli_state *cli2;
7270 const char *fname = "\\readonly.file";
7271 uint16_t fnum1, fnum2;
7274 bool correct = True;
7278 printf("starting open test\n");
7280 if (!torture_open_connection(&cli1, 0)) {
7284 cli_setatr(cli1, fname, 0, 0);
7285 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7287 smbXcli_conn_set_sockopt(cli1->conn, sockops);
7289 status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
7290 if (!NT_STATUS_IS_OK(status)) {
7291 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
7295 status = cli_close(cli1, fnum1);
7296 if (!NT_STATUS_IS_OK(status)) {
7297 printf("close2 failed (%s)\n", nt_errstr(status));
7301 status = cli_setatr(cli1, fname, FILE_ATTRIBUTE_READONLY, 0);
7302 if (!NT_STATUS_IS_OK(status)) {
7303 printf("cli_setatr failed (%s)\n", nt_errstr(status));
7307 status = cli_openx(cli1, fname, O_RDONLY, DENY_WRITE, &fnum1);
7308 if (!NT_STATUS_IS_OK(status)) {
7309 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
7313 /* This will fail - but the error should be ERRnoaccess, not ERRbadshare. */
7314 status = cli_openx(cli1, fname, O_RDWR, DENY_ALL, &fnum2);
7316 if (check_error(__LINE__, status, ERRDOS, ERRnoaccess,
7317 NT_STATUS_ACCESS_DENIED)) {
7318 printf("correct error code ERRDOS/ERRnoaccess returned\n");
7321 printf("finished open test 1\n");
7323 cli_close(cli1, fnum1);
7325 /* Now try not readonly and ensure ERRbadshare is returned. */
7327 cli_setatr(cli1, fname, 0, 0);
7329 status = cli_openx(cli1, fname, O_RDONLY, DENY_WRITE, &fnum1);
7330 if (!NT_STATUS_IS_OK(status)) {
7331 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
7335 /* This will fail - but the error should be ERRshare. */
7336 status = cli_openx(cli1, fname, O_RDWR, DENY_ALL, &fnum2);
7338 if (check_error(__LINE__, status, ERRDOS, ERRbadshare,
7339 NT_STATUS_SHARING_VIOLATION)) {
7340 printf("correct error code ERRDOS/ERRbadshare returned\n");
7343 status = cli_close(cli1, fnum1);
7344 if (!NT_STATUS_IS_OK(status)) {
7345 printf("close2 failed (%s)\n", nt_errstr(status));
7349 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7351 printf("finished open test 2\n");
7353 /* Test truncate open disposition on file opened for read. */
7354 status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
7355 if (!NT_STATUS_IS_OK(status)) {
7356 printf("(3) open (1) of %s failed (%s)\n", fname, nt_errstr(status));
7360 /* write 20 bytes. */
7362 memset(buf, '\0', 20);
7364 status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 0, 20, NULL);
7365 if (!NT_STATUS_IS_OK(status)) {
7366 printf("write failed (%s)\n", nt_errstr(status));
7370 status = cli_close(cli1, fnum1);
7371 if (!NT_STATUS_IS_OK(status)) {
7372 printf("(3) close1 failed (%s)\n", nt_errstr(status));
7376 /* Ensure size == 20. */
7377 status = cli_getatr(cli1, fname, NULL, &fsize, NULL);
7378 if (!NT_STATUS_IS_OK(status)) {
7379 printf("(3) getatr failed (%s)\n", nt_errstr(status));
7384 printf("(3) file size != 20\n");
7388 /* Now test if we can truncate a file opened for readonly. */
7389 status = cli_openx(cli1, fname, O_RDONLY|O_TRUNC, DENY_NONE, &fnum1);
7390 if (!NT_STATUS_IS_OK(status)) {
7391 printf("(3) open (2) of %s failed (%s)\n", fname, nt_errstr(status));
7395 status = cli_close(cli1, fnum1);
7396 if (!NT_STATUS_IS_OK(status)) {
7397 printf("close2 failed (%s)\n", nt_errstr(status));
7401 /* Ensure size == 0. */
7402 status = cli_getatr(cli1, fname, NULL, &fsize, NULL);
7403 if (!NT_STATUS_IS_OK(status)) {
7404 printf("(3) getatr failed (%s)\n", nt_errstr(status));
7409 printf("(3) file size != 0\n");
7412 printf("finished open test 3\n");
7414 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7416 printf("Do ctemp tests\n");
7417 status = cli_ctemp(cli1, talloc_tos(), "\\", &fnum1, &tmp_path);
7418 if (!NT_STATUS_IS_OK(status)) {
7419 printf("ctemp failed (%s)\n", nt_errstr(status));
7423 printf("ctemp gave path %s\n", tmp_path);
7424 status = cli_close(cli1, fnum1);
7425 if (!NT_STATUS_IS_OK(status)) {
7426 printf("close of temp failed (%s)\n", nt_errstr(status));
7429 status = cli_unlink(cli1, tmp_path, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7430 if (!NT_STATUS_IS_OK(status)) {
7431 printf("unlink of temp failed (%s)\n", nt_errstr(status));
7434 /* Test the non-io opens... */
7436 if (!torture_open_connection(&cli2, 1)) {
7440 cli_setatr(cli2, fname, 0, 0);
7441 cli_unlink(cli2, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7443 smbXcli_conn_set_sockopt(cli2->conn, sockops);
7445 printf("TEST #1 testing 2 non-io opens (no delete)\n");
7446 status = cli_ntcreate(cli1, fname, 0, FILE_READ_ATTRIBUTES,
7447 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7448 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
7449 if (!NT_STATUS_IS_OK(status)) {
7450 printf("TEST #1 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
7454 status = cli_ntcreate(cli2, fname, 0, FILE_READ_ATTRIBUTES,
7455 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7456 FILE_OPEN_IF, 0, 0, &fnum2, NULL);
7457 if (!NT_STATUS_IS_OK(status)) {
7458 printf("TEST #1 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
7462 status = cli_close(cli1, fnum1);
7463 if (!NT_STATUS_IS_OK(status)) {
7464 printf("TEST #1 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
7468 status = cli_close(cli2, fnum2);
7469 if (!NT_STATUS_IS_OK(status)) {
7470 printf("TEST #1 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
7474 printf("non-io open test #1 passed.\n");
7476 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7478 printf("TEST #2 testing 2 non-io opens (first with delete)\n");
7480 status = cli_ntcreate(cli1, fname, 0,
7481 DELETE_ACCESS|FILE_READ_ATTRIBUTES,
7482 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7483 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
7484 if (!NT_STATUS_IS_OK(status)) {
7485 printf("TEST #2 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
7489 status = cli_ntcreate(cli2, fname, 0, FILE_READ_ATTRIBUTES,
7490 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7491 FILE_OPEN_IF, 0, 0, &fnum2, NULL);
7492 if (!NT_STATUS_IS_OK(status)) {
7493 printf("TEST #2 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
7497 status = cli_close(cli1, fnum1);
7498 if (!NT_STATUS_IS_OK(status)) {
7499 printf("TEST #2 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
7503 status = cli_close(cli2, fnum2);
7504 if (!NT_STATUS_IS_OK(status)) {
7505 printf("TEST #2 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
7509 printf("non-io open test #2 passed.\n");
7511 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7513 printf("TEST #3 testing 2 non-io opens (second with delete)\n");
7515 status = cli_ntcreate(cli1, fname, 0, FILE_READ_ATTRIBUTES,
7516 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7517 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
7518 if (!NT_STATUS_IS_OK(status)) {
7519 printf("TEST #3 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
7523 status = cli_ntcreate(cli2, fname, 0,
7524 DELETE_ACCESS|FILE_READ_ATTRIBUTES,
7525 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7526 FILE_OPEN_IF, 0, 0, &fnum2, NULL);
7527 if (!NT_STATUS_IS_OK(status)) {
7528 printf("TEST #3 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
7532 status = cli_close(cli1, fnum1);
7533 if (!NT_STATUS_IS_OK(status)) {
7534 printf("TEST #3 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
7538 status = cli_close(cli2, fnum2);
7539 if (!NT_STATUS_IS_OK(status)) {
7540 printf("TEST #3 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
7544 printf("non-io open test #3 passed.\n");
7546 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7548 printf("TEST #4 testing 2 non-io opens (both with delete)\n");
7550 status = cli_ntcreate(cli1, fname, 0,
7551 DELETE_ACCESS|FILE_READ_ATTRIBUTES,
7552 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7553 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
7554 if (!NT_STATUS_IS_OK(status)) {
7555 printf("TEST #4 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
7559 status = cli_ntcreate(cli2, fname, 0,
7560 DELETE_ACCESS|FILE_READ_ATTRIBUTES,
7561 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7562 FILE_OPEN_IF, 0, 0, &fnum2, NULL);
7563 if (NT_STATUS_IS_OK(status)) {
7564 printf("TEST #4 open 2 of %s SUCCEEDED - should have failed (%s)\n", fname, nt_errstr(status));
7568 printf("TEST #4 open 2 of %s gave %s (correct error should be %s)\n", fname, nt_errstr(status), "sharing violation");
7570 status = cli_close(cli1, fnum1);
7571 if (!NT_STATUS_IS_OK(status)) {
7572 printf("TEST #4 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
7576 printf("non-io open test #4 passed.\n");
7578 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7580 printf("TEST #5 testing 2 non-io opens (both with delete - both with file share delete)\n");
7582 status = cli_ntcreate(cli1, fname, 0,
7583 DELETE_ACCESS|FILE_READ_ATTRIBUTES,
7584 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_DELETE,
7585 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
7586 if (!NT_STATUS_IS_OK(status)) {
7587 printf("TEST #5 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
7591 status = cli_ntcreate(cli2, fname, 0,
7592 DELETE_ACCESS|FILE_READ_ATTRIBUTES,
7593 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_DELETE,
7594 FILE_OPEN_IF, 0, 0, &fnum2, NULL);
7595 if (!NT_STATUS_IS_OK(status)) {
7596 printf("TEST #5 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
7600 status = cli_close(cli1, fnum1);
7601 if (!NT_STATUS_IS_OK(status)) {
7602 printf("TEST #5 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
7606 status = cli_close(cli2, fnum2);
7607 if (!NT_STATUS_IS_OK(status)) {
7608 printf("TEST #5 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
7612 printf("non-io open test #5 passed.\n");
7614 printf("TEST #6 testing 1 non-io open, one io open\n");
7616 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7618 status = cli_ntcreate(cli1, fname, 0, FILE_READ_DATA,
7619 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7620 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
7621 if (!NT_STATUS_IS_OK(status)) {
7622 printf("TEST #6 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
7626 status = cli_ntcreate(cli2, fname, 0, FILE_READ_ATTRIBUTES,
7627 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ,
7628 FILE_OPEN_IF, 0, 0, &fnum2, NULL);
7629 if (!NT_STATUS_IS_OK(status)) {
7630 printf("TEST #6 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
7634 status = cli_close(cli1, fnum1);
7635 if (!NT_STATUS_IS_OK(status)) {
7636 printf("TEST #6 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
7640 status = cli_close(cli2, fnum2);
7641 if (!NT_STATUS_IS_OK(status)) {
7642 printf("TEST #6 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
7646 printf("non-io open test #6 passed.\n");
7648 printf("TEST #7 testing 1 non-io open, one io open with delete\n");
7650 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7652 status = cli_ntcreate(cli1, fname, 0, FILE_READ_DATA,
7653 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7654 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
7655 if (!NT_STATUS_IS_OK(status)) {
7656 printf("TEST #7 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
7660 status = cli_ntcreate(cli2, fname, 0,
7661 DELETE_ACCESS|FILE_READ_ATTRIBUTES,
7662 FILE_ATTRIBUTE_NORMAL,
7663 FILE_SHARE_READ|FILE_SHARE_DELETE,
7664 FILE_OPEN_IF, 0, 0, &fnum2, NULL);
7665 if (NT_STATUS_IS_OK(status)) {
7666 printf("TEST #7 open 2 of %s SUCCEEDED - should have failed (%s)\n", fname, nt_errstr(status));
7670 printf("TEST #7 open 2 of %s gave %s (correct error should be %s)\n", fname, nt_errstr(status), "sharing violation");
7672 status = cli_close(cli1, fnum1);
7673 if (!NT_STATUS_IS_OK(status)) {
7674 printf("TEST #7 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
7678 printf("non-io open test #7 passed.\n");
7680 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7682 printf("TEST #8 testing open without WRITE_ATTRIBUTES, updating close write time.\n");
7683 status = cli_ntcreate(cli1, fname, 0, FILE_WRITE_DATA, FILE_ATTRIBUTE_NORMAL,
7684 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
7685 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
7686 if (!NT_STATUS_IS_OK(status)) {
7687 printf("TEST #8 open of %s failed (%s)\n", fname, nt_errstr(status));
7692 /* Write to ensure we have to update the file time. */
7693 status = cli_writeall(cli1, fnum1, 0, (const uint8_t *)"TEST DATA\n", 0, 10,
7695 if (!NT_STATUS_IS_OK(status)) {
7696 printf("TEST #8 cli_write failed: %s\n", nt_errstr(status));
7701 status = cli_close(cli1, fnum1);
7702 if (!NT_STATUS_IS_OK(status)) {
7703 printf("TEST #8 close of %s failed (%s)\n", fname, nt_errstr(status));
7709 if (!torture_close_connection(cli1)) {
7712 if (!torture_close_connection(cli2)) {
7719 NTSTATUS torture_setup_unix_extensions(struct cli_state *cli)
7721 uint16_t major, minor;
7722 uint32_t caplow, caphigh;
7725 if (!SERVER_HAS_UNIX_CIFS(cli)) {
7726 printf("Server doesn't support UNIX CIFS extensions.\n");
7727 return NT_STATUS_NOT_SUPPORTED;
7730 status = cli_unix_extensions_version(cli, &major, &minor, &caplow,
7732 if (!NT_STATUS_IS_OK(status)) {
7733 printf("Server didn't return UNIX CIFS extensions: %s\n",
7738 status = cli_set_unix_extensions_capabilities(cli, major, minor,
7740 if (!NT_STATUS_IS_OK(status)) {
7741 printf("Server doesn't support setting UNIX CIFS extensions: "
7742 "%s.\n", nt_errstr(status));
7746 return NT_STATUS_OK;
7750 Test POSIX open /mkdir calls.
7752 static bool run_simple_posix_open_test(int dummy)
7754 static struct cli_state *cli1;
7755 const char *fname = "posix:file";
7756 const char *hname = "posix:hlink";
7757 const char *sname = "posix:symlink";
7758 const char *dname = "posix:dir";
7760 char *target = NULL;
7761 uint16_t fnum1 = (uint16_t)-1;
7762 SMB_STRUCT_STAT sbuf;
7763 bool correct = false;
7766 const char *fname_windows = "windows_file";
7767 uint16_t fnum2 = (uint16_t)-1;
7770 printf("Starting simple POSIX open test\n");
7772 if (!torture_open_connection(&cli1, 0)) {
7776 smbXcli_conn_set_sockopt(cli1->conn, sockops);
7778 status = torture_setup_unix_extensions(cli1);
7779 if (!NT_STATUS_IS_OK(status)) {
7783 cli_setatr(cli1, fname, 0, 0);
7784 cli_posix_unlink(cli1, fname);
7785 cli_setatr(cli1, dname, 0, 0);
7786 cli_posix_rmdir(cli1, dname);
7787 cli_setatr(cli1, hname, 0, 0);
7788 cli_posix_unlink(cli1, hname);
7789 cli_setatr(cli1, sname, 0, 0);
7790 cli_posix_unlink(cli1, sname);
7791 cli_setatr(cli1, fname_windows, 0, 0);
7792 cli_posix_unlink(cli1, fname_windows);
7794 /* Create a directory. */
7795 status = cli_posix_mkdir(cli1, dname, 0777);
7796 if (!NT_STATUS_IS_OK(status)) {
7797 printf("POSIX mkdir of %s failed (%s)\n", dname, nt_errstr(status));
7801 status = cli_posix_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL,
7803 if (!NT_STATUS_IS_OK(status)) {
7804 printf("POSIX create of %s failed (%s)\n", fname, nt_errstr(status));
7808 /* Test ftruncate - set file size. */
7809 status = cli_ftruncate(cli1, fnum1, 1000);
7810 if (!NT_STATUS_IS_OK(status)) {
7811 printf("ftruncate failed (%s)\n", nt_errstr(status));
7815 /* Ensure st_size == 1000 */
7816 status = cli_posix_stat(cli1, fname, &sbuf);
7817 if (!NT_STATUS_IS_OK(status)) {
7818 printf("stat failed (%s)\n", nt_errstr(status));
7822 if (sbuf.st_ex_size != 1000) {
7823 printf("ftruncate - stat size (%u) != 1000\n", (unsigned int)sbuf.st_ex_size);
7827 /* Ensure st_mode == 0600 */
7828 if ((sbuf.st_ex_mode & 07777) != 0600) {
7829 printf("posix_open - bad permissions 0%o != 0600\n",
7830 (unsigned int)(sbuf.st_ex_mode & 07777));
7834 /* Test ftruncate - set file size back to zero. */
7835 status = cli_ftruncate(cli1, fnum1, 0);
7836 if (!NT_STATUS_IS_OK(status)) {
7837 printf("ftruncate failed (%s)\n", nt_errstr(status));
7841 status = cli_close(cli1, fnum1);
7842 if (!NT_STATUS_IS_OK(status)) {
7843 printf("close failed (%s)\n", nt_errstr(status));
7847 /* Now open the file again for read only. */
7848 status = cli_posix_open(cli1, fname, O_RDONLY, 0, &fnum1);
7849 if (!NT_STATUS_IS_OK(status)) {
7850 printf("POSIX open of %s failed (%s)\n", fname, nt_errstr(status));
7854 /* Now unlink while open. */
7855 status = cli_posix_unlink(cli1, fname);
7856 if (!NT_STATUS_IS_OK(status)) {
7857 printf("POSIX unlink of %s failed (%s)\n", fname, nt_errstr(status));
7861 status = cli_close(cli1, fnum1);
7862 if (!NT_STATUS_IS_OK(status)) {
7863 printf("close(2) failed (%s)\n", nt_errstr(status));
7867 /* Ensure the file has gone. */
7868 status = cli_posix_open(cli1, fname, O_RDONLY, 0, &fnum1);
7869 if (NT_STATUS_IS_OK(status)) {
7870 printf("POSIX open of %s succeeded, should have been deleted.\n", fname);
7874 /* Create again to test open with O_TRUNC. */
7875 status = cli_posix_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL, 0600, &fnum1);
7876 if (!NT_STATUS_IS_OK(status)) {
7877 printf("POSIX create of %s failed (%s)\n", fname, nt_errstr(status));
7881 /* Test ftruncate - set file size. */
7882 status = cli_ftruncate(cli1, fnum1, 1000);
7883 if (!NT_STATUS_IS_OK(status)) {
7884 printf("ftruncate failed (%s)\n", nt_errstr(status));
7888 /* Ensure st_size == 1000 */
7889 status = cli_posix_stat(cli1, fname, &sbuf);
7890 if (!NT_STATUS_IS_OK(status)) {
7891 printf("stat failed (%s)\n", nt_errstr(status));
7895 if (sbuf.st_ex_size != 1000) {
7896 printf("ftruncate - stat size (%u) != 1000\n", (unsigned int)sbuf.st_ex_size);
7900 status = cli_close(cli1, fnum1);
7901 if (!NT_STATUS_IS_OK(status)) {
7902 printf("close(2) failed (%s)\n", nt_errstr(status));
7906 /* Re-open with O_TRUNC. */
7907 status = cli_posix_open(cli1, fname, O_WRONLY|O_TRUNC, 0600, &fnum1);
7908 if (!NT_STATUS_IS_OK(status)) {
7909 printf("POSIX create of %s failed (%s)\n", fname, nt_errstr(status));
7913 /* Ensure st_size == 0 */
7914 status = cli_posix_stat(cli1, fname, &sbuf);
7915 if (!NT_STATUS_IS_OK(status)) {
7916 printf("stat failed (%s)\n", nt_errstr(status));
7920 if (sbuf.st_ex_size != 0) {
7921 printf("O_TRUNC - stat size (%u) != 0\n", (unsigned int)sbuf.st_ex_size);
7925 status = cli_close(cli1, fnum1);
7926 if (!NT_STATUS_IS_OK(status)) {
7927 printf("close failed (%s)\n", nt_errstr(status));
7931 status = cli_posix_unlink(cli1, fname);
7932 if (!NT_STATUS_IS_OK(status)) {
7933 printf("POSIX unlink of %s failed (%s)\n", fname, nt_errstr(status));
7937 status = cli_posix_open(cli1, dname, O_RDONLY, 0, &fnum1);
7938 if (!NT_STATUS_IS_OK(status)) {
7939 printf("POSIX open directory O_RDONLY of %s failed (%s)\n",
7940 dname, nt_errstr(status));
7944 cli_close(cli1, fnum1);
7946 /* What happens when we try and POSIX open a directory for write ? */
7947 status = cli_posix_open(cli1, dname, O_RDWR, 0, &fnum1);
7948 if (NT_STATUS_IS_OK(status)) {
7949 printf("POSIX open of directory %s succeeded, "
7950 "should have failed.\n",
7954 if (!check_both_error(__LINE__, status, ERRDOS, EISDIR,
7955 NT_STATUS_FILE_IS_A_DIRECTORY)) {
7960 /* Create the file. */
7961 status = cli_posix_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL,
7963 if (!NT_STATUS_IS_OK(status)) {
7964 printf("POSIX create of %s failed (%s)\n", fname, nt_errstr(status));
7968 /* Write some data into it. */
7969 status = cli_writeall(cli1, fnum1, 0, (const uint8_t *)"TEST DATA\n", 0, 10,
7971 if (!NT_STATUS_IS_OK(status)) {
7972 printf("cli_write failed: %s\n", nt_errstr(status));
7976 cli_close(cli1, fnum1);
7978 /* Now create a hardlink. */
7979 status = cli_posix_hardlink(cli1, fname, hname);
7980 if (!NT_STATUS_IS_OK(status)) {
7981 printf("POSIX hardlink of %s failed (%s)\n", hname, nt_errstr(status));
7985 /* Now create a symlink. */
7986 status = cli_posix_symlink(cli1, fname, sname);
7987 if (!NT_STATUS_IS_OK(status)) {
7988 printf("POSIX symlink of %s failed (%s)\n", sname, nt_errstr(status));
7992 /* Open the hardlink for read. */
7993 status = cli_posix_open(cli1, hname, O_RDONLY, 0, &fnum1);
7994 if (!NT_STATUS_IS_OK(status)) {
7995 printf("POSIX open of %s failed (%s)\n", hname, nt_errstr(status));
7999 status = cli_read(cli1, fnum1, buf, 0, 10, &nread);
8000 if (!NT_STATUS_IS_OK(status)) {
8001 printf("POSIX read of %s failed (%s)\n", hname,
8004 } else if (nread != 10) {
8005 printf("POSIX read of %s failed. Received %ld, expected %d\n",
8006 hname, (unsigned long)nread, 10);
8010 if (memcmp(buf, "TEST DATA\n", 10)) {
8011 printf("invalid data read from hardlink\n");
8015 /* Do a POSIX lock/unlock. */
8016 status = cli_posix_lock(cli1, fnum1, 0, 100, true, READ_LOCK);
8017 if (!NT_STATUS_IS_OK(status)) {
8018 printf("POSIX lock failed %s\n", nt_errstr(status));
8022 /* Punch a hole in the locked area. */
8023 status = cli_posix_unlock(cli1, fnum1, 10, 80);
8024 if (!NT_STATUS_IS_OK(status)) {
8025 printf("POSIX unlock failed %s\n", nt_errstr(status));
8029 cli_close(cli1, fnum1);
8031 /* Open the symlink for read - this should fail. A POSIX
8032 client should not be doing opens on a symlink. */
8033 status = cli_posix_open(cli1, sname, O_RDONLY, 0, &fnum1);
8034 if (NT_STATUS_IS_OK(status)) {
8035 printf("POSIX open of %s succeeded (should have failed)\n", sname);
8038 ok = check_both_error(
8039 __LINE__, status, ERRDOS, ERRbadpath,
8040 NT_STATUS_OBJECT_NAME_NOT_FOUND);
8042 printf("POSIX open of %s should have failed "
8043 "with NT_STATUS_OBJECT_NAME_NOT_FOUND, "
8044 "failed with %s instead.\n",
8045 sname, nt_errstr(status));
8049 status = cli_posix_readlink(cli1, sname, talloc_tos(), &target);
8050 if (!NT_STATUS_IS_OK(status)) {
8051 printf("POSIX readlink on %s failed (%s)\n", sname, nt_errstr(status));
8055 if (strcmp(target, fname) != 0) {
8056 printf("POSIX readlink on %s failed to match name %s (read %s)\n",
8057 sname, fname, target);
8061 status = cli_posix_rmdir(cli1, dname);
8062 if (!NT_STATUS_IS_OK(status)) {
8063 printf("POSIX rmdir failed (%s)\n", nt_errstr(status));
8067 /* Check directory opens with a specific permission. */
8068 status = cli_posix_mkdir(cli1, dname, 0700);
8069 if (!NT_STATUS_IS_OK(status)) {
8070 printf("POSIX mkdir of %s failed (%s)\n", dname, nt_errstr(status));
8074 /* Ensure st_mode == 0700 */
8075 status = cli_posix_stat(cli1, dname, &sbuf);
8076 if (!NT_STATUS_IS_OK(status)) {
8077 printf("stat failed (%s)\n", nt_errstr(status));
8081 if ((sbuf.st_ex_mode & 07777) != 0700) {
8082 printf("posix_mkdir - bad permissions 0%o != 0700\n",
8083 (unsigned int)(sbuf.st_ex_mode & 07777));
8088 * Now create a Windows file, and attempt a POSIX unlink.
8089 * This should fail with a sharing violation but due to:
8091 * [Bug 9571] Unlink after open causes smbd to panic
8093 * ensure we've fixed the lock ordering violation.
8096 status = cli_ntcreate(cli1, fname_windows, 0,
8097 FILE_READ_DATA|FILE_WRITE_DATA, 0,
8098 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
8100 0x0, 0x0, &fnum2, NULL);
8101 if (!NT_STATUS_IS_OK(status)) {
8102 printf("Windows create of %s failed (%s)\n", fname_windows,
8107 /* Now try posix_unlink. */
8108 status = cli_posix_unlink(cli1, fname_windows);
8109 if (!NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
8110 printf("POSIX unlink of %s should fail "
8111 "with NT_STATUS_SHARING_VIOLATION "
8112 "got %s instead !\n",
8118 cli_close(cli1, fnum2);
8120 printf("Simple POSIX open test passed\n");
8125 if (fnum1 != (uint16_t)-1) {
8126 cli_close(cli1, fnum1);
8127 fnum1 = (uint16_t)-1;
8130 if (fnum2 != (uint16_t)-1) {
8131 cli_close(cli1, fnum2);
8132 fnum2 = (uint16_t)-1;
8135 cli_setatr(cli1, sname, 0, 0);
8136 cli_posix_unlink(cli1, sname);
8137 cli_setatr(cli1, hname, 0, 0);
8138 cli_posix_unlink(cli1, hname);
8139 cli_setatr(cli1, fname, 0, 0);
8140 cli_posix_unlink(cli1, fname);
8141 cli_setatr(cli1, dname, 0, 0);
8142 cli_posix_rmdir(cli1, dname);
8143 cli_setatr(cli1, fname_windows, 0, 0);
8144 cli_posix_unlink(cli1, fname_windows);
8146 if (!torture_close_connection(cli1)) {
8154 Test POSIX and Windows ACLs are rejected on symlinks.
8156 static bool run_acl_symlink_test(int dummy)
8158 static struct cli_state *cli;
8159 const char *fname = "posix_file";
8160 const char *sname = "posix_symlink";
8161 uint16_t fnum = (uint16_t)-1;
8162 bool correct = false;
8164 char *posix_acl = NULL;
8165 size_t posix_acl_len = 0;
8166 char *posix_acl_sym = NULL;
8167 size_t posix_acl_len_sym = 0;
8168 struct security_descriptor *sd = NULL;
8169 TALLOC_CTX *frame = NULL;
8171 frame = talloc_stackframe();
8173 printf("Starting acl symlink test\n");
8175 if (!torture_open_connection(&cli, 0)) {
8180 smbXcli_conn_set_sockopt(cli->conn, sockops);
8182 status = torture_setup_unix_extensions(cli);
8183 if (!NT_STATUS_IS_OK(status)) {
8188 cli_setatr(cli, fname, 0, 0);
8189 cli_posix_unlink(cli, fname);
8190 cli_setatr(cli, sname, 0, 0);
8191 cli_posix_unlink(cli, sname);
8193 status = cli_ntcreate(cli,
8196 READ_CONTROL_ACCESS,
8198 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
8205 if (!NT_STATUS_IS_OK(status)) {
8206 printf("cli_ntcreate of %s failed (%s)\n",
8212 /* Get the Windows ACL on the file. */
8213 status = cli_query_secdesc(cli,
8217 if (!NT_STATUS_IS_OK(status)) {
8218 printf("cli_query_secdesc failed (%s)\n",
8223 /* Get the POSIX ACL on the file. */
8224 status = cli_posix_getacl(cli,
8230 if (!NT_STATUS_IS_OK(status)) {
8231 printf("cli_posix_getacl failed (%s)\n",
8236 status = cli_close(cli, fnum);
8237 if (!NT_STATUS_IS_OK(status)) {
8238 printf("close failed (%s)\n", nt_errstr(status));
8241 fnum = (uint16_t)-1;
8243 /* Now create a symlink. */
8244 status = cli_posix_symlink(cli, fname, sname);
8245 if (!NT_STATUS_IS_OK(status)) {
8246 printf("cli_posix_symlink of %s -> %s failed (%s)\n",
8253 /* Open a handle on the symlink for SD set/get should fail. */
8254 status = cli_ntcreate(cli,
8257 READ_CONTROL_ACCESS|SEC_STD_WRITE_DAC,
8259 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
8266 if (NT_STATUS_IS_OK(status)) {
8267 printf("Symlink open for getsd/setsd of %s "
8268 "succeeded (should fail)\n",
8273 /* Try a stat-open on the symlink, should also fail. */
8274 status = cli_ntcreate(cli,
8277 FILE_READ_ATTRIBUTES|FILE_WRITE_ATTRIBUTES,
8279 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
8286 if (NT_STATUS_IS_OK(status)) {
8287 printf("Stat-open of symlink succeeded (should fail)\n");
8291 /* Get the POSIX ACL on the symlink pathname. Should fail. */
8292 status = cli_posix_getacl(cli,
8298 if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
8299 printf("cli_posix_getacl on a symlink gave %s. "
8300 "Should be NT_STATUS_ACCESS_DENIED.\n",
8305 /* Set the POSIX ACL on the symlink pathname. Should fail. */
8306 status = cli_posix_setacl(cli,
8311 if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
8312 printf("cli_posix_setacl on a symlink gave %s. "
8313 "Should be NT_STATUS_ACCESS_DENIED.\n",
8318 printf("ACL symlink test passed\n");
8323 if (fnum != (uint16_t)-1) {
8324 cli_close(cli, fnum);
8325 fnum = (uint16_t)-1;
8328 cli_setatr(cli, sname, 0, 0);
8329 cli_posix_unlink(cli, sname);
8330 cli_setatr(cli, fname, 0, 0);
8331 cli_posix_unlink(cli, fname);
8333 if (!torture_close_connection(cli)) {
8342 Test POSIX can delete a file containing streams.
8344 static bool run_posix_stream_delete(int dummy)
8346 struct cli_state *cli1 = NULL;
8347 struct cli_state *cli2 = NULL;
8348 const char *fname = "streamfile";
8349 const char *stream_fname = "streamfile:Zone.Identifier:$DATA";
8350 uint16_t fnum1 = (uint16_t)-1;
8351 bool correct = false;
8353 TALLOC_CTX *frame = NULL;
8355 frame = talloc_stackframe();
8357 printf("Starting POSIX stream delete test\n");
8359 if (!torture_open_connection(&cli1, 0) ||
8360 !torture_open_connection(&cli2, 1)) {
8365 smbXcli_conn_set_sockopt(cli1->conn, sockops);
8366 smbXcli_conn_set_sockopt(cli2->conn, sockops);
8368 status = torture_setup_unix_extensions(cli2);
8369 if (!NT_STATUS_IS_OK(status)) {
8373 cli_setatr(cli1, fname, 0, 0);
8374 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
8376 /* Create the file. */
8377 status = cli_ntcreate(cli1,
8380 READ_CONTROL_ACCESS,
8382 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
8389 if (!NT_STATUS_IS_OK(status)) {
8390 printf("cli_ntcreate of %s failed (%s)\n",
8396 status = cli_close(cli1, fnum1);
8397 if (!NT_STATUS_IS_OK(status)) {
8398 printf("cli_close of %s failed (%s)\n",
8403 fnum1 = (uint16_t)-1;
8405 /* Now create the stream. */
8406 status = cli_ntcreate(cli1,
8411 FILE_SHARE_READ|FILE_SHARE_WRITE,
8418 if (!NT_STATUS_IS_OK(status)) {
8419 printf("cli_ntcreate of %s failed (%s)\n",
8425 /* Leave the stream handle open... */
8427 /* POSIX unlink should fail. */
8428 status = cli_posix_unlink(cli2, fname);
8429 if (NT_STATUS_IS_OK(status)) {
8430 printf("cli_posix_unlink of %s succeeded, should have failed\n",
8435 if (!NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
8436 printf("cli_posix_unlink of %s failed with (%s) "
8437 "should have been NT_STATUS_SHARING_VIOLATION\n",
8443 /* Close the stream handle. */
8444 status = cli_close(cli1, fnum1);
8445 if (!NT_STATUS_IS_OK(status)) {
8446 printf("cli_close of %s failed (%s)\n",
8451 fnum1 = (uint16_t)-1;
8453 /* POSIX unlink after stream handle closed should succeed. */
8454 status = cli_posix_unlink(cli2, fname);
8455 if (!NT_STATUS_IS_OK(status)) {
8456 printf("cli_posix_unlink of %s failed (%s)\n",
8462 printf("POSIX stream delete test passed\n");
8467 if (fnum1 != (uint16_t)-1) {
8468 cli_close(cli1, fnum1);
8469 fnum1 = (uint16_t)-1;
8472 cli_setatr(cli1, fname, 0, 0);
8473 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
8475 if (!torture_close_connection(cli1)) {
8478 if (!torture_close_connection(cli2)) {
8487 Test setting EA's are rejected on symlinks.
8489 static bool run_ea_symlink_test(int dummy)
8491 static struct cli_state *cli;
8492 const char *fname = "posix_file_ea";
8493 const char *sname = "posix_symlink_ea";
8494 const char *ea_name = "testea_name";
8495 const char *ea_value = "testea_value";
8496 uint16_t fnum = (uint16_t)-1;
8497 bool correct = false;
8500 struct ea_struct *eas = NULL;
8501 TALLOC_CTX *frame = NULL;
8503 frame = talloc_stackframe();
8505 printf("Starting EA symlink test\n");
8507 if (!torture_open_connection(&cli, 0)) {
8512 smbXcli_conn_set_sockopt(cli->conn, sockops);
8514 status = torture_setup_unix_extensions(cli);
8515 if (!NT_STATUS_IS_OK(status)) {
8520 cli_setatr(cli, fname, 0, 0);
8521 cli_posix_unlink(cli, fname);
8522 cli_setatr(cli, sname, 0, 0);
8523 cli_posix_unlink(cli, sname);
8525 status = cli_ntcreate(cli,
8528 READ_CONTROL_ACCESS,
8530 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
8537 if (!NT_STATUS_IS_OK(status)) {
8538 printf("cli_ntcreate of %s failed (%s)\n",
8544 status = cli_close(cli, fnum);
8545 if (!NT_STATUS_IS_OK(status)) {
8546 printf("close failed (%s)\n",
8550 fnum = (uint16_t)-1;
8552 /* Set an EA on the path. */
8553 status = cli_set_ea_path(cli,
8557 strlen(ea_value)+1);
8559 if (!NT_STATUS_IS_OK(status)) {
8560 printf("cli_set_ea_path failed (%s)\n",
8565 /* Now create a symlink. */
8566 status = cli_posix_symlink(cli, fname, sname);
8567 if (!NT_STATUS_IS_OK(status)) {
8568 printf("cli_posix_symlink of %s -> %s failed (%s)\n",
8575 /* Get the EA list on the path. Should return value set. */
8576 status = cli_get_ea_list_path(cli,
8582 if (!NT_STATUS_IS_OK(status)) {
8583 printf("cli_get_ea_list_path failed (%s)\n",
8588 /* Ensure the EA we set is there. */
8589 for (i=0; i<num_eas; i++) {
8590 if (strcmp(eas[i].name, ea_name) == 0 &&
8591 eas[i].value.length == strlen(ea_value)+1 &&
8592 memcmp(eas[i].value.data,
8594 eas[i].value.length) == 0) {
8600 printf("Didn't find EA on pathname %s\n",
8608 /* Get the EA list on the symlink. Should return empty list. */
8609 status = cli_get_ea_list_path(cli,
8615 if (!NT_STATUS_IS_OK(status)) {
8616 printf("cli_get_ea_list_path failed (%s)\n",
8622 printf("cli_get_ea_list_path failed (%s)\n",
8627 /* Set an EA on the symlink. Should fail. */
8628 status = cli_set_ea_path(cli,
8632 strlen(ea_value)+1);
8634 if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
8635 printf("cli_set_ea_path on a symlink gave %s. "
8636 "Should be NT_STATUS_ACCESS_DENIED.\n",
8641 printf("EA symlink test passed\n");
8646 if (fnum != (uint16_t)-1) {
8647 cli_close(cli, fnum);
8648 fnum = (uint16_t)-1;
8651 cli_setatr(cli, sname, 0, 0);
8652 cli_posix_unlink(cli, sname);
8653 cli_setatr(cli, fname, 0, 0);
8654 cli_posix_unlink(cli, fname);
8656 if (!torture_close_connection(cli)) {
8665 Test POSIX locks are OFD-locks.
8667 static bool run_posix_ofd_lock_test(int dummy)
8669 static struct cli_state *cli;
8670 const char *fname = "posix_file";
8671 uint16_t fnum1 = (uint16_t)-1;
8672 uint16_t fnum2 = (uint16_t)-1;
8673 bool correct = false;
8675 TALLOC_CTX *frame = NULL;
8677 frame = talloc_stackframe();
8679 printf("Starting POSIX ofd-lock test\n");
8681 if (!torture_open_connection(&cli, 0)) {
8686 smbXcli_conn_set_sockopt(cli->conn, sockops);
8688 status = torture_setup_unix_extensions(cli);
8689 if (!NT_STATUS_IS_OK(status)) {
8694 cli_setatr(cli, fname, 0, 0);
8695 cli_posix_unlink(cli, fname);
8697 /* Open the file twice. */
8698 status = cli_posix_open(cli, fname, O_RDWR|O_CREAT|O_EXCL,
8700 if (!NT_STATUS_IS_OK(status)) {
8701 printf("First POSIX open of %s failed\n", fname);
8705 status = cli_posix_open(cli, fname, O_RDWR, 0, &fnum2);
8706 if (!NT_STATUS_IS_OK(status)) {
8707 printf("First POSIX open of %s failed\n", fname);
8711 /* Set a 0-50 lock on fnum1. */
8712 status = cli_posix_lock(cli, fnum1, 0, 50, false, WRITE_LOCK);
8713 if (!NT_STATUS_IS_OK(status)) {
8714 printf("POSIX lock (1) failed %s\n", nt_errstr(status));
8718 /* Set a 60-100 lock on fnum2. */
8719 status = cli_posix_lock(cli, fnum2, 60, 100, false, WRITE_LOCK);
8720 if (!NT_STATUS_IS_OK(status)) {
8721 printf("POSIX lock (2) failed %s\n", nt_errstr(status));
8725 /* close fnum1 - 0-50 lock should go away. */
8726 status = cli_close(cli, fnum1);
8727 if (!NT_STATUS_IS_OK(status)) {
8728 printf("close failed (%s)\n",
8732 fnum1 = (uint16_t)-1;
8734 /* Change the lock context. */
8735 cli_setpid(cli, cli_getpid(cli) + 1);
8737 /* Re-open fnum1. */
8738 status = cli_posix_open(cli, fname, O_RDWR, 0, &fnum1);
8739 if (!NT_STATUS_IS_OK(status)) {
8740 printf("Third POSIX open of %s failed\n", fname);
8744 /* 60-100 lock should still be there. */
8745 status = cli_posix_lock(cli, fnum1, 60, 100, false, WRITE_LOCK);
8746 if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
8747 printf("POSIX lock 60-100 not there %s\n", nt_errstr(status));
8751 /* 0-50 lock should be gone. */
8752 status = cli_posix_lock(cli, fnum1, 0, 50, false, WRITE_LOCK);
8753 if (!NT_STATUS_IS_OK(status)) {
8754 printf("POSIX lock 0-50 failed %s\n", nt_errstr(status));
8758 printf("POSIX OFD lock test passed\n");
8763 if (fnum1 != (uint16_t)-1) {
8764 cli_close(cli, fnum1);
8765 fnum1 = (uint16_t)-1;
8767 if (fnum2 != (uint16_t)-1) {
8768 cli_close(cli, fnum2);
8769 fnum2 = (uint16_t)-1;
8772 cli_setatr(cli, fname, 0, 0);
8773 cli_posix_unlink(cli, fname);
8775 if (!torture_close_connection(cli)) {
8783 struct posix_blocking_state {
8784 struct tevent_context *ev;
8785 struct cli_state *cli1;
8787 struct cli_state *cli2;
8793 static void posix_blocking_locked(struct tevent_req *subreq);
8794 static void posix_blocking_gotblocked(struct tevent_req *subreq);
8795 static void posix_blocking_gotecho(struct tevent_req *subreq);
8796 static void posix_blocking_unlocked(struct tevent_req *subreq);
8798 static struct tevent_req *posix_blocking_send(
8799 TALLOC_CTX *mem_ctx,
8800 struct tevent_context *ev,
8801 struct cli_state *cli1,
8803 struct cli_state *cli2,
8806 struct tevent_req *req = NULL, *subreq = NULL;
8807 struct posix_blocking_state *state = NULL;
8809 req = tevent_req_create(mem_ctx, &state, struct posix_blocking_state);
8815 state->fnum1 = fnum1;
8817 state->fnum2 = fnum2;
8819 subreq = cli_posix_lock_send(
8828 if (tevent_req_nomem(subreq, req)) {
8829 return tevent_req_post(req, ev);
8831 tevent_req_set_callback(subreq, posix_blocking_locked, req);
8835 static void posix_blocking_locked(struct tevent_req *subreq)
8837 struct tevent_req *req = tevent_req_callback_data(
8838 subreq, struct tevent_req);
8839 struct posix_blocking_state *state = tevent_req_data(
8840 req, struct posix_blocking_state);
8843 status = cli_posix_lock_recv(subreq);
8844 TALLOC_FREE(subreq);
8845 if (tevent_req_nterror(req, status)) {
8849 subreq = cli_posix_lock_send(
8858 if (tevent_req_nomem(subreq, req)) {
8861 tevent_req_set_callback(subreq, posix_blocking_gotblocked, req);
8863 /* Make sure the blocking request is delivered */
8864 subreq = cli_echo_send(
8869 (DATA_BLOB) { .data = (uint8_t *)state, .length = 1 });
8870 if (tevent_req_nomem(subreq, req)) {
8873 tevent_req_set_callback(subreq, posix_blocking_gotecho, req);
8876 static void posix_blocking_gotblocked(struct tevent_req *subreq)
8878 struct tevent_req *req = tevent_req_callback_data(
8879 subreq, struct tevent_req);
8880 struct posix_blocking_state *state = tevent_req_data(
8881 req, struct posix_blocking_state);
8884 status = cli_posix_lock_recv(subreq);
8885 TALLOC_FREE(subreq);
8886 if (tevent_req_nterror(req, status)) {
8889 if (!state->gotecho) {
8890 printf("blocked req got through before echo\n");
8891 tevent_req_nterror(req, NT_STATUS_INVALID_LOCK_SEQUENCE);
8894 tevent_req_done(req);
8897 static void posix_blocking_gotecho(struct tevent_req *subreq)
8899 struct tevent_req *req = tevent_req_callback_data(
8900 subreq, struct tevent_req);
8901 struct posix_blocking_state *state = tevent_req_data(
8902 req, struct posix_blocking_state);
8905 status = cli_echo_recv(subreq);
8906 TALLOC_FREE(subreq);
8907 if (tevent_req_nterror(req, status)) {
8910 if (state->gotblocked) {
8911 printf("blocked req got through before echo\n");
8912 tevent_req_nterror(req, NT_STATUS_INVALID_LOCK_SEQUENCE);
8915 state->gotecho = true;
8917 subreq = cli_posix_lock_send(
8926 if (tevent_req_nomem(subreq, req)) {
8929 tevent_req_set_callback(subreq, posix_blocking_unlocked, req);
8932 static void posix_blocking_unlocked(struct tevent_req *subreq)
8934 struct tevent_req *req = tevent_req_callback_data(
8935 subreq, struct tevent_req);
8938 status = cli_posix_lock_recv(subreq);
8939 TALLOC_FREE(subreq);
8940 if (tevent_req_nterror(req, status)) {
8943 /* tevent_req_done in posix_blocking_gotlocked */
8946 static NTSTATUS posix_blocking_recv(struct tevent_req *req)
8948 return tevent_req_simple_recv_ntstatus(req);
8951 static bool run_posix_blocking_lock(int dummy)
8953 struct tevent_context *ev = NULL;
8954 struct cli_state *cli1 = NULL, *cli2 = NULL;
8955 const char *fname = "posix_blocking";
8956 uint16_t fnum1 = UINT16_MAX, fnum2 = UINT16_MAX;
8957 struct tevent_req *req = NULL;
8962 printf("Starting posix blocking lock test\n");
8964 ev = samba_tevent_context_init(NULL);
8969 ok = torture_open_connection(&cli1, 0);
8973 ok = torture_open_connection(&cli2, 0);
8978 smbXcli_conn_set_sockopt(cli1->conn, sockops);
8980 status = torture_setup_unix_extensions(cli1);
8981 if (!NT_STATUS_IS_OK(status)) {
8985 status = torture_setup_unix_extensions(cli2);
8986 if (!NT_STATUS_IS_OK(status)) {
8990 cli_setatr(cli1, fname, 0, 0);
8991 cli_posix_unlink(cli1, fname);
8993 status = cli_posix_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL,
8995 if (!NT_STATUS_IS_OK(status)) {
8996 printf("First POSIX open of %s failed: %s\n",
9002 status = cli_posix_open(cli2, fname, O_RDWR, 0600, &fnum2);
9003 if (!NT_STATUS_IS_OK(status)) {
9004 printf("Second POSIX open of %s failed: %s\n",
9010 req = posix_blocking_send(ev, ev, cli1, fnum1, cli2, fnum2);
9012 printf("cli_posix_blocking failed\n");
9016 ok = tevent_req_poll_ntstatus(req, ev, &status);
9018 printf("tevent_req_poll_ntstatus failed: %s\n",
9022 status = posix_blocking_recv(req);
9024 if (!NT_STATUS_IS_OK(status)) {
9025 printf("posix_blocking_recv returned %s\n",
9033 if (fnum1 != UINT16_MAX) {
9034 cli_close(cli1, fnum1);
9037 if (fnum2 != UINT16_MAX) {
9038 cli_close(cli2, fnum2);
9043 cli_setatr(cli1, fname, 0, 0);
9044 cli_posix_unlink(cli1, fname);
9050 ok &= torture_close_connection(cli1);
9054 ok &= torture_close_connection(cli2);
9066 Test POSIX mkdir is case-sensitive.
9068 static bool run_posix_mkdir_test(int dummy)
9070 static struct cli_state *cli;
9071 const char *fname_foo = "POSIX_foo";
9072 const char *fname_foo_Foo = "POSIX_foo/Foo";
9073 const char *fname_foo_foo = "POSIX_foo/foo";
9074 const char *fname_Foo = "POSIX_Foo";
9075 const char *fname_Foo_Foo = "POSIX_Foo/Foo";
9076 const char *fname_Foo_foo = "POSIX_Foo/foo";
9077 bool correct = false;
9079 TALLOC_CTX *frame = NULL;
9080 uint16_t fnum = (uint16_t)-1;
9082 frame = talloc_stackframe();
9084 printf("Starting POSIX mkdir test\n");
9086 if (!torture_open_connection(&cli, 0)) {
9091 smbXcli_conn_set_sockopt(cli->conn, sockops);
9093 status = torture_setup_unix_extensions(cli);
9094 if (!NT_STATUS_IS_OK(status)) {
9099 cli_posix_rmdir(cli, fname_foo_foo);
9100 cli_posix_rmdir(cli, fname_foo_Foo);
9101 cli_posix_rmdir(cli, fname_foo);
9103 cli_posix_rmdir(cli, fname_Foo_foo);
9104 cli_posix_rmdir(cli, fname_Foo_Foo);
9105 cli_posix_rmdir(cli, fname_Foo);
9108 * Create a file POSIX_foo then try
9109 * and use it in a directory path by
9110 * doing mkdir POSIX_foo/bar.
9111 * The mkdir should fail with
9112 * NT_STATUS_OBJECT_PATH_NOT_FOUND
9115 status = cli_posix_open(cli,
9120 if (!NT_STATUS_IS_OK(status)) {
9121 printf("cli_posix_open of %s failed error %s\n",
9127 status = cli_posix_mkdir(cli, fname_foo_foo, 0777);
9128 if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_PATH_NOT_FOUND)) {
9129 printf("cli_posix_mkdir of %s should fail with "
9130 "NT_STATUS_OBJECT_PATH_NOT_FOUND got "
9137 status = cli_close(cli, fnum);
9138 if (!NT_STATUS_IS_OK(status)) {
9139 printf("cli_close failed %s\n", nt_errstr(status));
9142 fnum = (uint16_t)-1;
9144 status = cli_posix_unlink(cli, fname_foo);
9145 if (!NT_STATUS_IS_OK(status)) {
9146 printf("cli_posix_unlink of %s failed error %s\n",
9153 * Now we've deleted everything, posix_mkdir, posix_rmdir,
9154 * posix_open, posix_unlink, on
9155 * POSIX_foo/foo should return NT_STATUS_OBJECT_PATH_NOT_FOUND
9156 * not silently create POSIX_foo/foo.
9159 status = cli_posix_mkdir(cli, fname_foo_foo, 0777);
9160 if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_PATH_NOT_FOUND)) {
9161 printf("cli_posix_mkdir of %s should fail with "
9162 "NT_STATUS_OBJECT_PATH_NOT_FOUND got "
9169 status = cli_posix_rmdir(cli, fname_foo_foo);
9170 if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_PATH_NOT_FOUND)) {
9171 printf("cli_posix_rmdir of %s should fail with "
9172 "NT_STATUS_OBJECT_PATH_NOT_FOUND got "
9179 status = cli_posix_open(cli,
9184 if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_PATH_NOT_FOUND)) {
9185 printf("cli_posix_open of %s should fail with "
9186 "NT_STATUS_OBJECT_PATH_NOT_FOUND got "
9193 status = cli_posix_unlink(cli, fname_foo_foo);
9194 if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_PATH_NOT_FOUND)) {
9195 printf("cli_posix_unlink of %s should fail with "
9196 "NT_STATUS_OBJECT_PATH_NOT_FOUND got "
9203 status = cli_posix_mkdir(cli, fname_foo, 0777);
9204 if (!NT_STATUS_IS_OK(status)) {
9205 printf("cli_posix_mkdir of %s failed\n", fname_foo);
9209 status = cli_posix_mkdir(cli, fname_Foo, 0777);
9210 if (!NT_STATUS_IS_OK(status)) {
9211 printf("cli_posix_mkdir of %s failed\n", fname_Foo);
9215 status = cli_posix_mkdir(cli, fname_foo_foo, 0777);
9216 if (!NT_STATUS_IS_OK(status)) {
9217 printf("cli_posix_mkdir of %s failed\n", fname_foo_foo);
9221 status = cli_posix_mkdir(cli, fname_foo_Foo, 0777);
9222 if (!NT_STATUS_IS_OK(status)) {
9223 printf("cli_posix_mkdir of %s failed\n", fname_foo_Foo);
9227 status = cli_posix_mkdir(cli, fname_Foo_foo, 0777);
9228 if (!NT_STATUS_IS_OK(status)) {
9229 printf("cli_posix_mkdir of %s failed\n", fname_Foo_foo);
9233 status = cli_posix_mkdir(cli, fname_Foo_Foo, 0777);
9234 if (!NT_STATUS_IS_OK(status)) {
9235 printf("cli_posix_mkdir of %s failed\n", fname_Foo_Foo);
9239 printf("POSIX mkdir test passed\n");
9244 if (fnum != (uint16_t)-1) {
9245 cli_close(cli, fnum);
9246 fnum = (uint16_t)-1;
9249 cli_posix_rmdir(cli, fname_foo_foo);
9250 cli_posix_rmdir(cli, fname_foo_Foo);
9251 cli_posix_rmdir(cli, fname_foo);
9253 cli_posix_rmdir(cli, fname_Foo_foo);
9254 cli_posix_rmdir(cli, fname_Foo_Foo);
9255 cli_posix_rmdir(cli, fname_Foo);
9257 if (!torture_close_connection(cli)) {
9265 struct posix_acl_oplock_state {
9266 struct tevent_context *ev;
9267 struct cli_state *cli;
9273 static void posix_acl_oplock_got_break(struct tevent_req *req)
9275 struct posix_acl_oplock_state *state = tevent_req_callback_data(
9276 req, struct posix_acl_oplock_state);
9281 status = cli_smb_oplock_break_waiter_recv(req, &fnum, &level);
9283 if (!NT_STATUS_IS_OK(status)) {
9284 printf("cli_smb_oplock_break_waiter_recv returned %s\n",
9288 *state->got_break = true;
9290 req = cli_oplock_ack_send(state, state->ev, state->cli, fnum,
9293 printf("cli_oplock_ack_send failed\n");
9298 static void posix_acl_oplock_got_acl(struct tevent_req *req)
9300 struct posix_acl_oplock_state *state = tevent_req_callback_data(
9301 req, struct posix_acl_oplock_state);
9302 size_t ret_size = 0;
9303 char *ret_data = NULL;
9305 state->status = cli_posix_getacl_recv(req,
9310 if (!NT_STATUS_IS_OK(state->status)) {
9311 printf("cli_posix_getacl_recv returned %s\n",
9312 nt_errstr(state->status));
9314 *state->acl_ret = true;
9317 static bool run_posix_acl_oplock_test(int dummy)
9319 struct tevent_context *ev;
9320 struct cli_state *cli1, *cli2;
9321 struct tevent_req *oplock_req, *getacl_req;
9322 const char *fname = "posix_acl_oplock";
9324 int saved_use_oplocks = use_oplocks;
9326 bool correct = true;
9327 bool got_break = false;
9328 bool acl_ret = false;
9330 struct posix_acl_oplock_state *state;
9332 printf("starting posix_acl_oplock test\n");
9334 if (!torture_open_connection(&cli1, 0)) {
9335 use_level_II_oplocks = false;
9336 use_oplocks = saved_use_oplocks;
9340 if (!torture_open_connection(&cli2, 1)) {
9341 use_level_II_oplocks = false;
9342 use_oplocks = saved_use_oplocks;
9346 /* Setup posix on cli2 only. */
9347 status = torture_setup_unix_extensions(cli2);
9348 if (!NT_STATUS_IS_OK(status)) {
9352 smbXcli_conn_set_sockopt(cli1->conn, sockops);
9353 smbXcli_conn_set_sockopt(cli2->conn, sockops);
9355 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
9357 /* Create the file on the Windows connection. */
9358 status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
9360 if (!NT_STATUS_IS_OK(status)) {
9361 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
9365 status = cli_close(cli1, fnum);
9366 if (!NT_STATUS_IS_OK(status)) {
9367 printf("close1 failed (%s)\n", nt_errstr(status));
9371 cli1->use_oplocks = true;
9373 /* Open with oplock. */
9374 status = cli_ntcreate(cli1,
9378 FILE_ATTRIBUTE_NORMAL,
9379 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
9386 if (!NT_STATUS_IS_OK(status)) {
9387 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
9391 ev = samba_tevent_context_init(talloc_tos());
9393 printf("tevent_context_init failed\n");
9397 state = talloc_zero(ev, struct posix_acl_oplock_state);
9398 if (state == NULL) {
9399 printf("talloc failed\n");
9404 state->got_break = &got_break;
9405 state->acl_ret = &acl_ret;
9407 oplock_req = cli_smb_oplock_break_waiter_send(
9408 talloc_tos(), ev, cli1);
9409 if (oplock_req == NULL) {
9410 printf("cli_smb_oplock_break_waiter_send failed\n");
9413 tevent_req_set_callback(oplock_req, posix_acl_oplock_got_break, state);
9415 /* Get ACL on POSIX connection - should break oplock. */
9416 getacl_req = cli_posix_getacl_send(talloc_tos(),
9420 if (getacl_req == NULL) {
9421 printf("cli_posix_getacl_send failed\n");
9424 tevent_req_set_callback(getacl_req, posix_acl_oplock_got_acl, state);
9426 while (!got_break || !acl_ret) {
9428 ret = tevent_loop_once(ev);
9430 printf("tevent_loop_once failed: %s\n",
9436 if (!NT_STATUS_IS_OK(state->status)) {
9437 printf("getacl failed (%s)\n", nt_errstr(state->status));
9441 status = cli_close(cli1, fnum);
9442 if (!NT_STATUS_IS_OK(status)) {
9443 printf("close2 failed (%s)\n", nt_errstr(status));
9447 status = cli_unlink(cli1,
9449 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
9450 if (!NT_STATUS_IS_OK(status)) {
9451 printf("unlink failed (%s)\n", nt_errstr(status));
9455 if (!torture_close_connection(cli1)) {
9458 if (!torture_close_connection(cli2)) {
9466 printf("finished posix acl oplock test\n");
9471 static bool run_posix_acl_shareroot_test(int dummy)
9473 struct cli_state *cli;
9475 bool correct = false;
9476 char *posix_acl = NULL;
9477 size_t posix_acl_len = 0;
9478 uint16_t num_file_acls = 0;
9479 uint16_t num_dir_acls = 0;
9481 uint32_t expected_size = 0;
9482 bool got_user = false;
9483 bool got_group = false;
9484 bool got_other = false;
9485 TALLOC_CTX *frame = NULL;
9487 frame = talloc_stackframe();
9489 printf("starting posix_acl_shareroot test\n");
9491 if (!torture_open_connection(&cli, 0)) {
9496 smbXcli_conn_set_sockopt(cli->conn, sockops);
9498 status = torture_setup_unix_extensions(cli);
9499 if (!NT_STATUS_IS_OK(status)) {
9500 printf("Failed to setup unix extensions\n");
9504 /* Get the POSIX ACL on the root of the share. */
9505 status = cli_posix_getacl(cli,
9511 if (!NT_STATUS_IS_OK(status)) {
9512 printf("cli_posix_getacl of '.' failed (%s)\n",
9517 if (posix_acl_len < 6 ||
9518 SVAL(posix_acl,0) != SMB_POSIX_ACL_VERSION) {
9519 printf("getfacl ., unknown POSIX acl version %u.\n",
9520 (unsigned int)CVAL(posix_acl,0) );
9524 num_file_acls = SVAL(posix_acl,2);
9525 num_dir_acls = SVAL(posix_acl,4);
9526 expected_size = SMB_POSIX_ACL_HEADER_SIZE +
9527 SMB_POSIX_ACL_ENTRY_SIZE*
9528 (num_file_acls+num_dir_acls);
9530 if (posix_acl_len != expected_size) {
9531 printf("incorrect POSIX acl buffer size "
9532 "(should be %u, was %u).\n",
9533 (unsigned int)expected_size,
9534 (unsigned int)posix_acl_len);
9539 * We don't need to know what the ACL's are
9540 * we just need to know we have at least 3
9541 * file entries (u,g,o).
9544 for (i = 0; i < num_file_acls; i++) {
9545 unsigned char tagtype =
9547 SMB_POSIX_ACL_HEADER_SIZE+
9548 (i*SMB_POSIX_ACL_ENTRY_SIZE));
9551 case SMB_POSIX_ACL_USER_OBJ:
9554 case SMB_POSIX_ACL_GROUP_OBJ:
9557 case SMB_POSIX_ACL_OTHER:
9566 printf("Missing user entry\n");
9571 printf("Missing group entry\n");
9576 printf("Missing other entry\n");
9584 if (!torture_close_connection(cli)) {
9588 printf("finished posix acl shareroot test\n");
9594 static uint32_t open_attrs_table[] = {
9595 FILE_ATTRIBUTE_NORMAL,
9596 FILE_ATTRIBUTE_ARCHIVE,
9597 FILE_ATTRIBUTE_READONLY,
9598 FILE_ATTRIBUTE_HIDDEN,
9599 FILE_ATTRIBUTE_SYSTEM,
9601 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY,
9602 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN,
9603 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM,
9604 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN,
9605 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM,
9606 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM,
9608 FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN,
9609 FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM,
9610 FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM,
9611 FILE_ATTRIBUTE_HIDDEN,FILE_ATTRIBUTE_SYSTEM,
9614 struct trunc_open_results {
9617 uint32_t trunc_attr;
9618 uint32_t result_attr;
9621 static struct trunc_open_results attr_results[] = {
9622 { 0, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_ARCHIVE },
9623 { 1, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_ARCHIVE },
9624 { 2, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_READONLY, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY },
9625 { 16, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_ARCHIVE },
9626 { 17, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_ARCHIVE },
9627 { 18, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_READONLY, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY },
9628 { 51, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
9629 { 54, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
9630 { 56, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN },
9631 { 68, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
9632 { 71, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
9633 { 73, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM },
9634 { 99, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_HIDDEN,FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
9635 { 102, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
9636 { 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 },
9637 { 116, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
9638 { 119, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
9639 { 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 },
9640 { 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 },
9641 { 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 },
9642 { 227, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
9643 { 230, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
9644 { 232, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN },
9645 { 244, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
9646 { 247, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
9647 { 249, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM }
9650 static bool run_openattrtest(int dummy)
9652 static struct cli_state *cli1;
9653 const char *fname = "\\openattr.file";
9655 bool correct = True;
9657 unsigned int i, j, k, l;
9660 printf("starting open attr test\n");
9662 if (!torture_open_connection(&cli1, 0)) {
9666 smbXcli_conn_set_sockopt(cli1->conn, sockops);
9668 for (k = 0, i = 0; i < sizeof(open_attrs_table)/sizeof(uint32_t); i++) {
9669 cli_setatr(cli1, fname, 0, 0);
9670 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
9672 status = cli_ntcreate(cli1, fname, 0, FILE_WRITE_DATA,
9673 open_attrs_table[i], FILE_SHARE_NONE,
9674 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
9675 if (!NT_STATUS_IS_OK(status)) {
9676 printf("open %d (1) of %s failed (%s)\n", i, fname, nt_errstr(status));
9680 status = cli_close(cli1, fnum1);
9681 if (!NT_STATUS_IS_OK(status)) {
9682 printf("close %d (1) of %s failed (%s)\n", i, fname, nt_errstr(status));
9686 for (j = 0; j < sizeof(open_attrs_table)/sizeof(uint32_t); j++) {
9687 status = cli_ntcreate(cli1, fname, 0,
9688 FILE_READ_DATA|FILE_WRITE_DATA,
9689 open_attrs_table[j],
9690 FILE_SHARE_NONE, FILE_OVERWRITE,
9691 0, 0, &fnum1, NULL);
9692 if (!NT_STATUS_IS_OK(status)) {
9693 for (l = 0; l < sizeof(attr_results)/sizeof(struct trunc_open_results); l++) {
9694 if (attr_results[l].num == k) {
9695 printf("[%d] trunc open 0x%x -> 0x%x of %s failed - should have succeeded !(0x%x:%s)\n",
9696 k, open_attrs_table[i],
9697 open_attrs_table[j],
9698 fname, NT_STATUS_V(status), nt_errstr(status));
9703 if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
9704 printf("[%d] trunc open 0x%x -> 0x%x failed with wrong error code %s\n",
9705 k, open_attrs_table[i], open_attrs_table[j],
9710 printf("[%d] trunc open 0x%x -> 0x%x failed\n", k, open_attrs_table[i], open_attrs_table[j]);
9716 status = cli_close(cli1, fnum1);
9717 if (!NT_STATUS_IS_OK(status)) {
9718 printf("close %d (2) of %s failed (%s)\n", j, fname, nt_errstr(status));
9722 status = cli_getatr(cli1, fname, &attr, NULL, NULL);
9723 if (!NT_STATUS_IS_OK(status)) {
9724 printf("getatr(2) failed (%s)\n", nt_errstr(status));
9729 printf("[%d] getatr check [0x%x] trunc [0x%x] got attr 0x%x\n",
9730 k, open_attrs_table[i], open_attrs_table[j], attr );
9733 for (l = 0; l < sizeof(attr_results)/sizeof(struct trunc_open_results); l++) {
9734 if (attr_results[l].num == k) {
9735 if (attr != attr_results[l].result_attr ||
9736 open_attrs_table[i] != attr_results[l].init_attr ||
9737 open_attrs_table[j] != attr_results[l].trunc_attr) {
9738 printf("getatr check failed. [0x%x] trunc [0x%x] got attr 0x%x, should be 0x%x\n",
9739 open_attrs_table[i],
9740 open_attrs_table[j],
9742 attr_results[l].result_attr);
9752 cli_setatr(cli1, fname, 0, 0);
9753 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
9755 printf("open attr test %s.\n", correct ? "passed" : "failed");
9757 if (!torture_close_connection(cli1)) {
9763 static NTSTATUS list_fn(struct file_info *finfo,
9764 const char *name, void *state)
9766 int *matched = (int *)state;
9767 if (matched != NULL) {
9770 return NT_STATUS_OK;
9774 test directory listing speed
9776 static bool run_dirtest(int dummy)
9779 static struct cli_state *cli;
9781 struct timeval core_start;
9782 bool correct = True;
9785 printf("starting directory test\n");
9787 if (!torture_open_connection(&cli, 0)) {
9791 smbXcli_conn_set_sockopt(cli->conn, sockops);
9794 for (i=0;i<torture_numops;i++) {
9796 slprintf(fname, sizeof(fname), "\\%x", (int)random());
9797 if (!NT_STATUS_IS_OK(cli_openx(cli, fname, O_RDWR|O_CREAT, DENY_NONE, &fnum))) {
9798 fprintf(stderr,"Failed to open %s\n", fname);
9801 cli_close(cli, fnum);
9804 core_start = timeval_current();
9807 cli_list(cli, "a*.*", 0, list_fn, &matched);
9808 printf("Matched %d\n", matched);
9811 cli_list(cli, "b*.*", 0, list_fn, &matched);
9812 printf("Matched %d\n", matched);
9815 cli_list(cli, "xyzabc", 0, list_fn, &matched);
9816 printf("Matched %d\n", matched);
9818 printf("dirtest core %g seconds\n", timeval_elapsed(&core_start));
9821 for (i=0;i<torture_numops;i++) {
9823 slprintf(fname, sizeof(fname), "\\%x", (int)random());
9824 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
9827 if (!torture_close_connection(cli)) {
9831 printf("finished dirtest\n");
9836 static NTSTATUS del_fn(struct file_info *finfo, const char *mask,
9839 struct cli_state *pcli = (struct cli_state *)state;
9841 slprintf(fname, sizeof(fname), "\\LISTDIR\\%s", finfo->name);
9843 if (strcmp(finfo->name, ".") == 0 || strcmp(finfo->name, "..") == 0)
9844 return NT_STATUS_OK;
9846 if (finfo->attr & FILE_ATTRIBUTE_DIRECTORY) {
9847 if (!NT_STATUS_IS_OK(cli_rmdir(pcli, fname)))
9848 printf("del_fn: failed to rmdir %s\n,", fname );
9850 if (!NT_STATUS_IS_OK(cli_unlink(pcli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN)))
9851 printf("del_fn: failed to unlink %s\n,", fname );
9853 return NT_STATUS_OK;
9858 sees what IOCTLs are supported
9860 bool torture_ioctl_test(int dummy)
9862 static struct cli_state *cli;
9863 uint16_t device, function;
9865 const char *fname = "\\ioctl.dat";
9869 if (!torture_open_connection(&cli, 0)) {
9873 printf("starting ioctl test\n");
9875 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
9877 status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
9878 if (!NT_STATUS_IS_OK(status)) {
9879 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
9883 status = cli_raw_ioctl(cli, fnum, 0x2d0000 | (0x0420<<2), &blob);
9884 printf("ioctl device info: %s\n", nt_errstr(status));
9886 status = cli_raw_ioctl(cli, fnum, IOCTL_QUERY_JOB_INFO, &blob);
9887 printf("ioctl job info: %s\n", nt_errstr(status));
9889 for (device=0;device<0x100;device++) {
9890 printf("ioctl test with device = 0x%x\n", device);
9891 for (function=0;function<0x100;function++) {
9892 uint32_t code = (device<<16) | function;
9894 status = cli_raw_ioctl(cli, fnum, code, &blob);
9896 if (NT_STATUS_IS_OK(status)) {
9897 printf("ioctl 0x%x OK : %d bytes\n", (int)code,
9899 data_blob_free(&blob);
9904 if (!torture_close_connection(cli)) {
9913 tries varients of chkpath
9915 bool torture_chkpath_test(int dummy)
9917 static struct cli_state *cli;
9922 if (!torture_open_connection(&cli, 0)) {
9926 printf("starting chkpath test\n");
9928 /* cleanup from an old run */
9929 torture_deltree(cli, "\\chkpath.dir");
9931 status = cli_mkdir(cli, "\\chkpath.dir");
9932 if (!NT_STATUS_IS_OK(status)) {
9933 printf("mkdir1 failed : %s\n", nt_errstr(status));
9937 status = cli_mkdir(cli, "\\chkpath.dir\\dir2");
9938 if (!NT_STATUS_IS_OK(status)) {
9939 printf("mkdir2 failed : %s\n", nt_errstr(status));
9943 status = cli_openx(cli, "\\chkpath.dir\\foo.txt", O_RDWR|O_CREAT|O_EXCL,
9945 if (!NT_STATUS_IS_OK(status)) {
9946 printf("open1 failed (%s)\n", nt_errstr(status));
9949 cli_close(cli, fnum);
9951 status = cli_chkpath(cli, "\\chkpath.dir");
9952 if (!NT_STATUS_IS_OK(status)) {
9953 printf("chkpath1 failed: %s\n", nt_errstr(status));
9957 status = cli_chkpath(cli, "\\chkpath.dir\\dir2");
9958 if (!NT_STATUS_IS_OK(status)) {
9959 printf("chkpath2 failed: %s\n", nt_errstr(status));
9963 status = cli_chkpath(cli, "\\chkpath.dir\\foo.txt");
9964 if (!NT_STATUS_IS_OK(status)) {
9965 ret = check_error(__LINE__, status, ERRDOS, ERRbadpath,
9966 NT_STATUS_NOT_A_DIRECTORY);
9968 printf("* chkpath on a file should fail\n");
9972 status = cli_chkpath(cli, "\\chkpath.dir\\bar.txt");
9973 if (!NT_STATUS_IS_OK(status)) {
9974 ret = check_error(__LINE__, status, ERRDOS, ERRbadfile,
9975 NT_STATUS_OBJECT_NAME_NOT_FOUND);
9977 printf("* chkpath on a non existent file should fail\n");
9981 status = cli_chkpath(cli, "\\chkpath.dir\\dirxx\\bar.txt");
9982 if (!NT_STATUS_IS_OK(status)) {
9983 ret = check_error(__LINE__, status, ERRDOS, ERRbadpath,
9984 NT_STATUS_OBJECT_PATH_NOT_FOUND);
9986 printf("* chkpath on a non existent component should fail\n");
9990 torture_deltree(cli, "\\chkpath.dir");
9992 if (!torture_close_connection(cli)) {
9999 static bool run_eatest(int dummy)
10001 static struct cli_state *cli;
10002 const char *fname = "\\eatest.txt";
10003 bool correct = True;
10006 struct ea_struct *ea_list = NULL;
10007 TALLOC_CTX *mem_ctx = talloc_init("eatest");
10010 printf("starting eatest\n");
10012 if (!torture_open_connection(&cli, 0)) {
10013 talloc_destroy(mem_ctx);
10017 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
10019 status = cli_ntcreate(cli, fname, 0,
10020 FIRST_DESIRED_ACCESS, FILE_ATTRIBUTE_ARCHIVE,
10021 FILE_SHARE_NONE, FILE_OVERWRITE_IF,
10022 0x4044, 0, &fnum, NULL);
10023 if (!NT_STATUS_IS_OK(status)) {
10024 printf("open failed - %s\n", nt_errstr(status));
10025 talloc_destroy(mem_ctx);
10029 for (i = 0; i < 10; i++) {
10030 fstring ea_name, ea_val;
10032 slprintf(ea_name, sizeof(ea_name), "EA_%zu", i);
10033 memset(ea_val, (char)i+1, i+1);
10034 status = cli_set_ea_fnum(cli, fnum, ea_name, ea_val, i+1);
10035 if (!NT_STATUS_IS_OK(status)) {
10036 printf("ea_set of name %s failed - %s\n", ea_name,
10037 nt_errstr(status));
10038 talloc_destroy(mem_ctx);
10043 cli_close(cli, fnum);
10044 for (i = 0; i < 10; i++) {
10045 fstring ea_name, ea_val;
10047 slprintf(ea_name, sizeof(ea_name), "EA_%zu", i+10);
10048 memset(ea_val, (char)i+1, i+1);
10049 status = cli_set_ea_path(cli, fname, ea_name, ea_val, i+1);
10050 if (!NT_STATUS_IS_OK(status)) {
10051 printf("ea_set of name %s failed - %s\n", ea_name,
10052 nt_errstr(status));
10053 talloc_destroy(mem_ctx);
10058 status = cli_get_ea_list_path(cli, fname, mem_ctx, &num_eas, &ea_list);
10059 if (!NT_STATUS_IS_OK(status)) {
10060 printf("ea_get list failed - %s\n", nt_errstr(status));
10064 printf("num_eas = %d\n", (int)num_eas);
10066 if (num_eas != 20) {
10067 printf("Should be 20 EA's stored... failing.\n");
10071 for (i = 0; i < num_eas; i++) {
10072 printf("%zu: ea_name = %s. Val = ", i, ea_list[i].name);
10073 dump_data(0, ea_list[i].value.data,
10074 ea_list[i].value.length);
10077 /* Setting EA's to zero length deletes them. Test this */
10078 printf("Now deleting all EA's - case indepenent....\n");
10081 cli_set_ea_path(cli, fname, "", "", 0);
10083 for (i = 0; i < 20; i++) {
10085 slprintf(ea_name, sizeof(ea_name), "ea_%d", i);
10086 status = cli_set_ea_path(cli, fname, ea_name, "", 0);
10087 if (!NT_STATUS_IS_OK(status)) {
10088 printf("ea_set of name %s failed - %s\n", ea_name,
10089 nt_errstr(status));
10090 talloc_destroy(mem_ctx);
10096 status = cli_get_ea_list_path(cli, fname, mem_ctx, &num_eas, &ea_list);
10097 if (!NT_STATUS_IS_OK(status)) {
10098 printf("ea_get list failed - %s\n", nt_errstr(status));
10102 printf("num_eas = %d\n", (int)num_eas);
10103 for (i = 0; i < num_eas; i++) {
10104 printf("%zu: ea_name = %s. Val = ", i, ea_list[i].name);
10105 dump_data(0, ea_list[i].value.data,
10106 ea_list[i].value.length);
10109 if (num_eas != 0) {
10110 printf("deleting EA's failed.\n");
10114 /* Try and delete a non existent EA. */
10115 status = cli_set_ea_path(cli, fname, "foo", "", 0);
10116 if (!NT_STATUS_IS_OK(status)) {
10117 printf("deleting non-existent EA 'foo' should succeed. %s\n",
10118 nt_errstr(status));
10122 talloc_destroy(mem_ctx);
10123 if (!torture_close_connection(cli)) {
10130 static bool run_dirtest1(int dummy)
10133 static struct cli_state *cli;
10136 bool correct = True;
10138 printf("starting directory test\n");
10140 if (!torture_open_connection(&cli, 0)) {
10144 smbXcli_conn_set_sockopt(cli->conn, sockops);
10146 cli_list(cli, "\\LISTDIR\\*", 0, del_fn, cli);
10147 cli_list(cli, "\\LISTDIR\\*", FILE_ATTRIBUTE_DIRECTORY, del_fn, cli);
10148 cli_rmdir(cli, "\\LISTDIR");
10149 cli_mkdir(cli, "\\LISTDIR");
10151 /* Create 1000 files and 1000 directories. */
10152 for (i=0;i<1000;i++) {
10154 slprintf(fname, sizeof(fname), "\\LISTDIR\\f%d", i);
10155 if (!NT_STATUS_IS_OK(cli_ntcreate(cli, fname, 0, GENERIC_ALL_ACCESS, FILE_ATTRIBUTE_ARCHIVE,
10156 FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OVERWRITE_IF,
10157 0, 0, &fnum, NULL))) {
10158 fprintf(stderr,"Failed to open %s\n", fname);
10161 cli_close(cli, fnum);
10163 for (i=0;i<1000;i++) {
10165 slprintf(fname, sizeof(fname), "\\LISTDIR\\d%d", i);
10166 if (!NT_STATUS_IS_OK(cli_mkdir(cli, fname))) {
10167 fprintf(stderr,"Failed to open %s\n", fname);
10172 /* Now ensure that doing an old list sees both files and directories. */
10174 cli_list_old(cli, "\\LISTDIR\\*", FILE_ATTRIBUTE_DIRECTORY, list_fn, &num_seen);
10175 printf("num_seen = %d\n", num_seen );
10176 /* We should see 100 files + 1000 directories + . and .. */
10177 if (num_seen != 2002)
10180 /* Ensure if we have the "must have" bits we only see the
10181 * relevent entries.
10184 cli_list_old(cli, "\\LISTDIR\\*", (FILE_ATTRIBUTE_DIRECTORY<<8)|FILE_ATTRIBUTE_DIRECTORY, list_fn, &num_seen);
10185 printf("num_seen = %d\n", num_seen );
10186 if (num_seen != 1002)
10190 cli_list_old(cli, "\\LISTDIR\\*", (FILE_ATTRIBUTE_ARCHIVE<<8)|FILE_ATTRIBUTE_DIRECTORY, list_fn, &num_seen);
10191 printf("num_seen = %d\n", num_seen );
10192 if (num_seen != 1000)
10195 /* Delete everything. */
10196 cli_list(cli, "\\LISTDIR\\*", 0, del_fn, cli);
10197 cli_list(cli, "\\LISTDIR\\*", FILE_ATTRIBUTE_DIRECTORY, del_fn, cli);
10198 cli_rmdir(cli, "\\LISTDIR");
10201 printf("Matched %d\n", cli_list(cli, "a*.*", 0, list_fn, NULL));
10202 printf("Matched %d\n", cli_list(cli, "b*.*", 0, list_fn, NULL));
10203 printf("Matched %d\n", cli_list(cli, "xyzabc", 0, list_fn, NULL));
10206 if (!torture_close_connection(cli)) {
10210 printf("finished dirtest1\n");
10215 static bool run_error_map_extract(int dummy) {
10217 static struct cli_state *c_dos;
10218 static struct cli_state *c_nt;
10226 NTSTATUS nt_status;
10230 /* NT-Error connection */
10232 disable_spnego = true;
10233 if (!(c_nt = open_nbt_connection())) {
10234 disable_spnego = false;
10237 disable_spnego = false;
10239 status = smbXcli_negprot(c_nt->conn, c_nt->timeout, PROTOCOL_CORE,
10242 if (!NT_STATUS_IS_OK(status)) {
10243 printf("%s rejected the NT-error negprot (%s)\n", host,
10244 nt_errstr(status));
10245 cli_shutdown(c_nt);
10249 status = cli_session_setup_anon(c_nt);
10250 if (!NT_STATUS_IS_OK(status)) {
10251 printf("%s rejected the NT-error initial session setup (%s)\n",host, nt_errstr(status));
10255 /* DOS-Error connection */
10257 disable_spnego = true;
10258 force_dos_errors = true;
10259 if (!(c_dos = open_nbt_connection())) {
10260 disable_spnego = false;
10261 force_dos_errors = false;
10264 disable_spnego = false;
10265 force_dos_errors = false;
10267 status = smbXcli_negprot(c_dos->conn, c_dos->timeout, PROTOCOL_CORE,
10269 if (!NT_STATUS_IS_OK(status)) {
10270 printf("%s rejected the DOS-error negprot (%s)\n", host,
10271 nt_errstr(status));
10272 cli_shutdown(c_dos);
10276 status = cli_session_setup_anon(c_dos);
10277 if (!NT_STATUS_IS_OK(status)) {
10278 printf("%s rejected the DOS-error initial session setup (%s)\n",
10279 host, nt_errstr(status));
10283 c_nt->map_dos_errors = false;
10284 c_dos->map_dos_errors = false;
10286 for (error=(0xc0000000 | 0x1); error < (0xc0000000| 0xFFF); error++) {
10287 struct cli_credentials *user_creds = NULL;
10289 fstr_sprintf(user, "%X", error);
10291 user_creds = cli_session_creds_init(talloc_tos(),
10296 false, /* use_kerberos */
10297 false, /* fallback_after_kerberos */
10298 false, /* use_ccache */
10299 false); /* password_is_nt_hash */
10300 if (user_creds == NULL) {
10301 printf("cli_session_creds_init(%s) failed\n", user);
10305 status = cli_session_setup_creds(c_nt, user_creds);
10306 if (NT_STATUS_IS_OK(status)) {
10307 printf("/** Session setup succeeded. This shouldn't happen...*/\n");
10310 /* Case #1: 32-bit NT errors */
10311 if (!NT_STATUS_IS_DOS(status)) {
10312 nt_status = status;
10314 printf("/** Dos error on NT connection! (%s) */\n",
10315 nt_errstr(status));
10316 nt_status = NT_STATUS(0xc0000000);
10319 status = cli_session_setup_creds(c_dos, user_creds);
10320 if (NT_STATUS_IS_OK(status)) {
10321 printf("/** Session setup succeeded. This shouldn't happen...*/\n");
10324 /* Case #1: 32-bit NT errors */
10325 if (NT_STATUS_IS_DOS(status)) {
10326 printf("/** NT error on DOS connection! (%s) */\n",
10327 nt_errstr(status));
10328 errnum = errclass = 0;
10330 errclass = NT_STATUS_DOS_CLASS(status);
10331 errnum = NT_STATUS_DOS_CODE(status);
10334 if (NT_STATUS_V(nt_status) != error) {
10335 printf("/*\t{ This NT error code was 'sqashed'\n\t from %s to %s \n\t during the session setup }\n*/\n",
10336 get_nt_error_c_code(talloc_tos(), NT_STATUS(error)),
10337 get_nt_error_c_code(talloc_tos(), nt_status));
10340 printf("\t{%s,\t%s,\t%s},\n",
10341 smb_dos_err_class(errclass),
10342 smb_dos_err_name(errclass, errnum),
10343 get_nt_error_c_code(talloc_tos(), NT_STATUS(error)));
10345 TALLOC_FREE(user_creds);
10350 static bool run_sesssetup_bench(int dummy)
10352 static struct cli_state *c;
10353 const char *fname = "\\file.dat";
10358 if (!torture_open_connection(&c, 0)) {
10362 status = cli_ntcreate(c, fname, 0, GENERIC_ALL_ACCESS|DELETE_ACCESS,
10363 FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
10364 FILE_DELETE_ON_CLOSE, 0, &fnum, NULL);
10365 if (!NT_STATUS_IS_OK(status)) {
10366 d_printf("open %s failed: %s\n", fname, nt_errstr(status));
10370 for (i=0; i<torture_numops; i++) {
10371 status = cli_session_setup_creds(c, torture_creds);
10372 if (!NT_STATUS_IS_OK(status)) {
10373 d_printf("(%s) cli_session_setup_creds failed: %s\n",
10374 __location__, nt_errstr(status));
10378 d_printf("\r%d ", (int)cli_state_get_uid(c));
10380 status = cli_ulogoff(c);
10381 if (!NT_STATUS_IS_OK(status)) {
10382 d_printf("(%s) cli_ulogoff failed: %s\n",
10383 __location__, nt_errstr(status));
10391 static bool subst_test(const char *str, const char *user, const char *domain,
10392 uid_t uid, gid_t gid, const char *expected)
10395 bool result = true;
10397 subst = talloc_sub_specified(talloc_tos(), str, user, NULL, domain, uid, gid);
10399 if (strcmp(subst, expected) != 0) {
10400 printf("sub_specified(%s, %s, %s, %d, %d) returned [%s], expected "
10401 "[%s]\n", str, user, domain, (int)uid, (int)gid, subst,
10406 TALLOC_FREE(subst);
10410 static void chain1_open_completion(struct tevent_req *req)
10414 status = cli_openx_recv(req, &fnum);
10417 d_printf("cli_openx_recv returned %s: %d\n",
10419 NT_STATUS_IS_OK(status) ? fnum : -1);
10422 static void chain1_write_completion(struct tevent_req *req)
10426 status = cli_write_andx_recv(req, &written);
10429 d_printf("cli_write_andx_recv returned %s: %d\n",
10431 NT_STATUS_IS_OK(status) ? (int)written : -1);
10434 static void chain1_close_completion(struct tevent_req *req)
10437 bool *done = (bool *)tevent_req_callback_data_void(req);
10439 status = cli_close_recv(req);
10444 d_printf("cli_close returned %s\n", nt_errstr(status));
10447 static bool run_chain1(int dummy)
10449 struct cli_state *cli1;
10450 struct tevent_context *evt = samba_tevent_context_init(NULL);
10451 struct tevent_req *reqs[3], *smbreqs[3];
10453 const char *str = "foobar";
10454 const char *fname = "\\test_chain";
10457 printf("starting chain1 test\n");
10458 if (!torture_open_connection(&cli1, 0)) {
10462 smbXcli_conn_set_sockopt(cli1->conn, sockops);
10464 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
10466 reqs[0] = cli_openx_create(talloc_tos(), evt, cli1, fname,
10467 O_CREAT|O_RDWR, 0, &smbreqs[0]);
10468 if (reqs[0] == NULL) return false;
10469 tevent_req_set_callback(reqs[0], chain1_open_completion, NULL);
10472 reqs[1] = cli_write_andx_create(talloc_tos(), evt, cli1, 0, 0,
10473 (const uint8_t *)str, 0, strlen(str)+1,
10474 smbreqs, 1, &smbreqs[1]);
10475 if (reqs[1] == NULL) return false;
10476 tevent_req_set_callback(reqs[1], chain1_write_completion, NULL);
10478 reqs[2] = cli_smb1_close_create(talloc_tos(), evt, cli1, 0, &smbreqs[2]);
10479 if (reqs[2] == NULL) return false;
10480 tevent_req_set_callback(reqs[2], chain1_close_completion, &done);
10482 status = smb1cli_req_chain_submit(smbreqs, ARRAY_SIZE(smbreqs));
10483 if (!NT_STATUS_IS_OK(status)) {
10488 tevent_loop_once(evt);
10491 torture_close_connection(cli1);
10495 static void chain2_sesssetup_completion(struct tevent_req *req)
10498 status = cli_session_setup_guest_recv(req);
10499 d_printf("sesssetup returned %s\n", nt_errstr(status));
10502 static void chain2_tcon_completion(struct tevent_req *req)
10504 bool *done = (bool *)tevent_req_callback_data_void(req);
10506 status = cli_tcon_andx_recv(req);
10507 d_printf("tcon_and_x returned %s\n", nt_errstr(status));
10511 static bool run_chain2(int dummy)
10513 struct cli_state *cli1;
10514 struct tevent_context *evt = samba_tevent_context_init(NULL);
10515 struct tevent_req *reqs[2], *smbreqs[2];
10518 int flags = CLI_FULL_CONNECTION_FORCE_SMB1;
10520 printf("starting chain2 test\n");
10521 status = cli_start_connection(&cli1, lp_netbios_name(), host, NULL,
10522 port_to_use, SMB_SIGNING_DEFAULT, flags);
10523 if (!NT_STATUS_IS_OK(status)) {
10527 smbXcli_conn_set_sockopt(cli1->conn, sockops);
10529 reqs[0] = cli_session_setup_guest_create(talloc_tos(), evt, cli1,
10531 if (reqs[0] == NULL) return false;
10532 tevent_req_set_callback(reqs[0], chain2_sesssetup_completion, NULL);
10534 reqs[1] = cli_tcon_andx_create(talloc_tos(), evt, cli1, "IPC$",
10535 "?????", NULL, 0, &smbreqs[1]);
10536 if (reqs[1] == NULL) return false;
10537 tevent_req_set_callback(reqs[1], chain2_tcon_completion, &done);
10539 status = smb1cli_req_chain_submit(smbreqs, ARRAY_SIZE(smbreqs));
10540 if (!NT_STATUS_IS_OK(status)) {
10545 tevent_loop_once(evt);
10548 torture_close_connection(cli1);
10553 struct torture_createdel_state {
10554 struct tevent_context *ev;
10555 struct cli_state *cli;
10558 static void torture_createdel_created(struct tevent_req *subreq);
10559 static void torture_createdel_closed(struct tevent_req *subreq);
10561 static struct tevent_req *torture_createdel_send(TALLOC_CTX *mem_ctx,
10562 struct tevent_context *ev,
10563 struct cli_state *cli,
10566 struct tevent_req *req, *subreq;
10567 struct torture_createdel_state *state;
10569 req = tevent_req_create(mem_ctx, &state,
10570 struct torture_createdel_state);
10577 subreq = cli_ntcreate_send(
10578 state, ev, cli, name, 0,
10579 FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
10580 FILE_ATTRIBUTE_NORMAL,
10581 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
10582 FILE_OPEN_IF, FILE_DELETE_ON_CLOSE,
10583 SMB2_IMPERSONATION_IMPERSONATION, 0);
10585 if (tevent_req_nomem(subreq, req)) {
10586 return tevent_req_post(req, ev);
10588 tevent_req_set_callback(subreq, torture_createdel_created, req);
10592 static void torture_createdel_created(struct tevent_req *subreq)
10594 struct tevent_req *req = tevent_req_callback_data(
10595 subreq, struct tevent_req);
10596 struct torture_createdel_state *state = tevent_req_data(
10597 req, struct torture_createdel_state);
10601 status = cli_ntcreate_recv(subreq, &fnum, NULL);
10602 TALLOC_FREE(subreq);
10603 if (tevent_req_nterror(req, status)) {
10604 DEBUG(10, ("cli_ntcreate_recv returned %s\n",
10605 nt_errstr(status)));
10609 subreq = cli_close_send(state, state->ev, state->cli, fnum);
10610 if (tevent_req_nomem(subreq, req)) {
10613 tevent_req_set_callback(subreq, torture_createdel_closed, req);
10616 static void torture_createdel_closed(struct tevent_req *subreq)
10618 struct tevent_req *req = tevent_req_callback_data(
10619 subreq, struct tevent_req);
10622 status = cli_close_recv(subreq);
10623 if (tevent_req_nterror(req, status)) {
10624 DEBUG(10, ("cli_close_recv returned %s\n", nt_errstr(status)));
10627 tevent_req_done(req);
10630 static NTSTATUS torture_createdel_recv(struct tevent_req *req)
10632 return tevent_req_simple_recv_ntstatus(req);
10635 struct torture_createdels_state {
10636 struct tevent_context *ev;
10637 struct cli_state *cli;
10638 const char *base_name;
10642 struct tevent_req **reqs;
10645 static void torture_createdels_done(struct tevent_req *subreq);
10647 static struct tevent_req *torture_createdels_send(TALLOC_CTX *mem_ctx,
10648 struct tevent_context *ev,
10649 struct cli_state *cli,
10650 const char *base_name,
10654 struct tevent_req *req;
10655 struct torture_createdels_state *state;
10658 req = tevent_req_create(mem_ctx, &state,
10659 struct torture_createdels_state);
10665 state->base_name = talloc_strdup(state, base_name);
10666 if (tevent_req_nomem(state->base_name, req)) {
10667 return tevent_req_post(req, ev);
10669 state->num_files = MAX(num_parallel, num_files);
10671 state->received = 0;
10673 state->reqs = talloc_array(state, struct tevent_req *, num_parallel);
10674 if (tevent_req_nomem(state->reqs, req)) {
10675 return tevent_req_post(req, ev);
10678 for (i=0; i<num_parallel; i++) {
10681 name = talloc_asprintf(state, "%s%8.8d", state->base_name,
10683 if (tevent_req_nomem(name, req)) {
10684 return tevent_req_post(req, ev);
10686 state->reqs[i] = torture_createdel_send(
10687 state->reqs, state->ev, state->cli, name);
10688 if (tevent_req_nomem(state->reqs[i], req)) {
10689 return tevent_req_post(req, ev);
10691 name = talloc_move(state->reqs[i], &name);
10692 tevent_req_set_callback(state->reqs[i],
10693 torture_createdels_done, req);
10699 static void torture_createdels_done(struct tevent_req *subreq)
10701 struct tevent_req *req = tevent_req_callback_data(
10702 subreq, struct tevent_req);
10703 struct torture_createdels_state *state = tevent_req_data(
10704 req, struct torture_createdels_state);
10705 size_t i, num_parallel = talloc_array_length(state->reqs);
10709 status = torture_createdel_recv(subreq);
10710 if (!NT_STATUS_IS_OK(status)){
10711 DEBUG(10, ("torture_createdel_recv returned %s\n",
10712 nt_errstr(status)));
10713 TALLOC_FREE(subreq);
10714 tevent_req_nterror(req, status);
10718 for (i=0; i<num_parallel; i++) {
10719 if (subreq == state->reqs[i]) {
10723 if (i == num_parallel) {
10724 DEBUG(10, ("received something we did not send\n"));
10725 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
10728 TALLOC_FREE(state->reqs[i]);
10730 if (state->sent >= state->num_files) {
10731 tevent_req_done(req);
10735 name = talloc_asprintf(state, "%s%8.8d", state->base_name,
10737 if (tevent_req_nomem(name, req)) {
10740 state->reqs[i] = torture_createdel_send(state->reqs, state->ev,
10742 if (tevent_req_nomem(state->reqs[i], req)) {
10745 name = talloc_move(state->reqs[i], &name);
10746 tevent_req_set_callback(state->reqs[i], torture_createdels_done, req);
10750 static NTSTATUS torture_createdels_recv(struct tevent_req *req)
10752 return tevent_req_simple_recv_ntstatus(req);
10755 struct swallow_notify_state {
10756 struct tevent_context *ev;
10757 struct cli_state *cli;
10759 uint32_t completion_filter;
10761 bool (*fn)(uint32_t action, const char *name, void *priv);
10765 static void swallow_notify_done(struct tevent_req *subreq);
10767 static struct tevent_req *swallow_notify_send(TALLOC_CTX *mem_ctx,
10768 struct tevent_context *ev,
10769 struct cli_state *cli,
10771 uint32_t completion_filter,
10773 bool (*fn)(uint32_t action,
10778 struct tevent_req *req, *subreq;
10779 struct swallow_notify_state *state;
10781 req = tevent_req_create(mem_ctx, &state,
10782 struct swallow_notify_state);
10788 state->fnum = fnum;
10789 state->completion_filter = completion_filter;
10790 state->recursive = recursive;
10792 state->priv = priv;
10794 subreq = cli_notify_send(state, state->ev, state->cli, state->fnum,
10795 0xffff, state->completion_filter,
10797 if (tevent_req_nomem(subreq, req)) {
10798 return tevent_req_post(req, ev);
10800 tevent_req_set_callback(subreq, swallow_notify_done, req);
10804 static void swallow_notify_done(struct tevent_req *subreq)
10806 struct tevent_req *req = tevent_req_callback_data(
10807 subreq, struct tevent_req);
10808 struct swallow_notify_state *state = tevent_req_data(
10809 req, struct swallow_notify_state);
10811 uint32_t i, num_changes;
10812 struct notify_change *changes;
10814 status = cli_notify_recv(subreq, state, &num_changes, &changes);
10815 TALLOC_FREE(subreq);
10816 if (!NT_STATUS_IS_OK(status)) {
10817 DEBUG(10, ("cli_notify_recv returned %s\n",
10818 nt_errstr(status)));
10819 tevent_req_nterror(req, status);
10823 for (i=0; i<num_changes; i++) {
10824 state->fn(changes[i].action, changes[i].name, state->priv);
10826 TALLOC_FREE(changes);
10828 subreq = cli_notify_send(state, state->ev, state->cli, state->fnum,
10829 0xffff, state->completion_filter,
10831 if (tevent_req_nomem(subreq, req)) {
10834 tevent_req_set_callback(subreq, swallow_notify_done, req);
10837 static bool print_notifies(uint32_t action, const char *name, void *priv)
10839 if (DEBUGLEVEL > 5) {
10840 d_printf("%d %s\n", (int)action, name);
10845 static void notify_bench_done(struct tevent_req *req)
10847 int *num_finished = (int *)tevent_req_callback_data_void(req);
10848 *num_finished += 1;
10851 static bool run_notify_bench(int dummy)
10853 const char *dname = "\\notify-bench";
10854 struct tevent_context *ev;
10857 struct tevent_req *req1;
10858 struct tevent_req *req2 = NULL;
10859 int i, num_unc_names;
10860 int num_finished = 0;
10862 printf("starting notify-bench test\n");
10864 if (use_multishare_conn) {
10866 unc_list = file_lines_load(multishare_conn_fname,
10867 &num_unc_names, 0, NULL);
10868 if (!unc_list || num_unc_names <= 0) {
10869 d_printf("Failed to load unc names list from '%s'\n",
10870 multishare_conn_fname);
10873 TALLOC_FREE(unc_list);
10878 ev = samba_tevent_context_init(talloc_tos());
10880 d_printf("tevent_context_init failed\n");
10884 for (i=0; i<num_unc_names; i++) {
10885 struct cli_state *cli;
10888 base_fname = talloc_asprintf(talloc_tos(), "%s\\file%3.3d.",
10890 if (base_fname == NULL) {
10894 if (!torture_open_connection(&cli, i)) {
10898 status = cli_ntcreate(cli, dname, 0,
10899 MAXIMUM_ALLOWED_ACCESS,
10900 0, FILE_SHARE_READ|FILE_SHARE_WRITE|
10902 FILE_OPEN_IF, FILE_DIRECTORY_FILE, 0,
10905 if (!NT_STATUS_IS_OK(status)) {
10906 d_printf("Could not create %s: %s\n", dname,
10907 nt_errstr(status));
10911 req1 = swallow_notify_send(talloc_tos(), ev, cli, dnum,
10912 FILE_NOTIFY_CHANGE_FILE_NAME |
10913 FILE_NOTIFY_CHANGE_DIR_NAME |
10914 FILE_NOTIFY_CHANGE_ATTRIBUTES |
10915 FILE_NOTIFY_CHANGE_LAST_WRITE,
10916 false, print_notifies, NULL);
10917 if (req1 == NULL) {
10918 d_printf("Could not create notify request\n");
10922 req2 = torture_createdels_send(talloc_tos(), ev, cli,
10923 base_fname, 10, torture_numops);
10924 if (req2 == NULL) {
10925 d_printf("Could not create createdels request\n");
10928 TALLOC_FREE(base_fname);
10930 tevent_req_set_callback(req2, notify_bench_done,
10934 while (num_finished < num_unc_names) {
10936 ret = tevent_loop_once(ev);
10938 d_printf("tevent_loop_once failed\n");
10943 if (!tevent_req_poll(req2, ev)) {
10944 d_printf("tevent_req_poll failed\n");
10947 status = torture_createdels_recv(req2);
10948 d_printf("torture_createdels_recv returned %s\n", nt_errstr(status));
10953 static bool run_mangle1(int dummy)
10955 struct cli_state *cli;
10956 const char *fname = "this_is_a_long_fname_to_be_mangled.txt";
10960 time_t change_time, access_time, write_time;
10964 printf("starting mangle1 test\n");
10965 if (!torture_open_connection(&cli, 0)) {
10969 smbXcli_conn_set_sockopt(cli->conn, sockops);
10971 status = cli_ntcreate(cli, fname, 0, GENERIC_ALL_ACCESS|DELETE_ACCESS,
10972 FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
10973 0, 0, &fnum, NULL);
10974 if (!NT_STATUS_IS_OK(status)) {
10975 d_printf("open %s failed: %s\n", fname, nt_errstr(status));
10978 cli_close(cli, fnum);
10980 status = cli_qpathinfo_alt_name(cli, fname, alt_name);
10981 if (!NT_STATUS_IS_OK(status)) {
10982 d_printf("cli_qpathinfo_alt_name failed: %s\n",
10983 nt_errstr(status));
10986 d_printf("alt_name: %s\n", alt_name);
10988 status = cli_openx(cli, alt_name, O_RDONLY, DENY_NONE, &fnum);
10989 if (!NT_STATUS_IS_OK(status)) {
10990 d_printf("cli_openx(%s) failed: %s\n", alt_name,
10991 nt_errstr(status));
10994 cli_close(cli, fnum);
10996 status = cli_qpathinfo1(cli, alt_name, &change_time, &access_time,
10997 &write_time, &size, &attr);
10998 if (!NT_STATUS_IS_OK(status)) {
10999 d_printf("cli_qpathinfo1(%s) failed: %s\n", alt_name,
11000 nt_errstr(status));
11007 static NTSTATUS mangle_illegal_list_shortname_fn(struct file_info *f,
11011 if (f->short_name == NULL) {
11012 return NT_STATUS_OK;
11015 if (strlen(f->short_name) == 0) {
11016 return NT_STATUS_OK;
11019 printf("unexpected shortname: %s\n", f->short_name);
11021 return NT_STATUS_OBJECT_NAME_INVALID;
11024 static NTSTATUS mangle_illegal_list_name_fn(struct file_info *f,
11028 char *name = state;
11030 printf("name: %s\n", f->name);
11031 fstrcpy(name, f->name);
11032 return NT_STATUS_OK;
11035 static bool run_mangle_illegal(int dummy)
11037 struct cli_state *cli = NULL;
11038 struct cli_state *cli_posix = NULL;
11039 const char *fname = "\\MANGLE_ILLEGAL\\this_is_a_long_fname_to_be_mangled.txt";
11040 const char *illegal_fname = "MANGLE_ILLEGAL/foo:bar";
11041 char *mangled_path = NULL;
11047 printf("starting mangle-illegal test\n");
11049 if (!torture_open_connection(&cli, 0)) {
11053 smbXcli_conn_set_sockopt(cli->conn, sockops);
11055 if (!torture_open_connection(&cli_posix, 0)) {
11059 smbXcli_conn_set_sockopt(cli_posix->conn, sockops);
11061 status = torture_setup_unix_extensions(cli_posix);
11062 if (!NT_STATUS_IS_OK(status)) {
11066 cli_rmdir(cli, "\\MANGLE_ILLEGAL");
11067 status = cli_mkdir(cli, "\\MANGLE_ILLEGAL");
11068 if (!NT_STATUS_IS_OK(status)) {
11069 printf("mkdir1 failed : %s\n", nt_errstr(status));
11074 * Create a file with illegal NTFS characters and test that we
11075 * get a usable mangled name
11078 cli_setatr(cli_posix, illegal_fname, 0, 0);
11079 cli_posix_unlink(cli_posix, illegal_fname);
11081 status = cli_posix_open(cli_posix, illegal_fname, O_RDWR|O_CREAT|O_EXCL,
11083 if (!NT_STATUS_IS_OK(status)) {
11084 printf("POSIX create of %s failed (%s)\n",
11085 illegal_fname, nt_errstr(status));
11089 status = cli_close(cli_posix, fnum);
11090 if (!NT_STATUS_IS_OK(status)) {
11091 printf("close failed (%s)\n", nt_errstr(status));
11095 status = cli_list(cli, "\\MANGLE_ILLEGAL\\*", 0, mangle_illegal_list_name_fn, &name);
11096 if (!NT_STATUS_IS_OK(status)) {
11097 d_printf("cli_list failed: %s\n", nt_errstr(status));
11101 mangled_path = talloc_asprintf(talloc_tos(), "\\MANGLE_ILLEGAL\\%s", name);
11102 if (mangled_path == NULL) {
11106 status = cli_openx(cli, mangled_path, O_RDONLY, DENY_NONE, &fnum);
11107 if (!NT_STATUS_IS_OK(status)) {
11108 d_printf("cli_openx(%s) failed: %s\n", mangled_path, nt_errstr(status));
11109 TALLOC_FREE(mangled_path);
11112 TALLOC_FREE(mangled_path);
11113 cli_close(cli, fnum);
11115 cli_setatr(cli_posix, illegal_fname, 0, 0);
11116 cli_posix_unlink(cli_posix, illegal_fname);
11119 * Create a file with a long name and check that we got *no* short name.
11122 status = cli_ntcreate(cli, fname, 0, GENERIC_ALL_ACCESS|DELETE_ACCESS,
11123 FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
11124 0, 0, &fnum, NULL);
11125 if (!NT_STATUS_IS_OK(status)) {
11126 d_printf("open %s failed: %s\n", fname, nt_errstr(status));
11129 cli_close(cli, fnum);
11131 status = cli_list(cli, fname, 0, mangle_illegal_list_shortname_fn, &alt_name);
11132 if (!NT_STATUS_IS_OK(status)) {
11133 d_printf("cli_list failed\n");
11137 cli_unlink(cli, fname, 0);
11138 cli_rmdir(cli, "\\MANGLE_ILLEGAL");
11140 if (!torture_close_connection(cli_posix)) {
11144 if (!torture_close_connection(cli)) {
11151 static size_t null_source(uint8_t *buf, size_t n, void *priv)
11153 size_t *to_pull = (size_t *)priv;
11154 size_t thistime = *to_pull;
11156 thistime = MIN(thistime, n);
11157 if (thistime == 0) {
11161 memset(buf, 0, thistime);
11162 *to_pull -= thistime;
11166 static bool run_windows_write(int dummy)
11168 struct cli_state *cli1;
11172 const char *fname = "\\writetest.txt";
11173 struct timeval start_time;
11178 printf("starting windows_write test\n");
11179 if (!torture_open_connection(&cli1, 0)) {
11183 status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
11184 if (!NT_STATUS_IS_OK(status)) {
11185 printf("open failed (%s)\n", nt_errstr(status));
11189 smbXcli_conn_set_sockopt(cli1->conn, sockops);
11191 start_time = timeval_current();
11193 for (i=0; i<torture_numops; i++) {
11195 off_t start = i * torture_blocksize;
11196 size_t to_pull = torture_blocksize - 1;
11198 status = cli_writeall(cli1, fnum, 0, &c,
11199 start + torture_blocksize - 1, 1, NULL);
11200 if (!NT_STATUS_IS_OK(status)) {
11201 printf("cli_write failed: %s\n", nt_errstr(status));
11205 status = cli_push(cli1, fnum, 0, i * torture_blocksize, torture_blocksize,
11206 null_source, &to_pull);
11207 if (!NT_STATUS_IS_OK(status)) {
11208 printf("cli_push returned: %s\n", nt_errstr(status));
11213 seconds = timeval_elapsed(&start_time);
11214 kbytes = (double)torture_blocksize * torture_numops;
11217 printf("Wrote %d kbytes in %.2f seconds: %d kb/sec\n", (int)kbytes,
11218 (double)seconds, (int)(kbytes/seconds));
11222 cli_close(cli1, fnum);
11223 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
11224 torture_close_connection(cli1);
11228 static size_t calc_expected_return(struct cli_state *cli, size_t len_requested)
11230 size_t max_pdu = 0x1FFFF;
11232 if (cli->server_posix_capabilities & CIFS_UNIX_LARGE_READ_CAP) {
11233 max_pdu = 0xFFFFFF;
11236 if (smb1cli_conn_signing_is_active(cli->conn)) {
11240 if (smb1cli_conn_encryption_on(cli->conn)) {
11241 max_pdu = CLI_BUFFER_SIZE;
11244 if ((len_requested & 0xFFFF0000) == 0xFFFF0000) {
11245 len_requested &= 0xFFFF;
11248 return MIN(len_requested,
11249 max_pdu - (MIN_SMB_SIZE + VWV(12) + 1 /* padding byte */));
11252 static bool check_read_call(struct cli_state *cli,
11255 size_t len_requested)
11258 struct tevent_req *subreq = NULL;
11259 ssize_t len_read = 0;
11260 size_t len_expected = 0;
11261 struct tevent_context *ev = NULL;
11263 ev = samba_tevent_context_init(talloc_tos());
11268 subreq = cli_read_andx_send(talloc_tos(),
11275 if (!tevent_req_poll_ntstatus(subreq, ev, &status)) {
11279 status = cli_read_andx_recv(subreq, &len_read, &buf);
11280 if (!NT_STATUS_IS_OK(status)) {
11281 d_printf("cli_read_andx_recv failed: %s\n", nt_errstr(status));
11285 TALLOC_FREE(subreq);
11288 len_expected = calc_expected_return(cli, len_requested);
11290 if (len_expected > 0x10000 && len_read == 0x10000) {
11291 /* Windows servers only return a max of 0x10000,
11292 doesn't matter if you set CAP_LARGE_READX in
11293 the client sessionsetupX call or not. */
11294 d_printf("Windows server - returned 0x10000 on a read of 0x%x\n",
11295 (unsigned int)len_requested);
11296 } else if (len_read != len_expected) {
11297 d_printf("read of 0x%x failed: got 0x%x, expected 0x%x\n",
11298 (unsigned int)len_requested,
11299 (unsigned int)len_read,
11300 (unsigned int)len_expected);
11303 d_printf("Correct read reply.\n");
11309 /* Test large readX variants. */
11310 static bool large_readx_tests(struct cli_state *cli,
11314 /* A read of 0xFFFF0001 should *always* return 1 byte. */
11315 if (check_read_call(cli, fnum, buf, 0xFFFF0001) == false) {
11318 /* A read of 0x10000 should return 0x10000 bytes. */
11319 if (check_read_call(cli, fnum, buf, 0x10000) == false) {
11322 /* A read of 0x10000 should return 0x10001 bytes. */
11323 if (check_read_call(cli, fnum, buf, 0x10001) == false) {
11326 /* A read of 0x1FFFF - (MIN_SMB_SIZE + VWV(12) should return
11327 the requested number of bytes. */
11328 if (check_read_call(cli, fnum, buf, 0x1FFFF - (MIN_SMB_SIZE + VWV(12))) == false) {
11331 /* A read of 1MB should return 1MB bytes (on Samba). */
11332 if (check_read_call(cli, fnum, buf, 0x100000) == false) {
11336 if (check_read_call(cli, fnum, buf, 0x20001) == false) {
11339 if (check_read_call(cli, fnum, buf, 0x22000001) == false) {
11342 if (check_read_call(cli, fnum, buf, 0xFFFE0001) == false) {
11348 static bool run_large_readx(int dummy)
11350 uint8_t *buf = NULL;
11351 struct cli_state *cli1 = NULL;
11352 struct cli_state *cli2 = NULL;
11353 bool correct = false;
11354 const char *fname = "\\large_readx.dat";
11356 uint16_t fnum1 = UINT16_MAX;
11357 uint32_t normal_caps = 0;
11358 size_t file_size = 20*1024*1024;
11359 TALLOC_CTX *frame = talloc_stackframe();
11363 enum smb_signing_setting signing_setting;
11364 enum protocol_types protocol;
11368 .signing_setting = SMB_SIGNING_IF_REQUIRED,
11369 .protocol = PROTOCOL_NT1,
11371 .name = "NT1 - SIGNING_REQUIRED",
11372 .signing_setting = SMB_SIGNING_REQUIRED,
11373 .protocol = PROTOCOL_NT1,
11377 printf("starting large_readx test\n");
11379 if (!torture_open_connection(&cli1, 0)) {
11383 normal_caps = smb1cli_conn_capabilities(cli1->conn);
11385 if (!(normal_caps & CAP_LARGE_READX)) {
11386 d_printf("Server doesn't have CAP_LARGE_READX 0x%x\n",
11387 (unsigned int)normal_caps);
11391 /* Create a file of size 4MB. */
11392 status = cli_ntcreate(cli1, fname, 0, GENERIC_ALL_ACCESS,
11393 FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
11394 0, 0, &fnum1, NULL);
11396 if (!NT_STATUS_IS_OK(status)) {
11397 d_printf("open %s failed: %s\n", fname, nt_errstr(status));
11401 /* Write file_size bytes. */
11402 buf = talloc_zero_array(frame, uint8_t, file_size);
11407 status = cli_writeall(cli1,
11414 if (!NT_STATUS_IS_OK(status)) {
11415 d_printf("cli_writeall failed: %s\n", nt_errstr(status));
11419 status = cli_close(cli1, fnum1);
11420 if (!NT_STATUS_IS_OK(status)) {
11421 d_printf("cli_close failed: %s\n", nt_errstr(status));
11425 fnum1 = UINT16_MAX;
11427 for (i=0; i < ARRAY_SIZE(runs); i++) {
11428 enum smb_signing_setting saved_signing_setting = signing_state;
11429 uint16_t fnum2 = -1;
11432 (runs[i].signing_setting == SMB_SIGNING_REQUIRED))
11434 d_printf("skip[%u] - %s\n", (unsigned)i, runs[i].name);
11438 d_printf("run[%u] - %s\n", (unsigned)i, runs[i].name);
11440 signing_state = runs[i].signing_setting;
11441 cli2 = open_nbt_connection();
11442 signing_state = saved_signing_setting;
11443 if (cli2 == NULL) {
11447 status = smbXcli_negprot(cli2->conn,
11451 if (!NT_STATUS_IS_OK(status)) {
11455 status = cli_session_setup_creds(cli2, torture_creds);
11456 if (!NT_STATUS_IS_OK(status)) {
11460 status = cli_tree_connect(cli2,
11464 if (!NT_STATUS_IS_OK(status)) {
11468 cli_set_timeout(cli2, 120000); /* set a really long timeout (2 minutes) */
11470 normal_caps = smb1cli_conn_capabilities(cli2->conn);
11472 if (!(normal_caps & CAP_LARGE_READX)) {
11473 d_printf("Server doesn't have CAP_LARGE_READX 0x%x\n",
11474 (unsigned int)normal_caps);
11479 if (force_cli_encryption(cli2, share) == false) {
11482 } else if (SERVER_HAS_UNIX_CIFS(cli2)) {
11483 uint16_t major, minor;
11484 uint32_t caplow, caphigh;
11486 status = cli_unix_extensions_version(cli2,
11488 &caplow, &caphigh);
11489 if (!NT_STATUS_IS_OK(status)) {
11494 status = cli_ntcreate(cli2, fname, 0, FILE_READ_DATA,
11495 FILE_ATTRIBUTE_NORMAL, 0, FILE_OPEN,
11496 0, 0, &fnum2, NULL);
11497 if (!NT_STATUS_IS_OK(status)) {
11498 d_printf("Second open %s failed: %s\n", fname, nt_errstr(status));
11502 /* All reads must return less than file_size bytes. */
11503 if (!large_readx_tests(cli2, fnum2, buf)) {
11507 status = cli_close(cli2, fnum2);
11508 if (!NT_STATUS_IS_OK(status)) {
11509 d_printf("cli_close failed: %s\n", nt_errstr(status));
11514 if (!torture_close_connection(cli2)) {
11521 printf("Success on large_readx test\n");
11526 if (!torture_close_connection(cli2)) {
11532 if (fnum1 != UINT16_MAX) {
11533 status = cli_close(cli1, fnum1);
11534 if (!NT_STATUS_IS_OK(status)) {
11535 d_printf("cli_close failed: %s\n", nt_errstr(status));
11537 fnum1 = UINT16_MAX;
11540 status = cli_unlink(cli1, fname,
11541 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
11542 if (!NT_STATUS_IS_OK(status)) {
11543 printf("unlink failed (%s)\n", nt_errstr(status));
11546 if (!torture_close_connection(cli1)) {
11551 TALLOC_FREE(frame);
11553 printf("finished large_readx test\n");
11557 static NTSTATUS msdfs_attribute_list_fn(struct file_info *finfo,
11559 void *private_data)
11561 uint32_t *p_attr = (uint32_t *)private_data;
11563 if (strequal(finfo->name, test_filename)) {
11564 *p_attr = finfo->attr;
11567 return NT_STATUS_OK;
11570 static bool run_msdfs_attribute(int dummy)
11572 static struct cli_state *cli;
11573 bool correct = false;
11577 printf("Starting MSDFS-ATTRIBUTE test\n");
11579 if (test_filename == NULL || test_filename[0] == '\0') {
11580 printf("MSDFS-ATTRIBUTE test "
11581 "needs -f filename-of-msdfs-link\n");
11586 * NB. We use torture_open_connection_flags() not
11587 * torture_open_connection() as the latter forces
11590 if (!torture_open_connection_flags(&cli, 0, 0)) {
11594 smbXcli_conn_set_sockopt(cli->conn, sockops);
11596 status = cli_list(cli,
11598 FILE_ATTRIBUTE_DIRECTORY,
11599 msdfs_attribute_list_fn,
11602 if (!NT_STATUS_IS_OK(status)) {
11603 printf("cli_list failed with %s\n",
11604 nt_errstr(status));
11607 if ((attr & FILE_ATTRIBUTE_REPARSE_POINT) == 0) {
11608 printf("file %s should have "
11609 "FILE_ATTRIBUTE_REPARSE_POINT set. attr = 0x%x\n",
11611 (unsigned int)attr);
11615 if ((attr & FILE_ATTRIBUTE_DIRECTORY) == 0) {
11616 printf("file %s should have "
11617 "FILE_ATTRIBUTE_DIRECTORY set. attr = 0x%x\n",
11619 (unsigned int)attr);
11627 torture_close_connection(cli);
11631 static bool run_cli_echo(int dummy)
11633 struct cli_state *cli;
11636 printf("starting cli_echo test\n");
11637 if (!torture_open_connection(&cli, 0)) {
11640 smbXcli_conn_set_sockopt(cli->conn, sockops);
11642 status = cli_echo(cli, 5, data_blob_const("hello", 5));
11644 d_printf("cli_echo returned %s\n", nt_errstr(status));
11646 torture_close_connection(cli);
11647 return NT_STATUS_IS_OK(status);
11650 static int splice_status(off_t written, void *priv)
11655 static bool run_cli_splice(int dummy)
11657 uint8_t *buf = NULL;
11658 struct cli_state *cli1 = NULL;
11659 bool correct = false;
11660 const char *fname_src = "\\splice_src.dat";
11661 const char *fname_dst = "\\splice_dst.dat";
11663 uint16_t fnum1 = UINT16_MAX;
11664 uint16_t fnum2 = UINT16_MAX;
11665 size_t file_size = 2*1024*1024;
11666 size_t splice_size = 1*1024*1024 + 713;
11667 uint8_t digest1[16], digest2[16];
11670 TALLOC_CTX *frame = talloc_stackframe();
11672 printf("starting cli_splice test\n");
11674 if (!torture_open_connection(&cli1, 0)) {
11678 cli_unlink(cli1, fname_src,
11679 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
11680 cli_unlink(cli1, fname_dst,
11681 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
11683 /* Create a file */
11684 status = cli_ntcreate(cli1, fname_src, 0, GENERIC_ALL_ACCESS,
11685 FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
11686 0, 0, &fnum1, NULL);
11688 if (!NT_STATUS_IS_OK(status)) {
11689 d_printf("open %s failed: %s\n", fname_src, nt_errstr(status));
11693 /* Write file_size bytes - must be bigger than splice_size. */
11694 buf = talloc_zero_array(frame, uint8_t, file_size);
11696 d_printf("talloc_fail\n");
11700 /* Fill it with random numbers. */
11701 generate_random_buffer(buf, file_size);
11703 /* MD5 the first 1MB + 713 bytes. */
11704 gnutls_hash_fast(GNUTLS_DIG_MD5,
11709 status = cli_writeall(cli1,
11716 if (!NT_STATUS_IS_OK(status)) {
11717 d_printf("cli_writeall failed: %s\n", nt_errstr(status));
11721 status = cli_ntcreate(cli1, fname_dst, 0, GENERIC_ALL_ACCESS,
11722 FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
11723 0, 0, &fnum2, NULL);
11725 if (!NT_STATUS_IS_OK(status)) {
11726 d_printf("open %s failed: %s\n", fname_dst, nt_errstr(status));
11730 /* Now splice 1MB + 713 bytes. */
11731 status = cli_splice(cli1,
11742 if (!NT_STATUS_IS_OK(status)) {
11743 d_printf("cli_splice failed: %s\n", nt_errstr(status));
11747 /* Clear the old buffer. */
11748 memset(buf, '\0', file_size);
11750 /* Read the new file. */
11751 status = cli_read(cli1, fnum2, (char *)buf, 0, splice_size, &nread);
11752 if (!NT_STATUS_IS_OK(status)) {
11753 d_printf("cli_read failed: %s\n", nt_errstr(status));
11756 if (nread != splice_size) {
11757 d_printf("bad read of 0x%x, should be 0x%x\n",
11758 (unsigned int)nread,
11759 (unsigned int)splice_size);
11763 /* MD5 the first 1MB + 713 bytes. */
11764 gnutls_hash_fast(GNUTLS_DIG_MD5,
11769 /* Must be the same. */
11770 if (memcmp(digest1, digest2, 16) != 0) {
11771 d_printf("bad MD5 compare\n");
11776 printf("Success on cli_splice test\n");
11781 if (fnum1 != UINT16_MAX) {
11782 cli_close(cli1, fnum1);
11784 if (fnum2 != UINT16_MAX) {
11785 cli_close(cli1, fnum2);
11788 cli_unlink(cli1, fname_src,
11789 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
11790 cli_unlink(cli1, fname_dst,
11791 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
11793 if (!torture_close_connection(cli1)) {
11798 TALLOC_FREE(frame);
11802 static bool run_uid_regression_test(int dummy)
11804 static struct cli_state *cli;
11807 bool correct = True;
11808 struct smbXcli_tcon *tcon_copy = NULL;
11811 printf("starting uid regression test\n");
11813 if (!torture_open_connection(&cli, 0)) {
11817 smbXcli_conn_set_sockopt(cli->conn, sockops);
11819 /* Ok - now save then logoff our current user. */
11820 old_vuid = cli_state_get_uid(cli);
11822 status = cli_ulogoff(cli);
11823 if (!NT_STATUS_IS_OK(status)) {
11824 d_printf("(%s) cli_ulogoff failed: %s\n",
11825 __location__, nt_errstr(status));
11830 cli_state_set_uid(cli, old_vuid);
11832 /* Try an operation. */
11833 status = cli_mkdir(cli, "\\uid_reg_test");
11834 if (NT_STATUS_IS_OK(status)) {
11835 d_printf("(%s) cli_mkdir succeeded\n",
11840 /* Should be bad uid. */
11841 if (!check_error(__LINE__, status, ERRSRV, ERRbaduid,
11842 NT_STATUS_USER_SESSION_DELETED)) {
11848 old_cnum = cli_state_get_tid(cli);
11850 * This is an SMB1-only test.
11851 * Copy the tcon, not "save/restore".
11853 * In SMB1 the cli_tdis() below frees
11854 * cli->smb1.tcon so we need a copy
11855 * of the struct to put back for the
11856 * second tdis call with invalid vuid.
11858 * This is a test-only hack. Real client code
11859 * uses cli_state_save_tcon()/cli_state_restore_tcon().
11861 tcon_copy = smbXcli_tcon_copy(cli, cli->smb1.tcon);
11862 if (tcon_copy == NULL) {
11867 /* Now try a SMBtdis with the invalid vuid set to zero. */
11868 cli_state_set_uid(cli, 0);
11870 /* This should succeed. */
11871 status = cli_tdis(cli);
11873 if (NT_STATUS_IS_OK(status)) {
11874 d_printf("First tdis with invalid vuid should succeed.\n");
11876 d_printf("First tdis failed (%s)\n", nt_errstr(status));
11878 cli->smb1.tcon = tcon_copy;
11882 cli->smb1.tcon = tcon_copy;
11883 cli_state_set_uid(cli, old_vuid);
11884 cli_state_set_tid(cli, old_cnum);
11886 /* This should fail. */
11887 status = cli_tdis(cli);
11888 if (NT_STATUS_IS_OK(status)) {
11889 d_printf("Second tdis with invalid vuid should fail - succeeded instead !.\n");
11893 /* Should be bad tid. */
11894 if (!check_error(__LINE__, status, ERRSRV, ERRinvnid,
11895 NT_STATUS_NETWORK_NAME_DELETED)) {
11901 cli_rmdir(cli, "\\uid_reg_test");
11910 static const char *illegal_chars = "*\\/?<>|\":";
11911 static char force_shortname_chars[] = " +,.[];=\177";
11913 static NTSTATUS shortname_del_fn(struct file_info *finfo,
11914 const char *mask, void *state)
11916 struct cli_state *pcli = (struct cli_state *)state;
11918 NTSTATUS status = NT_STATUS_OK;
11920 slprintf(fname, sizeof(fname), "\\shortname\\%s", finfo->name);
11922 if (strcmp(finfo->name, ".") == 0 || strcmp(finfo->name, "..") == 0)
11923 return NT_STATUS_OK;
11925 if (finfo->attr & FILE_ATTRIBUTE_DIRECTORY) {
11926 status = cli_rmdir(pcli, fname);
11927 if (!NT_STATUS_IS_OK(status)) {
11928 printf("del_fn: failed to rmdir %s\n,", fname );
11931 status = cli_unlink(pcli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
11932 if (!NT_STATUS_IS_OK(status)) {
11933 printf("del_fn: failed to unlink %s\n,", fname );
11945 static NTSTATUS shortname_list_fn(struct file_info *finfo,
11946 const char *name, void *state)
11948 struct sn_state *s = (struct sn_state *)state;
11952 printf("shortname list: i = %d, name = |%s|, shortname = |%s|\n",
11953 i, finfo->name, finfo->short_name);
11956 if (strchr(force_shortname_chars, i)) {
11957 if (!finfo->short_name) {
11958 /* Shortname not created when it should be. */
11959 d_printf("(%s) ERROR: Shortname was not created for file %s containing %d\n",
11960 __location__, finfo->name, i);
11963 } else if (finfo->short_name){
11964 /* Shortname created when it should not be. */
11965 d_printf("(%s) ERROR: Shortname %s was created for file %s\n",
11966 __location__, finfo->short_name, finfo->name);
11970 return NT_STATUS_OK;
11973 static bool run_shortname_test(int dummy)
11975 static struct cli_state *cli;
11976 bool correct = True;
11982 printf("starting shortname test\n");
11984 if (!torture_open_connection(&cli, 0)) {
11988 smbXcli_conn_set_sockopt(cli->conn, sockops);
11990 cli_list(cli, "\\shortname\\*", 0, shortname_del_fn, cli);
11991 cli_list(cli, "\\shortname\\*", FILE_ATTRIBUTE_DIRECTORY, shortname_del_fn, cli);
11992 cli_rmdir(cli, "\\shortname");
11994 status = cli_mkdir(cli, "\\shortname");
11995 if (!NT_STATUS_IS_OK(status)) {
11996 d_printf("(%s) cli_mkdir of \\shortname failed: %s\n",
11997 __location__, nt_errstr(status));
12002 if (strlcpy(fname, "\\shortname\\", sizeof(fname)) >= sizeof(fname)) {
12006 if (strlcat(fname, "test .txt", sizeof(fname)) >= sizeof(fname)) {
12013 for (i = 32; i < 128; i++) {
12014 uint16_t fnum = (uint16_t)-1;
12018 if (strchr(illegal_chars, i)) {
12023 status = cli_ntcreate(cli, fname, 0, GENERIC_ALL_ACCESS, FILE_ATTRIBUTE_NORMAL,
12024 FILE_SHARE_READ|FILE_SHARE_WRITE,
12025 FILE_OVERWRITE_IF, 0, 0, &fnum, NULL);
12026 if (!NT_STATUS_IS_OK(status)) {
12027 d_printf("(%s) cli_nt_create of %s failed: %s\n",
12028 __location__, fname, nt_errstr(status));
12032 cli_close(cli, fnum);
12035 status = cli_list(cli, "\\shortname\\test*.*", 0,
12036 shortname_list_fn, &s);
12037 if (s.matched != 1) {
12038 d_printf("(%s) failed to list %s: %s\n",
12039 __location__, fname, nt_errstr(status));
12044 status = cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
12045 if (!NT_STATUS_IS_OK(status)) {
12046 d_printf("(%s) failed to delete %s: %s\n",
12047 __location__, fname, nt_errstr(status));
12060 cli_list(cli, "\\shortname\\*", 0, shortname_del_fn, cli);
12061 cli_list(cli, "\\shortname\\*", FILE_ATTRIBUTE_DIRECTORY, shortname_del_fn, cli);
12062 cli_rmdir(cli, "\\shortname");
12063 torture_close_connection(cli);
12067 TLDAPRC callback_code;
12069 static void pagedsearch_cb(struct tevent_req *req)
12072 struct tldap_message *msg;
12075 rc = tldap_search_paged_recv(req, talloc_tos(), &msg);
12076 if (!TLDAP_RC_IS_SUCCESS(rc)) {
12077 d_printf("tldap_search_paged_recv failed: %s\n",
12078 tldap_rc2string(rc));
12079 callback_code = rc;
12082 if (tldap_msg_type(msg) != TLDAP_RES_SEARCH_ENTRY) {
12086 if (!tldap_entry_dn(msg, &dn)) {
12087 d_printf("tldap_entry_dn failed\n");
12090 d_printf("%s\n", dn);
12094 enum tldap_extended_val {
12101 * Construct an extended dn control with either no value, 0 or 1
12103 * No value and 0 are equivalent (non-hyphenated GUID)
12104 * 1 has the hyphenated GUID
12106 static struct tldap_control *
12107 tldap_build_extended_control(enum tldap_extended_val val)
12109 struct tldap_control empty_control;
12110 struct asn1_data *data;
12112 ZERO_STRUCT(empty_control);
12114 if (val != EXTENDED_NONE) {
12115 data = asn1_init(talloc_tos(), ASN1_MAX_TREE_DEPTH);
12121 if (!asn1_push_tag(data, ASN1_SEQUENCE(0))) {
12125 if (!asn1_write_Integer(data, (int)val)) {
12129 if (!asn1_pop_tag(data)) {
12133 if (!asn1_blob(data, &empty_control.value)) {
12138 empty_control.oid = "1.2.840.113556.1.4.529";
12139 empty_control.critical = true;
12141 return tldap_add_control(talloc_tos(), NULL, 0, &empty_control);
12145 static bool tldap_test_dn_guid_format(struct tldap_context *ld, const char *basedn,
12146 enum tldap_extended_val control_val)
12148 struct tldap_control *control = tldap_build_extended_control(control_val);
12150 struct tldap_message **msg;
12153 rc = tldap_search(ld, basedn, TLDAP_SCOPE_BASE,
12154 "(objectClass=*)", NULL, 0, 0,
12156 0, 0, 0, 0, talloc_tos(), &msg);
12157 if (!TLDAP_RC_IS_SUCCESS(rc)) {
12158 d_printf("tldap_search for domain DN failed: %s\n",
12159 tldap_errstr(talloc_tos(), ld, rc));
12163 if (!tldap_entry_dn(msg[0], &dn)) {
12164 d_printf("tldap_search domain DN fetch failed: %s\n",
12165 tldap_errstr(talloc_tos(), ld, rc));
12169 d_printf("%s\n", dn);
12172 uint32_t time_mid, time_hi_and_version;
12173 uint32_t clock_seq[2];
12177 switch (control_val) {
12178 case EXTENDED_NONE:
12179 case EXTENDED_ZERO:
12181 * When reading GUIDs with hyphens, scanf will treat
12182 * hyphen as a hex character (and counts as part of the
12183 * width). This creates leftover GUID string which we
12184 * check will for with 'next' and closing '>'.
12186 if (12 == sscanf(dn, "<GUID=%08x%04x%04x%02x%02x%02x%02x%02x%02x%02x%02x>%c",
12187 &time_low, &time_mid,
12188 &time_hi_and_version, &clock_seq[0],
12189 &clock_seq[1], &node[0], &node[1],
12190 &node[2], &node[3], &node[4],
12191 &node[5], &next)) {
12192 /* This GUID is good */
12194 d_printf("GUID format in control (no hyphens) doesn't match output\n");
12200 if (12 == sscanf(dn,
12201 "<GUID=%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x>%c",
12202 &time_low, &time_mid,
12203 &time_hi_and_version, &clock_seq[0],
12204 &clock_seq[1], &node[0], &node[1],
12205 &node[2], &node[3], &node[4],
12206 &node[5], &next)) {
12207 /* This GUID is good */
12209 d_printf("GUID format in control (with hyphens) doesn't match output\n");
12222 static bool run_tldap(int dummy)
12224 struct tldap_context *ld;
12228 struct sockaddr_storage addr;
12229 struct tevent_context *ev;
12230 struct tevent_req *req;
12232 const char *filter;
12234 if (!resolve_name(host, &addr, 0, false)) {
12235 d_printf("could not find host %s\n", host);
12238 status = open_socket_out(&addr, 389, 9999, &fd);
12239 if (!NT_STATUS_IS_OK(status)) {
12240 d_printf("open_socket_out failed: %s\n", nt_errstr(status));
12244 ld = tldap_context_create(talloc_tos(), fd);
12247 d_printf("tldap_context_create failed\n");
12251 rc = tldap_fetch_rootdse(ld);
12252 if (!TLDAP_RC_IS_SUCCESS(rc)) {
12253 d_printf("tldap_fetch_rootdse failed: %s\n",
12254 tldap_errstr(talloc_tos(), ld, rc));
12258 basedn = tldap_talloc_single_attribute(
12259 tldap_rootdse(ld), "defaultNamingContext", talloc_tos());
12260 if (basedn == NULL) {
12261 d_printf("no defaultNamingContext\n");
12264 d_printf("defaultNamingContext: %s\n", basedn);
12266 ev = samba_tevent_context_init(talloc_tos());
12268 d_printf("tevent_context_init failed\n");
12272 rc = tldap_gensec_bind(ld, torture_creds, "ldap", host, NULL,
12273 loadparm_init_s3(talloc_tos(),
12274 loadparm_s3_helpers()),
12275 GENSEC_FEATURE_SIGN | GENSEC_FEATURE_SEAL);
12277 if (!TLDAP_RC_IS_SUCCESS(rc)) {
12278 d_printf("tldap_gensec_bind failed\n");
12282 callback_code = TLDAP_SUCCESS;
12284 req = tldap_search_paged_send(talloc_tos(), ev, ld, basedn,
12285 TLDAP_SCOPE_SUB, "(objectclass=*)",
12287 NULL, 0, NULL, 0, 0, 0, 0, 5);
12289 d_printf("tldap_search_paged_send failed\n");
12292 tevent_req_set_callback(req, pagedsearch_cb, NULL);
12294 tevent_req_poll(req, ev);
12298 rc = callback_code;
12300 if (!TLDAP_RC_IS_SUCCESS(rc)) {
12301 d_printf("tldap_search with paging failed: %s\n",
12302 tldap_errstr(talloc_tos(), ld, rc));
12306 /* test search filters against rootDSE */
12307 filter = "(&(|(name=samba)(nextRid<=10000000)(usnChanged>=10)(samba~=ambas)(!(name=s*m*a)))"
12308 "(|(name:=samba)(name:dn:2.5.13.5:=samba)(:dn:2.5.13.5:=samba)(!(name=*samba))))";
12310 rc = tldap_search(ld, "", TLDAP_SCOPE_BASE, filter,
12311 NULL, 0, 0, NULL, 0, NULL, 0, 0, 0, 0,
12312 talloc_tos(), NULL);
12313 if (!TLDAP_RC_IS_SUCCESS(rc)) {
12314 d_printf("tldap_search with complex filter failed: %s\n",
12315 tldap_errstr(talloc_tos(), ld, rc));
12320 * Tests to check for regression of:
12322 * https://bugzilla.samba.org/show_bug.cgi?id=14029
12324 * TLDAP used here to pick apart the original string DN (with GUID)
12326 if (!tldap_test_dn_guid_format(ld, basedn, EXTENDED_NONE)) {
12327 d_printf("tldap_search with extended dn (no val) failed: %s\n",
12328 tldap_errstr(talloc_tos(), ld, rc));
12331 if (!tldap_test_dn_guid_format(ld, basedn, EXTENDED_ZERO)) {
12332 d_printf("tldap_search with extended dn (0) failed: %s\n",
12333 tldap_errstr(talloc_tos(), ld, rc));
12336 if (!tldap_test_dn_guid_format(ld, basedn, EXTENDED_ONE)) {
12337 d_printf("tldap_search with extended dn (1) failed: %s\n",
12338 tldap_errstr(talloc_tos(), ld, rc));
12346 /* Torture test to ensure no regression of :
12347 https://bugzilla.samba.org/show_bug.cgi?id=7084
12350 static bool run_dir_createtime(int dummy)
12352 struct cli_state *cli;
12353 const char *dname = "\\testdir_createtime";
12354 const char *fname = "\\testdir_createtime\\testfile";
12356 struct timespec create_time;
12357 struct timespec create_time1;
12362 if (!torture_open_connection(&cli, 0)) {
12366 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
12367 /* Ensure ino is zero, SMB2 gets a real one. */
12370 /* Ensure ino is -1, SMB1 never gets a real one. */
12371 ino = (uint64_t)-1;
12374 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
12375 cli_rmdir(cli, dname);
12377 status = cli_mkdir(cli, dname);
12378 if (!NT_STATUS_IS_OK(status)) {
12379 printf("mkdir failed: %s\n", nt_errstr(status));
12383 status = cli_qpathinfo2(cli, dname, &create_time, NULL, NULL, NULL,
12385 if (!NT_STATUS_IS_OK(status)) {
12386 printf("cli_qpathinfo2 returned %s\n",
12387 nt_errstr(status));
12391 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
12392 /* SMB2 should always return an inode. */
12394 printf("SMB2 bad inode (0)\n");
12398 /* SMB1 must always return zero here. */
12400 printf("SMB1 bad inode (!0)\n");
12405 /* Sleep 3 seconds, then create a file. */
12408 status = cli_openx(cli, fname, O_RDWR | O_CREAT | O_EXCL,
12410 if (!NT_STATUS_IS_OK(status)) {
12411 printf("cli_openx failed: %s\n", nt_errstr(status));
12415 status = cli_qpathinfo2(cli, dname, &create_time1, NULL, NULL, NULL,
12417 if (!NT_STATUS_IS_OK(status)) {
12418 printf("cli_qpathinfo2 (2) returned %s\n",
12419 nt_errstr(status));
12423 if (timespec_compare(&create_time1, &create_time)) {
12424 printf("run_dir_createtime: create time was updated (error)\n");
12426 printf("run_dir_createtime: create time was not updated (correct)\n");
12432 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
12433 cli_rmdir(cli, dname);
12434 if (!torture_close_connection(cli)) {
12441 static bool run_streamerror(int dummy)
12443 struct cli_state *cli;
12444 const char *dname = "\\testdir_streamerror";
12445 const char *streamname =
12446 "testdir_streamerror:{4c8cc155-6c1e-11d1-8e41-00c04fb9386d}:$DATA";
12448 time_t change_time, access_time, write_time;
12454 if (!torture_open_connection(&cli, 0)) {
12458 torture_deltree(cli, dname);
12460 status = cli_mkdir(cli, dname);
12461 if (!NT_STATUS_IS_OK(status)) {
12462 printf("mkdir failed: %s\n", nt_errstr(status));
12466 status = cli_qpathinfo1(cli, streamname, &change_time, &access_time,
12467 &write_time, &size, &attr);
12468 if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
12469 printf("pathinfo returned %s, expected "
12470 "NT_STATUS_OBJECT_NAME_NOT_FOUND\n",
12471 nt_errstr(status));
12475 status = cli_ntcreate(cli, streamname, 0x16,
12476 FILE_READ_DATA|FILE_READ_EA|
12477 FILE_READ_ATTRIBUTES|READ_CONTROL_ACCESS,
12478 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ,
12479 FILE_OPEN, 0, 0, &fnum, NULL);
12481 if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
12482 printf("ntcreate returned %s, expected "
12483 "NT_STATUS_OBJECT_NAME_NOT_FOUND\n",
12484 nt_errstr(status));
12489 cli_rmdir(cli, dname);
12493 struct pidtest_state {
12499 static void pid_echo_done(struct tevent_req *subreq);
12501 static struct tevent_req *pid_echo_send(TALLOC_CTX *mem_ctx,
12502 struct tevent_context *ev,
12503 struct cli_state *cli)
12505 struct tevent_req *req, *subreq;
12506 struct pidtest_state *state;
12508 req = tevent_req_create(mem_ctx, &state, struct pidtest_state);
12513 SSVAL(state->vwv, 0, 1);
12514 state->data = data_blob_const("hello", 5);
12516 subreq = smb1cli_req_send(state,
12520 0, 0, /* *_flags */
12521 0, 0, /* *_flags2 */
12523 0xDEADBEEF, /* pid */
12525 NULL, /* session */
12526 ARRAY_SIZE(state->vwv), state->vwv,
12527 state->data.length, state->data.data);
12529 if (tevent_req_nomem(subreq, req)) {
12530 return tevent_req_post(req, ev);
12532 tevent_req_set_callback(subreq, pid_echo_done, req);
12536 static void pid_echo_done(struct tevent_req *subreq)
12538 struct tevent_req *req = tevent_req_callback_data(
12539 subreq, struct tevent_req);
12540 struct pidtest_state *state = tevent_req_data(
12541 req, struct pidtest_state);
12543 uint32_t num_bytes;
12544 uint8_t *bytes = NULL;
12545 struct iovec *recv_iov = NULL;
12546 uint8_t *phdr = NULL;
12547 uint16_t pidlow = 0;
12548 uint16_t pidhigh = 0;
12549 struct smb1cli_req_expected_response expected[] = {
12551 .status = NT_STATUS_OK,
12556 status = smb1cli_req_recv(subreq, state,
12561 NULL, /* pvwv_offset */
12564 NULL, /* pbytes_offset */
12566 expected, ARRAY_SIZE(expected));
12568 TALLOC_FREE(subreq);
12570 if (!NT_STATUS_IS_OK(status)) {
12571 tevent_req_nterror(req, status);
12575 if (num_bytes != state->data.length) {
12576 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
12580 if (memcmp(bytes, state->data.data, num_bytes) != 0) {
12581 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
12585 /* Check pid low/high == DEADBEEF */
12586 pidlow = SVAL(phdr, HDR_PID);
12587 if (pidlow != 0xBEEF){
12588 printf("Incorrect pidlow 0x%x, should be 0xBEEF\n",
12589 (unsigned int)pidlow);
12590 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
12593 pidhigh = SVAL(phdr, HDR_PIDHIGH);
12594 if (pidhigh != 0xDEAD){
12595 printf("Incorrect pidhigh 0x%x, should be 0xDEAD\n",
12596 (unsigned int)pidhigh);
12597 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
12601 tevent_req_done(req);
12604 static NTSTATUS pid_echo_recv(struct tevent_req *req)
12606 return tevent_req_simple_recv_ntstatus(req);
12609 static bool run_pidhigh(int dummy)
12611 bool success = false;
12612 struct cli_state *cli = NULL;
12614 struct tevent_context *ev = NULL;
12615 struct tevent_req *req = NULL;
12616 TALLOC_CTX *frame = talloc_stackframe();
12618 printf("starting pid high test\n");
12619 if (!torture_open_connection(&cli, 0)) {
12622 smbXcli_conn_set_sockopt(cli->conn, sockops);
12624 ev = samba_tevent_context_init(frame);
12629 req = pid_echo_send(frame, ev, cli);
12634 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
12638 status = pid_echo_recv(req);
12639 if (NT_STATUS_IS_OK(status)) {
12640 printf("pid high test ok\n");
12646 TALLOC_FREE(frame);
12647 torture_close_connection(cli);
12652 Test Windows open on a bad POSIX symlink.
12654 static bool run_symlink_open_test(int dummy)
12656 static struct cli_state *cli;
12657 const char *fname = "non_existant_file";
12658 const char *sname = "dangling_symlink";
12659 uint16_t fnum = (uint16_t)-1;
12660 bool correct = false;
12662 TALLOC_CTX *frame = NULL;
12664 frame = talloc_stackframe();
12666 printf("Starting Windows bad symlink open test\n");
12668 if (!torture_open_connection(&cli, 0)) {
12669 TALLOC_FREE(frame);
12673 smbXcli_conn_set_sockopt(cli->conn, sockops);
12675 status = torture_setup_unix_extensions(cli);
12676 if (!NT_STATUS_IS_OK(status)) {
12677 TALLOC_FREE(frame);
12681 /* Ensure nothing exists. */
12682 cli_setatr(cli, fname, 0, 0);
12683 cli_posix_unlink(cli, fname);
12684 cli_setatr(cli, sname, 0, 0);
12685 cli_posix_unlink(cli, sname);
12687 /* Create a symlink pointing nowhere. */
12688 status = cli_posix_symlink(cli, fname, sname);
12689 if (!NT_STATUS_IS_OK(status)) {
12690 printf("cli_posix_symlink of %s -> %s failed (%s)\n",
12693 nt_errstr(status));
12697 /* Now ensure that a Windows open doesn't hang. */
12698 status = cli_ntcreate(cli,
12701 FILE_READ_DATA|FILE_WRITE_DATA,
12703 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
12711 * We get either NT_STATUS_OBJECT_NAME_NOT_FOUND or
12712 * NT_STATUS_OBJECT_PATH_NOT_FOUND depending on if
12713 * we use O_NOFOLLOW on the server or not.
12715 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND) ||
12716 NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_PATH_NOT_FOUND))
12720 printf("cli_ntcreate of %s returned %s - should return"
12721 " either (%s) or (%s)\n",
12724 nt_errstr(NT_STATUS_OBJECT_NAME_NOT_FOUND),
12725 nt_errstr(NT_STATUS_OBJECT_PATH_NOT_FOUND));
12733 if (fnum != (uint16_t)-1) {
12734 cli_close(cli, fnum);
12735 fnum = (uint16_t)-1;
12738 cli_setatr(cli, sname, 0, 0);
12739 cli_posix_unlink(cli, sname);
12740 cli_setatr(cli, fname, 0, 0);
12741 cli_posix_unlink(cli, fname);
12743 if (!torture_close_connection(cli)) {
12747 TALLOC_FREE(frame);
12751 static NTSTATUS smb1_wild_mangle_list_fn(struct file_info *finfo,
12755 char **mangled_name_return = (char **)state;
12756 bool is_mangled = strchr(finfo->name, '~');
12759 *mangled_name_return = talloc_strdup(NULL, finfo->name);
12760 if (*mangled_name_return == NULL) {
12761 return NT_STATUS_NO_MEMORY;
12764 return NT_STATUS_OK;
12767 static bool run_smb1_wild_mangle_unlink_test(int dummy)
12769 static struct cli_state *cli_posix = NULL;
12770 static struct cli_state *cli = NULL;
12771 uint16_t fnum = (uint16_t)-1;
12772 bool correct = false;
12773 const char *dname = "smb1_wild_mangle_unlink";
12774 const char *aname = "smb1_wild_mangle_unlink/a";
12775 const char *star_name = "smb1_wild_mangle_unlink/*";
12776 char *windows_unlink_name = NULL;
12777 char *mangled_name = NULL;
12780 printf("Starting SMB1 wild mangle unlink test\n");
12782 /* Open a Windows connection. */
12783 if (!torture_open_connection(&cli, 0)) {
12787 smbXcli_conn_set_sockopt(cli->conn, sockops);
12789 /* Open a POSIX connection. */
12790 if (!torture_open_connection(&cli_posix, 0)) {
12794 smbXcli_conn_set_sockopt(cli_posix->conn, sockops);
12796 status = torture_setup_unix_extensions(cli_posix);
12797 if (!NT_STATUS_IS_OK(status)) {
12798 printf("server doesn't support POSIX\n");
12803 torture_deltree(cli, dname);
12806 * Create two files - 'a' and '*'.
12807 * We need POSIX extensions for this as '*'
12808 * is not a valid Windows name.
12811 status = cli_mkdir(cli, dname);
12812 if (!NT_STATUS_IS_OK(status)) {
12813 printf("cli_mkdir of %s returned %s\n",
12815 nt_errstr(status));
12819 status = cli_posix_open(cli_posix,
12821 O_RDWR|O_CREAT|O_EXCL,
12824 if (!NT_STATUS_IS_OK(status)) {
12825 printf("cli_posix_open (create) of %s returned %s\n",
12827 nt_errstr(status));
12830 status = cli_close(cli_posix, fnum);
12831 if (!NT_STATUS_IS_OK(status)) {
12834 status = cli_posix_open(cli_posix,
12836 O_RDWR|O_CREAT|O_EXCL,
12839 if (!NT_STATUS_IS_OK(status)) {
12840 printf("cli_posix_open (create) of %s returned %s\n",
12842 nt_errstr(status));
12845 status = cli_close(cli_posix, fnum);
12846 if (!NT_STATUS_IS_OK(status)) {
12850 status = cli_list(cli,
12853 smb1_wild_mangle_list_fn,
12855 if (!NT_STATUS_IS_OK(status)) {
12856 printf("cli_list of %s returned %s\n",
12858 nt_errstr(status));
12862 if (mangled_name == NULL) {
12866 printf("mangled_name = %s\n",
12870 * Try a Windows unlink with the mangled name.
12871 * This should *NOT* unlink the 'a' name.
12874 windows_unlink_name = talloc_asprintf(cli_posix,
12879 status = cli_unlink(cli, windows_unlink_name, 0);
12880 if (!NT_STATUS_IS_OK(status)) {
12881 printf("cli_unlink of %s returned %s\n",
12882 windows_unlink_name,
12883 nt_errstr(status));
12887 /* Does 'a' still exist ? */
12888 status = cli_posix_open(cli_posix,
12893 if (!NT_STATUS_IS_OK(status)) {
12894 printf("cli_posix_open O_RNONLY of %s returned %s\n",
12896 nt_errstr(status));
12900 status = cli_close(cli_posix, fnum);
12901 if (!NT_STATUS_IS_OK(status)) {
12909 TALLOC_FREE(windows_unlink_name);
12910 TALLOC_FREE(mangled_name);
12913 torture_deltree(cli, dname);
12914 torture_close_connection(cli);
12917 if (cli_posix != NULL) {
12918 torture_close_connection(cli_posix);
12924 static bool run_smb1_wild_mangle_rename_test(int dummy)
12926 static struct cli_state *cli_posix = NULL;
12927 static struct cli_state *cli = NULL;
12928 uint16_t fnum = (uint16_t)-1;
12929 bool correct = false;
12930 const char *dname = "smb1_wild_mangle_rename";
12931 const char *fooname = "smb1_wild_mangle_rename/foo";
12932 const char *foostar_name = "smb1_wild_mangle_rename/fo*";
12933 const char *wild_name = "smb1_wild_mangle_rename/*";
12934 char *windows_rename_src = NULL;
12935 const char *windows_rename_dst = "smb1_wild_mangle_rename\\bar";
12936 char *mangled_name = NULL;
12939 printf("Starting SMB1 wild mangle rename test\n");
12941 if (!torture_open_connection(&cli_posix, 0)) {
12945 smbXcli_conn_set_sockopt(cli_posix->conn, sockops);
12947 status = torture_setup_unix_extensions(cli_posix);
12948 if (!NT_STATUS_IS_OK(status)) {
12949 printf("server doesn't support POSIX\n");
12953 /* Open a Windows connection. */
12954 if (!torture_open_connection(&cli, 0)) {
12958 smbXcli_conn_set_sockopt(cli->conn, sockops);
12960 /* Ensure we start from fresh. */
12961 torture_deltree(cli, dname);
12964 * Create two files - 'foo' and 'fo*'.
12965 * We need POSIX extensions for this as 'fo*'
12966 * is not a valid Windows name.
12969 status = cli_posix_mkdir(cli_posix, dname, 0770);
12970 if (!NT_STATUS_IS_OK(status)) {
12971 printf("cli_posix_mkdir of %s returned %s\n",
12973 nt_errstr(status));
12977 status = cli_posix_open(cli_posix,
12979 O_RDWR|O_CREAT|O_EXCL,
12982 if (!NT_STATUS_IS_OK(status)) {
12983 printf("cli_posix_open (create) of %s returned %s\n",
12985 nt_errstr(status));
12988 status = cli_close(cli_posix, fnum);
12989 if (!NT_STATUS_IS_OK(status)) {
12992 status = cli_posix_open(cli_posix,
12994 O_RDWR|O_CREAT|O_EXCL,
12997 if (!NT_STATUS_IS_OK(status)) {
12998 printf("cli_posix_open (create) of %s returned %s\n",
13000 nt_errstr(status));
13003 status = cli_close(cli_posix, fnum);
13004 if (!NT_STATUS_IS_OK(status)) {
13009 * Get the mangled name. We can re-use the
13010 * previous smb1_wild_mangle_list_fn for this.
13013 status = cli_list(cli,
13016 smb1_wild_mangle_list_fn,
13018 if (!NT_STATUS_IS_OK(status)) {
13019 printf("cli_list of %s returned %s\n",
13021 nt_errstr(status));
13025 if (mangled_name == NULL) {
13029 printf("mangled_name = %s\n",
13033 * Try a Windows rename with the mangled name.
13034 * This should *NOT* rename the 'foo' name.
13037 windows_rename_src = talloc_asprintf(cli_posix,
13042 status = cli_rename(cli,
13043 windows_rename_src,
13044 windows_rename_dst,
13046 if (!NT_STATUS_IS_OK(status)) {
13047 printf("cli_rename of %s -> %s returned %s\n",
13048 windows_rename_src,
13049 windows_rename_dst,
13050 nt_errstr(status));
13054 /* Does 'foo' still exist ? */
13055 status = cli_posix_open(cli_posix,
13060 if (!NT_STATUS_IS_OK(status)) {
13061 printf("cli_posix_open O_RNONLY of %s returned %s\n",
13063 nt_errstr(status));
13067 status = cli_close(cli_posix, fnum);
13068 if (!NT_STATUS_IS_OK(status)) {
13076 TALLOC_FREE(mangled_name);
13077 TALLOC_FREE(windows_rename_src);
13080 torture_deltree(cli, dname);
13081 torture_close_connection(cli);
13084 torture_close_connection(cli_posix);
13090 * Only testing minimal time strings, as the others
13091 * need (locale-dependent) guessing at what strftime does and
13092 * even may differ in builds.
13094 static bool timesubst_test(void)
13096 TALLOC_CTX *ctx = NULL;
13097 /* Sa 23. Dez 04:33:20 CET 2017 */
13098 const struct timeval tv = { 1514000000, 123 };
13099 const char* expect_minimal = "20171223_033320";
13100 const char* expect_minus = "20171223_033320_000123";
13102 char *env_tz, *orig_tz = NULL;
13103 bool result = true;
13105 ctx = talloc_new(NULL);
13107 env_tz = getenv("TZ");
13109 orig_tz = talloc_strdup(ctx, env_tz);
13111 setenv("TZ", "UTC", 1);
13113 s = minimal_timeval_string(ctx, &tv, false);
13115 if(!s || strcmp(s, expect_minimal)) {
13116 printf("minimal_timeval_string(ctx, tv, false) returned [%s], expected "
13117 "[%s]\n", s ? s : "<nil>", expect_minimal);
13121 s = minimal_timeval_string(ctx, &tv, true);
13122 if(!s || strcmp(s, expect_minus)) {
13123 printf("minimal_timeval_string(ctx, tv, true) returned [%s], expected "
13124 "[%s]\n", s ? s : "<nil>", expect_minus);
13130 setenv("TZ", orig_tz, 1);
13137 static bool run_local_substitute(int dummy)
13141 ok &= subst_test("%U", "bla", "", -1, -1, "bla");
13142 ok &= subst_test("%u%U", "bla", "", -1, -1, "blabla");
13143 ok &= subst_test("%g", "", "", -1, -1, "NO_GROUP");
13144 ok &= subst_test("%G", "", "", -1, -1, "NO_GROUP");
13145 ok &= subst_test("%g", "", "", -1, 0, gidtoname(0));
13146 ok &= subst_test("%G", "", "", -1, 0, gidtoname(0));
13147 ok &= subst_test("%D%u", "u", "dom", -1, 0, "domu");
13148 ok &= subst_test("%i %I", "", "", -1, -1, "0.0.0.0 0.0.0.0");
13149 ok &= subst_test("%j %J", "", "", -1, -1, "0_0_0_0 0_0_0_0");
13150 /* Substitution depends on current time, so better test the underlying
13151 formatting function. At least covers %t. */
13152 ok &= timesubst_test();
13154 /* Different captialization rules in sub_basic... */
13156 ok &= (strcmp(talloc_sub_basic(talloc_tos(), "BLA", "dom", "%U%D"),
13162 static bool run_local_base64(int dummy)
13167 for (i=1; i<2000; i++) {
13168 DATA_BLOB blob1, blob2;
13171 blob1.data = talloc_array(talloc_tos(), uint8_t, i);
13173 generate_random_buffer(blob1.data, blob1.length);
13175 b64 = base64_encode_data_blob(talloc_tos(), blob1);
13177 d_fprintf(stderr, "base64_encode_data_blob failed "
13178 "for %d bytes\n", i);
13181 blob2 = base64_decode_data_blob(b64);
13184 if (data_blob_cmp(&blob1, &blob2)) {
13185 d_fprintf(stderr, "data_blob_cmp failed for %d "
13189 TALLOC_FREE(blob1.data);
13190 data_blob_free(&blob2);
13195 static void parse_fn(const struct gencache_timeout *t,
13197 void *private_data)
13202 static bool run_local_gencache(int dummy)
13208 struct memcache *mem;
13211 mem = memcache_init(NULL, 0);
13213 d_printf("%s: memcache_init failed\n", __location__);
13216 memcache_set_global(mem);
13218 if (!gencache_set("foo", "bar", time(NULL) + 1000)) {
13219 d_printf("%s: gencache_set() failed\n", __location__);
13223 if (!gencache_get("foo", NULL, NULL, NULL)) {
13224 d_printf("%s: gencache_get() failed\n", __location__);
13228 for (i=0; i<1000000; i++) {
13229 gencache_parse("foo", parse_fn, NULL);
13232 if (!gencache_get("foo", talloc_tos(), &val, &tm)) {
13233 d_printf("%s: gencache_get() failed\n", __location__);
13238 if (!gencache_get("foo", talloc_tos(), &val, &tm)) {
13239 d_printf("%s: gencache_get() failed\n", __location__);
13243 if (strcmp(val, "bar") != 0) {
13244 d_printf("%s: gencache_get() returned %s, expected %s\n",
13245 __location__, val, "bar");
13252 if (!gencache_del("foo")) {
13253 d_printf("%s: gencache_del() failed\n", __location__);
13256 if (gencache_del("foo")) {
13257 d_printf("%s: second gencache_del() succeeded\n",
13262 if (gencache_get("foo", talloc_tos(), &val, &tm)) {
13263 d_printf("%s: gencache_get() on deleted entry "
13264 "succeeded\n", __location__);
13268 blob = data_blob_string_const_null("bar");
13269 tm = time(NULL) + 60;
13271 if (!gencache_set_data_blob("foo", blob, tm)) {
13272 d_printf("%s: gencache_set_data_blob() failed\n", __location__);
13276 if (!gencache_get_data_blob("foo", talloc_tos(), &blob, NULL, NULL)) {
13277 d_printf("%s: gencache_get_data_blob() failed\n", __location__);
13281 if (strcmp((const char *)blob.data, "bar") != 0) {
13282 d_printf("%s: gencache_get_data_blob() returned %s, expected %s\n",
13283 __location__, (const char *)blob.data, "bar");
13284 data_blob_free(&blob);
13288 data_blob_free(&blob);
13290 if (!gencache_del("foo")) {
13291 d_printf("%s: gencache_del() failed\n", __location__);
13294 if (gencache_del("foo")) {
13295 d_printf("%s: second gencache_del() succeeded\n",
13300 if (gencache_get_data_blob("foo", talloc_tos(), &blob, NULL, NULL)) {
13301 d_printf("%s: gencache_get_data_blob() on deleted entry "
13302 "succeeded\n", __location__);
13307 blob.data = (uint8_t *)&v;
13308 blob.length = sizeof(v);
13310 if (!gencache_set_data_blob("blob", blob, tm)) {
13311 d_printf("%s: gencache_set_data_blob() failed\n",
13315 if (gencache_get("blob", talloc_tos(), &val, &tm)) {
13316 d_printf("%s: gencache_get succeeded\n", __location__);
13323 static bool rbt_testflags(struct db_context *db, const char *key,
13328 struct db_record *rec;
13330 rec = dbwrap_fetch_locked(db, db, string_tdb_data(key));
13332 d_fprintf(stderr, "fetch_locked failed\n");
13336 status = dbwrap_record_store(rec, string_tdb_data(value), TDB_MODIFY);
13337 if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
13338 d_fprintf(stderr, "store TDB_MODIFY unexpected status: %s\n",
13339 nt_errstr(status));
13343 status = dbwrap_record_store(rec, string_tdb_data("overwriteme"),
13345 if (!NT_STATUS_IS_OK(status)) {
13346 d_fprintf(stderr, "store TDB_INSERT failed: %s\n",
13347 nt_errstr(status));
13351 status = dbwrap_record_store(rec, string_tdb_data(value), TDB_INSERT);
13352 if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_COLLISION)) {
13353 d_fprintf(stderr, "store TDB_INSERT unexpected status: %s\n",
13354 nt_errstr(status));
13358 status = dbwrap_record_store(rec, string_tdb_data(value), TDB_MODIFY);
13359 if (!NT_STATUS_IS_OK(status)) {
13360 d_fprintf(stderr, "store TDB_MODIFY failed: %s\n",
13361 nt_errstr(status));
13371 static bool rbt_testval(struct db_context *db, const char *key,
13374 struct db_record *rec;
13375 TDB_DATA data = string_tdb_data(value);
13380 rec = dbwrap_fetch_locked(db, db, string_tdb_data(key));
13382 d_fprintf(stderr, "fetch_locked failed\n");
13385 status = dbwrap_record_store(rec, data, 0);
13386 if (!NT_STATUS_IS_OK(status)) {
13387 d_fprintf(stderr, "store failed: %s\n", nt_errstr(status));
13392 rec = dbwrap_fetch_locked(db, db, string_tdb_data(key));
13394 d_fprintf(stderr, "second fetch_locked failed\n");
13398 dbvalue = dbwrap_record_get_value(rec);
13399 if ((dbvalue.dsize != data.dsize)
13400 || (memcmp(dbvalue.dptr, data.dptr, data.dsize) != 0)) {
13401 d_fprintf(stderr, "Got wrong data back\n");
13411 static int local_rbtree_traverse_read(struct db_record *rec, void *private_data)
13413 int *count2 = (int *)private_data;
13418 static int local_rbtree_traverse_delete(struct db_record *rec, void *private_data)
13420 int *count2 = (int *)private_data;
13422 dbwrap_record_delete(rec);
13426 static bool run_local_rbtree(int dummy)
13428 struct db_context *db;
13435 db = db_open_rbt(NULL);
13438 d_fprintf(stderr, "db_open_rbt failed\n");
13442 if (!rbt_testflags(db, "firstkey", "firstval")) {
13446 for (i = 0; i < 999; i++) {
13447 char key[sizeof("key-9223372036854775807")];
13448 char value[sizeof("value-9223372036854775807")];
13450 snprintf(key, sizeof(key), "key%ld", random());
13451 snprintf(value, sizeof(value) ,"value%ld", random());
13453 if (!rbt_testval(db, key, value)) {
13457 snprintf(value, sizeof(value) ,"value%ld", random());
13459 if (!rbt_testval(db, key, value)) {
13465 count = 0; count2 = 0;
13466 status = dbwrap_traverse_read(db, local_rbtree_traverse_read,
13468 printf("%s: read1: %d %d, %s\n", __func__, count, count2, nt_errstr(status));
13469 if ((count != count2) || (count != 1000)) {
13472 count = 0; count2 = 0;
13473 status = dbwrap_traverse(db, local_rbtree_traverse_delete,
13475 printf("%s: delete: %d %d, %s\n", __func__, count, count2, nt_errstr(status));
13476 if ((count != count2) || (count != 1000)) {
13479 count = 0; count2 = 0;
13480 status = dbwrap_traverse_read(db, local_rbtree_traverse_read,
13482 printf("%s: read2: %d %d, %s\n", __func__, count, count2, nt_errstr(status));
13483 if ((count != count2) || (count != 0)) {
13494 local test for character set functions
13496 This is a very simple test for the functionality in convert_string_error()
13498 static bool run_local_convert_string(int dummy)
13500 TALLOC_CTX *tmp_ctx = talloc_new(NULL);
13501 const char *test_strings[2] = { "March", "M\303\244rz" };
13505 for (i=0; i<2; i++) {
13506 const char *str = test_strings[i];
13507 int len = strlen(str);
13508 size_t converted_size;
13511 memset(dst, 'X', sizeof(dst));
13513 /* first try with real source length */
13514 ret = convert_string_error(CH_UNIX, CH_UTF8,
13519 d_fprintf(stderr, "Failed to convert '%s' to CH_DISPLAY\n", str);
13523 if (converted_size != len) {
13524 d_fprintf(stderr, "Converted size of '%s' should be %d - got %d\n",
13525 str, len, (int)converted_size);
13529 if (strncmp(str, dst, converted_size) != 0) {
13530 d_fprintf(stderr, "Expected '%s' to match '%s'\n", str, dst);
13534 if (strlen(str) != converted_size) {
13535 d_fprintf(stderr, "Expected '%s' length %d - got %d\n", str,
13536 (int)strlen(str), (int)converted_size);
13540 if (dst[converted_size] != 'X') {
13541 d_fprintf(stderr, "Expected no termination of '%s'\n", dst);
13545 /* now with srclen==-1, this causes the nul to be
13547 ret = convert_string_error(CH_UNIX, CH_UTF8,
13552 d_fprintf(stderr, "Failed to convert '%s' to CH_DISPLAY\n", str);
13556 if (converted_size != len+1) {
13557 d_fprintf(stderr, "Converted size of '%s' should be %d - got %d\n",
13558 str, len, (int)converted_size);
13562 if (strncmp(str, dst, converted_size) != 0) {
13563 d_fprintf(stderr, "Expected '%s' to match '%s'\n", str, dst);
13567 if (len+1 != converted_size) {
13568 d_fprintf(stderr, "Expected '%s' length %d - got %d\n", str,
13569 len+1, (int)converted_size);
13573 if (dst[converted_size] != 'X') {
13574 d_fprintf(stderr, "Expected no termination of '%s'\n", dst);
13581 TALLOC_FREE(tmp_ctx);
13584 TALLOC_FREE(tmp_ctx);
13588 static bool run_local_string_to_sid(int dummy) {
13589 struct dom_sid sid;
13591 if (string_to_sid(&sid, "S--1-5-32-545")) {
13592 printf("allowing S--1-5-32-545\n");
13595 if (string_to_sid(&sid, "S-1-5-32-+545")) {
13596 printf("allowing S-1-5-32-+545\n");
13599 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")) {
13600 printf("allowing S-1-2-3-4-5-6-7-8-9-0-1-2-3-4-5-6-7-8-9-0\n");
13603 if (string_to_sid(&sid, "S-1-5-32-545-abc")) {
13604 printf("allowing S-1-5-32-545-abc\n");
13607 if (string_to_sid(&sid, "S-300-5-32-545")) {
13608 printf("allowing S-300-5-32-545\n");
13611 if (string_to_sid(&sid, "S-1-0xfffffffffffffe-32-545")) {
13612 printf("allowing S-1-0xfffffffffffffe-32-545\n");
13615 if (string_to_sid(&sid, "S-1-0xffffffffffff-5294967297-545")) {
13616 printf("allowing S-1-0xffffffffffff-5294967297-545\n");
13619 if (!string_to_sid(&sid, "S-1-0xfffffffffffe-32-545")) {
13620 printf("could not parse S-1-0xfffffffffffe-32-545\n");
13623 if (!string_to_sid(&sid, "S-1-5-32-545")) {
13624 printf("could not parse S-1-5-32-545\n");
13627 if (!dom_sid_equal(&sid, &global_sid_Builtin_Users)) {
13628 struct dom_sid_buf buf;
13629 printf("mis-parsed S-1-5-32-545 as %s\n",
13630 dom_sid_str_buf(&sid, &buf));
13636 static bool sid_to_string_test(const char *expected) {
13639 struct dom_sid sid;
13641 if (!string_to_sid(&sid, expected)) {
13642 printf("could not parse %s\n", expected);
13646 str = dom_sid_string(NULL, &sid);
13647 if (strcmp(str, expected)) {
13648 printf("Comparison failed (%s != %s)\n", str, expected);
13655 static bool run_local_sid_to_string(int dummy) {
13656 if (!sid_to_string_test("S-1-0xffffffffffff-1-1-1-1-1-1-1-1-1-1-1-1"))
13658 if (!sid_to_string_test("S-1-545"))
13660 if (!sid_to_string_test("S-255-3840-1-1-1-1"))
13665 static bool run_local_binary_to_sid(int dummy) {
13667 struct dom_sid *sid = talloc(NULL, struct dom_sid);
13668 static const uint8_t good_binary_sid[] = {
13669 0x1, /* revision number */
13670 15, /* num auths */
13671 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, /* id_auth */
13672 0x1, 0x1, 0x1, 0x1, /* auth[0] */
13673 0x1, 0x1, 0x1, 0x1, /* auth[1] */
13674 0x1, 0x1, 0x1, 0x1, /* auth[2] */
13675 0x1, 0x1, 0x1, 0x1, /* auth[3] */
13676 0x1, 0x1, 0x1, 0x1, /* auth[4] */
13677 0x1, 0x1, 0x1, 0x1, /* auth[5] */
13678 0x1, 0x1, 0x1, 0x1, /* auth[6] */
13679 0x1, 0x1, 0x1, 0x1, /* auth[7] */
13680 0x1, 0x1, 0x1, 0x1, /* auth[8] */
13681 0x1, 0x1, 0x1, 0x1, /* auth[9] */
13682 0x1, 0x1, 0x1, 0x1, /* auth[10] */
13683 0x1, 0x1, 0x1, 0x1, /* auth[11] */
13684 0x1, 0x1, 0x1, 0x1, /* auth[12] */
13685 0x1, 0x1, 0x1, 0x1, /* auth[13] */
13686 0x1, 0x1, 0x1, 0x1, /* auth[14] */
13689 static const uint8_t long_binary_sid[] = {
13690 0x1, /* revision number */
13691 15, /* num auths */
13692 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, /* id_auth */
13693 0x1, 0x1, 0x1, 0x1, /* auth[0] */
13694 0x1, 0x1, 0x1, 0x1, /* auth[1] */
13695 0x1, 0x1, 0x1, 0x1, /* auth[2] */
13696 0x1, 0x1, 0x1, 0x1, /* auth[3] */
13697 0x1, 0x1, 0x1, 0x1, /* auth[4] */
13698 0x1, 0x1, 0x1, 0x1, /* auth[5] */
13699 0x1, 0x1, 0x1, 0x1, /* auth[6] */
13700 0x1, 0x1, 0x1, 0x1, /* auth[7] */
13701 0x1, 0x1, 0x1, 0x1, /* auth[8] */
13702 0x1, 0x1, 0x1, 0x1, /* auth[9] */
13703 0x1, 0x1, 0x1, 0x1, /* auth[10] */
13704 0x1, 0x1, 0x1, 0x1, /* auth[11] */
13705 0x1, 0x1, 0x1, 0x1, /* auth[12] */
13706 0x1, 0x1, 0x1, 0x1, /* auth[13] */
13707 0x1, 0x1, 0x1, 0x1, /* auth[14] */
13708 0x1, 0x1, 0x1, 0x1, /* auth[15] */
13709 0x1, 0x1, 0x1, 0x1, /* auth[16] */
13710 0x1, 0x1, 0x1, 0x1, /* auth[17] */
13713 static const uint8_t long_binary_sid2[] = {
13714 0x1, /* revision number */
13715 32, /* num auths */
13716 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, /* id_auth */
13717 0x1, 0x1, 0x1, 0x1, /* auth[0] */
13718 0x1, 0x1, 0x1, 0x1, /* auth[1] */
13719 0x1, 0x1, 0x1, 0x1, /* auth[2] */
13720 0x1, 0x1, 0x1, 0x1, /* auth[3] */
13721 0x1, 0x1, 0x1, 0x1, /* auth[4] */
13722 0x1, 0x1, 0x1, 0x1, /* auth[5] */
13723 0x1, 0x1, 0x1, 0x1, /* auth[6] */
13724 0x1, 0x1, 0x1, 0x1, /* auth[7] */
13725 0x1, 0x1, 0x1, 0x1, /* auth[8] */
13726 0x1, 0x1, 0x1, 0x1, /* auth[9] */
13727 0x1, 0x1, 0x1, 0x1, /* auth[10] */
13728 0x1, 0x1, 0x1, 0x1, /* auth[11] */
13729 0x1, 0x1, 0x1, 0x1, /* auth[12] */
13730 0x1, 0x1, 0x1, 0x1, /* auth[13] */
13731 0x1, 0x1, 0x1, 0x1, /* auth[14] */
13732 0x1, 0x1, 0x1, 0x1, /* auth[15] */
13733 0x1, 0x1, 0x1, 0x1, /* auth[16] */
13734 0x1, 0x1, 0x1, 0x1, /* auth[17] */
13735 0x1, 0x1, 0x1, 0x1, /* auth[18] */
13736 0x1, 0x1, 0x1, 0x1, /* auth[19] */
13737 0x1, 0x1, 0x1, 0x1, /* auth[20] */
13738 0x1, 0x1, 0x1, 0x1, /* auth[21] */
13739 0x1, 0x1, 0x1, 0x1, /* auth[22] */
13740 0x1, 0x1, 0x1, 0x1, /* auth[23] */
13741 0x1, 0x1, 0x1, 0x1, /* auth[24] */
13742 0x1, 0x1, 0x1, 0x1, /* auth[25] */
13743 0x1, 0x1, 0x1, 0x1, /* auth[26] */
13744 0x1, 0x1, 0x1, 0x1, /* auth[27] */
13745 0x1, 0x1, 0x1, 0x1, /* auth[28] */
13746 0x1, 0x1, 0x1, 0x1, /* auth[29] */
13747 0x1, 0x1, 0x1, 0x1, /* auth[30] */
13748 0x1, 0x1, 0x1, 0x1, /* auth[31] */
13751 ret = sid_parse(good_binary_sid, sizeof(good_binary_sid), sid);
13755 ret = sid_parse(long_binary_sid2, sizeof(long_binary_sid2), sid);
13759 ret = sid_parse(long_binary_sid, sizeof(long_binary_sid), sid);
13766 /* Split a path name into filename and stream name components. Canonicalise
13767 * such that an implicit $DATA token is always explicit.
13769 * The "specification" of this function can be found in the
13770 * run_local_stream_name() function in torture.c, I've tried those
13771 * combinations against a W2k3 server.
13774 static NTSTATUS split_ntfs_stream_name(TALLOC_CTX *mem_ctx, const char *fname,
13775 char **pbase, char **pstream)
13778 char *stream = NULL;
13779 char *sname; /* stream name */
13780 const char *stype; /* stream type */
13782 DEBUG(10, ("split_ntfs_stream_name called for [%s]\n", fname));
13784 sname = strchr_m(fname, ':');
13786 if (sname == NULL) {
13787 if (pbase != NULL) {
13788 base = talloc_strdup(mem_ctx, fname);
13789 NT_STATUS_HAVE_NO_MEMORY(base);
13794 if (pbase != NULL) {
13795 base = talloc_strndup(mem_ctx, fname, PTR_DIFF(sname, fname));
13796 NT_STATUS_HAVE_NO_MEMORY(base);
13801 stype = strchr_m(sname, ':');
13803 if (stype == NULL) {
13804 sname = talloc_strdup(mem_ctx, sname);
13808 if (strcasecmp_m(stype, ":$DATA") != 0) {
13810 * If there is an explicit stream type, so far we only
13811 * allow $DATA. Is there anything else allowed? -- vl
13813 DEBUG(10, ("[%s] is an invalid stream type\n", stype));
13815 return NT_STATUS_OBJECT_NAME_INVALID;
13817 sname = talloc_strndup(mem_ctx, sname, PTR_DIFF(stype, sname));
13821 if (sname == NULL) {
13823 return NT_STATUS_NO_MEMORY;
13826 if (sname[0] == '\0') {
13828 * no stream name, so no stream
13833 if (pstream != NULL) {
13834 stream = talloc_asprintf(mem_ctx, "%s:%s", sname, stype);
13835 if (stream == NULL) {
13836 TALLOC_FREE(sname);
13838 return NT_STATUS_NO_MEMORY;
13841 * upper-case the type field
13843 (void)strupper_m(strchr_m(stream, ':')+1);
13847 if (pbase != NULL) {
13850 if (pstream != NULL) {
13853 return NT_STATUS_OK;
13856 static bool test_stream_name(const char *fname, const char *expected_base,
13857 const char *expected_stream,
13858 NTSTATUS expected_status)
13862 char *stream = NULL;
13864 status = split_ntfs_stream_name(talloc_tos(), fname, &base, &stream);
13865 if (!NT_STATUS_EQUAL(status, expected_status)) {
13869 if (!NT_STATUS_IS_OK(status)) {
13873 if (base == NULL) goto error;
13875 if (strcmp(expected_base, base) != 0) goto error;
13877 if ((expected_stream != NULL) && (stream == NULL)) goto error;
13878 if ((expected_stream == NULL) && (stream != NULL)) goto error;
13880 if ((stream != NULL) && (strcmp(expected_stream, stream) != 0))
13884 TALLOC_FREE(stream);
13888 d_fprintf(stderr, "Do test_stream(%s, %s, %s, %s)\n",
13889 fname, expected_base ? expected_base : "<NULL>",
13890 expected_stream ? expected_stream : "<NULL>",
13891 nt_errstr(expected_status));
13892 d_fprintf(stderr, "-> base=%s, stream=%s, status=%s\n",
13893 base ? base : "<NULL>", stream ? stream : "<NULL>",
13894 nt_errstr(status));
13896 TALLOC_FREE(stream);
13900 static bool run_local_stream_name(int dummy)
13904 ret &= test_stream_name(
13905 "bla", "bla", NULL, NT_STATUS_OK);
13906 ret &= test_stream_name(
13907 "bla::$DATA", "bla", NULL, NT_STATUS_OK);
13908 ret &= test_stream_name(
13909 "bla:blub:", "bla", NULL, NT_STATUS_OBJECT_NAME_INVALID);
13910 ret &= test_stream_name(
13911 "bla::", NULL, NULL, NT_STATUS_OBJECT_NAME_INVALID);
13912 ret &= test_stream_name(
13913 "bla::123", "bla", NULL, NT_STATUS_OBJECT_NAME_INVALID);
13914 ret &= test_stream_name(
13915 "bla:$DATA", "bla", "$DATA:$DATA", NT_STATUS_OK);
13916 ret &= test_stream_name(
13917 "bla:x:$DATA", "bla", "x:$DATA", NT_STATUS_OK);
13918 ret &= test_stream_name(
13919 "bla:x", "bla", "x:$DATA", NT_STATUS_OK);
13924 static bool data_blob_equal(DATA_BLOB a, DATA_BLOB b)
13926 if (a.length != b.length) {
13927 printf("a.length=%d != b.length=%d\n",
13928 (int)a.length, (int)b.length);
13931 if (memcmp(a.data, b.data, a.length) != 0) {
13932 printf("a.data and b.data differ\n");
13938 static bool run_local_memcache(int dummy)
13940 struct memcache *cache;
13941 DATA_BLOB k1, k2, k3, k4, k5;
13945 TALLOC_CTX *mem_ctx;
13951 size_t size1, size2;
13954 mem_ctx = talloc_init("foo");
13955 if (mem_ctx == NULL) {
13959 /* STAT_CACHE TESTS */
13961 cache = memcache_init(NULL, sizeof(void *) == 8 ? 200 : 100);
13963 if (cache == NULL) {
13964 printf("memcache_init failed\n");
13968 d1 = data_blob_const("d1", 2);
13969 d3 = data_blob_const("d3", 2);
13971 k1 = data_blob_const("d1", 2);
13972 k2 = data_blob_const("d2", 2);
13973 k3 = data_blob_const("d3", 2);
13974 k4 = data_blob_const("d4", 2);
13975 k5 = data_blob_const("d5", 2);
13977 memcache_add(cache, STAT_CACHE, k1, d1);
13979 if (!memcache_lookup(cache, STAT_CACHE, k1, &v1)) {
13980 printf("could not find k1\n");
13983 if (!data_blob_equal(d1, v1)) {
13987 memcache_add(cache, STAT_CACHE, k1, d3);
13989 if (!memcache_lookup(cache, STAT_CACHE, k1, &v3)) {
13990 printf("could not find replaced k1\n");
13993 if (!data_blob_equal(d3, v3)) {
13997 TALLOC_FREE(cache);
13999 /* GETWD_CACHE TESTS */
14000 str1 = talloc_strdup(mem_ctx, "string1");
14001 if (str1 == NULL) {
14004 ptr2 = str1; /* Keep an alias for comparison. */
14006 str2 = talloc_strdup(mem_ctx, "string2");
14007 if (str2 == NULL) {
14011 cache = memcache_init(NULL, sizeof(void *) == 8 ? 200 : 100);
14012 if (cache == NULL) {
14013 printf("memcache_init failed\n");
14017 memcache_add_talloc(cache, GETWD_CACHE, k2, &str1);
14018 /* str1 == NULL now. */
14019 ptr1 = memcache_lookup_talloc(cache, GETWD_CACHE, k2);
14020 if (ptr1 == NULL) {
14021 printf("could not find k2\n");
14024 if (ptr1 != ptr2) {
14025 printf("fetch of k2 got wrong string\n");
14029 /* Add a blob to ensure k2 gets purged. */
14030 d3 = data_blob_talloc_zero(mem_ctx, 180);
14031 memcache_add(cache, STAT_CACHE, k3, d3);
14033 ptr2 = memcache_lookup_talloc(cache, GETWD_CACHE, k2);
14034 if (ptr2 != NULL) {
14035 printf("Did find k2, should have been purged\n");
14040 * Test that talloc size also is accounted in memcache and
14041 * causes purge of other object.
14044 str1 = talloc_zero_size(mem_ctx, 100);
14045 str2 = talloc_zero_size(mem_ctx, 100);
14047 memcache_add_talloc(cache, GETWD_CACHE, k4, &str1);
14048 memcache_add_talloc(cache, GETWD_CACHE, k5, &str1);
14050 ptr3 = memcache_lookup_talloc(cache, GETWD_CACHE, k4);
14051 if (ptr3 != NULL) {
14052 printf("Did find k4, should have been purged\n");
14057 * Test that adding a duplicate non-talloced
14058 * key/value on top of a talloced key/value takes account
14059 * of the talloc_freed value size.
14061 TALLOC_FREE(cache);
14062 TALLOC_FREE(mem_ctx);
14064 mem_ctx = talloc_init("key_replace");
14065 if (mem_ctx == NULL) {
14069 cache = memcache_init(NULL, sizeof(void *) == 8 ? 200 : 100);
14070 if (cache == NULL) {
14075 * Add a 100 byte talloced string. This will
14076 * store a (4 or 8 byte) pointer and record the
14077 * total talloced size.
14079 str1 = talloc_zero_size(mem_ctx, 100);
14080 memcache_add_talloc(cache, GETWD_CACHE, k4, &str1);
14082 * Now overwrite with a small talloced
14083 * value. This should fit in the existing size
14084 * and the total talloced size should be removed
14085 * from the cache size.
14087 str1 = talloc_zero_size(mem_ctx, 2);
14088 memcache_add_talloc(cache, GETWD_CACHE, k4, &str1);
14090 * Now store a 20 byte string. If the
14091 * total talloced size wasn't accounted for
14092 * and removed in the overwrite, then this
14095 str2 = talloc_zero_size(mem_ctx, 20);
14096 memcache_add_talloc(cache, GETWD_CACHE, k5, &str2);
14098 ptr3 = memcache_lookup_talloc(cache, GETWD_CACHE, k4);
14099 if (ptr3 == NULL) {
14100 printf("Did not find k4, should not have been purged\n");
14104 TALLOC_FREE(cache);
14105 TALLOC_FREE(mem_ctx);
14107 mem_ctx = talloc_init("foo");
14108 if (mem_ctx == NULL) {
14112 cache = memcache_init(NULL, 0);
14113 if (cache == NULL) {
14117 str1 = talloc_strdup(mem_ctx, "string1");
14118 if (str1 == NULL) {
14121 str2 = talloc_strdup(mem_ctx, "string2");
14122 if (str2 == NULL) {
14125 memcache_add_talloc(cache, SINGLETON_CACHE_TALLOC,
14126 data_blob_string_const("torture"), &str1);
14127 size1 = talloc_total_size(cache);
14129 memcache_add_talloc(cache, SINGLETON_CACHE_TALLOC,
14130 data_blob_string_const("torture"), &str2);
14131 size2 = talloc_total_size(cache);
14133 printf("size1=%d, size2=%d\n", (int)size1, (int)size2);
14135 if (size2 > size1) {
14136 printf("memcache leaks memory!\n");
14142 TALLOC_FREE(cache);
14146 static void wbclient_done(struct tevent_req *req)
14149 struct winbindd_response *wb_resp;
14150 int *i = (int *)tevent_req_callback_data_void(req);
14152 wbc_err = wb_trans_recv(req, req, &wb_resp);
14155 d_printf("wb_trans_recv %d returned %s\n", *i, wbcErrorString(wbc_err));
14158 static bool run_wbclient_multi_ping(int dummy)
14160 struct tevent_context *ev;
14161 struct wb_context **wb_ctx;
14162 struct winbindd_request wb_req;
14163 bool result = false;
14166 BlockSignals(True, SIGPIPE);
14168 ev = tevent_context_init(talloc_tos());
14173 wb_ctx = talloc_array(ev, struct wb_context *, torture_nprocs);
14174 if (wb_ctx == NULL) {
14178 ZERO_STRUCT(wb_req);
14179 wb_req.cmd = WINBINDD_PING;
14181 d_printf("torture_nprocs=%d, numops=%d\n", (int)torture_nprocs, (int)torture_numops);
14183 for (i=0; i<torture_nprocs; i++) {
14184 wb_ctx[i] = wb_context_init(ev, NULL);
14185 if (wb_ctx[i] == NULL) {
14188 for (j=0; j<torture_numops; j++) {
14189 struct tevent_req *req;
14190 req = wb_trans_send(ev, ev, wb_ctx[i],
14191 (j % 2) == 0, &wb_req);
14195 tevent_req_set_callback(req, wbclient_done, &i);
14201 while (i < torture_nprocs * torture_numops) {
14202 tevent_loop_once(ev);
14211 static bool dbtrans_inc(struct db_context *db)
14213 struct db_record *rec;
14219 rec = dbwrap_fetch_locked(db, db, string_term_tdb_data("transtest"));
14221 printf(__location__ "fetch_lock failed\n");
14225 value = dbwrap_record_get_value(rec);
14227 if (value.dsize != sizeof(uint32_t)) {
14228 printf(__location__ "value.dsize = %d\n",
14233 memcpy(&val, value.dptr, sizeof(val));
14236 status = dbwrap_record_store(
14237 rec, make_tdb_data((uint8_t *)&val, sizeof(val)), 0);
14238 if (!NT_STATUS_IS_OK(status)) {
14239 printf(__location__ "store failed: %s\n",
14240 nt_errstr(status));
14250 static bool run_local_dbtrans(int dummy)
14252 struct db_context *db;
14253 struct db_record *rec;
14259 db = db_open(talloc_tos(), "transtest.tdb", 0, TDB_DEFAULT,
14260 O_RDWR|O_CREAT, 0600, DBWRAP_LOCK_ORDER_1,
14263 printf("Could not open transtest.db\n");
14267 res = dbwrap_transaction_start(db);
14269 printf(__location__ "transaction_start failed\n");
14273 rec = dbwrap_fetch_locked(db, db, string_term_tdb_data("transtest"));
14275 printf(__location__ "fetch_lock failed\n");
14279 value = dbwrap_record_get_value(rec);
14281 if (value.dptr == NULL) {
14283 status = dbwrap_record_store(
14284 rec, make_tdb_data((uint8_t *)&initial,
14287 if (!NT_STATUS_IS_OK(status)) {
14288 printf(__location__ "store returned %s\n",
14289 nt_errstr(status));
14296 res = dbwrap_transaction_commit(db);
14298 printf(__location__ "transaction_commit failed\n");
14303 uint32_t val, val2;
14306 res = dbwrap_transaction_start(db);
14308 printf(__location__ "transaction_start failed\n");
14312 status = dbwrap_fetch_uint32_bystring(db, "transtest", &val);
14313 if (!NT_STATUS_IS_OK(status)) {
14314 printf(__location__ "dbwrap_fetch_uint32 failed: %s\n",
14315 nt_errstr(status));
14319 for (i=0; i<10; i++) {
14320 if (!dbtrans_inc(db)) {
14325 status = dbwrap_fetch_uint32_bystring(db, "transtest", &val2);
14326 if (!NT_STATUS_IS_OK(status)) {
14327 printf(__location__ "dbwrap_fetch_uint32 failed: %s\n",
14328 nt_errstr(status));
14332 if (val2 != val + 10) {
14333 printf(__location__ "val=%d, val2=%d\n",
14334 (int)val, (int)val2);
14338 printf("val2=%d\r", val2);
14340 res = dbwrap_transaction_commit(db);
14342 printf(__location__ "transaction_commit failed\n");
14352 * Just a dummy test to be run under a debugger. There's no real way
14353 * to inspect the tevent_poll specific function from outside of
14357 static bool run_local_tevent_poll(int dummy)
14359 struct tevent_context *ev;
14360 struct tevent_fd *fd1, *fd2;
14361 bool result = false;
14363 ev = tevent_context_init_byname(NULL, "poll");
14365 d_fprintf(stderr, "tevent_context_init_byname failed\n");
14369 fd1 = tevent_add_fd(ev, ev, 2, 0, NULL, NULL);
14371 d_fprintf(stderr, "tevent_add_fd failed\n");
14374 fd2 = tevent_add_fd(ev, ev, 3, 0, NULL, NULL);
14376 d_fprintf(stderr, "tevent_add_fd failed\n");
14381 fd2 = tevent_add_fd(ev, ev, 1, 0, NULL, NULL);
14383 d_fprintf(stderr, "tevent_add_fd failed\n");
14393 static bool run_local_hex_encode_buf(int dummy)
14399 for (i=0; i<sizeof(src); i++) {
14402 hex_encode_buf(buf, src, sizeof(src));
14403 if (strcmp(buf, "0001020304050607") != 0) {
14406 hex_encode_buf(buf, NULL, 0);
14407 if (buf[0] != '\0') {
14413 static const char *remove_duplicate_addrs2_test_strings_vector[] = {
14435 "1001:1111:1111:1000:0:1111:1111:1111",
14444 static const char *remove_duplicate_addrs2_test_strings_result[] = {
14458 "1001:1111:1111:1000:0:1111:1111:1111"
14461 static bool run_local_remove_duplicate_addrs2(int dummy)
14463 struct samba_sockaddr test_vector[28];
14466 /* Construct the sockaddr_storage test vector. */
14467 for (i = 0; i < 28; i++) {
14468 struct addrinfo hints;
14469 struct addrinfo *res = NULL;
14472 memset(&hints, '\0', sizeof(hints));
14473 hints.ai_flags = AI_NUMERICHOST;
14474 ret = getaddrinfo(remove_duplicate_addrs2_test_strings_vector[i],
14479 fprintf(stderr, "getaddrinfo failed on [%s]\n",
14480 remove_duplicate_addrs2_test_strings_vector[i]);
14483 memset(&test_vector[i], '\0', sizeof(test_vector[i]));
14484 memcpy(&test_vector[i].u.ss,
14490 count = remove_duplicate_addrs2(test_vector, i);
14493 fprintf(stderr, "count wrong (%zu) should be 14\n",
14498 for (i = 0; i < count; i++) {
14499 char addr[INET6_ADDRSTRLEN];
14501 print_sockaddr(addr, sizeof(addr), &test_vector[i].u.ss);
14503 if (strcmp(addr, remove_duplicate_addrs2_test_strings_result[i]) != 0) {
14504 fprintf(stderr, "mismatch on [%zu] [%s] [%s]\n",
14507 remove_duplicate_addrs2_test_strings_result[i]);
14512 printf("run_local_remove_duplicate_addrs2: success\n");
14516 static bool run_local_tdb_opener(int dummy)
14522 t = tdb_open("test.tdb", 1000, TDB_CLEAR_IF_FIRST,
14523 O_RDWR|O_CREAT, 0755);
14525 perror("tdb_open failed");
14536 static bool run_local_tdb_writer(int dummy)
14542 t = tdb_open("test.tdb", 1000, 0, O_RDWR|O_CREAT, 0755);
14544 perror("tdb_open failed");
14548 val.dptr = (uint8_t *)&v;
14549 val.dsize = sizeof(v);
14555 ret = tdb_store(t, val, val, 0);
14557 printf("%s\n", tdb_errorstr(t));
14562 data = tdb_fetch(t, val);
14563 if (data.dptr != NULL) {
14564 SAFE_FREE(data.dptr);
14570 static bool run_local_canonicalize_path(int dummy)
14572 const char *src[] = {
14579 ".././././../../../boo",
14591 "/foo/bar/../baz/",
14592 "////////////////",
14593 "/////////./././././.",
14594 "/./.././../.boo/../baz",
14595 "/a/component/path",
14596 "/a/component/path/",
14597 "/a/component/path/..",
14598 "/a/component/../path/",
14599 "///a/./././///component/../////path/",
14602 const char *dst[] = {
14625 "/a/component/path",
14626 "/a/component/path",
14634 for (i = 0; src[i] != NULL; i++) {
14635 char *d = canonicalize_absolute_path(talloc_tos(), src[i]);
14637 perror("talloc fail\n");
14640 if (strcmp(d, dst[i]) != 0) {
14642 "canonicalize mismatch %s -> %s != %s",
14643 src[i], d, dst[i]);
14651 static bool run_ign_bad_negprot(int dummy)
14653 struct tevent_context *ev;
14654 struct tevent_req *req;
14655 struct smbXcli_conn *conn;
14656 struct sockaddr_storage ss;
14661 printf("starting ignore bad negprot\n");
14663 ok = resolve_name(host, &ss, 0x20, true);
14665 d_fprintf(stderr, "Could not resolve name %s\n", host);
14669 status = open_socket_out(&ss, 445, 10000, &fd);
14670 if (!NT_STATUS_IS_OK(status)) {
14671 d_fprintf(stderr, "open_socket_out failed: %s\n",
14672 nt_errstr(status));
14676 conn = smbXcli_conn_create(talloc_tos(), fd, host, SMB_SIGNING_OFF, 0,
14678 if (conn == NULL) {
14679 d_fprintf(stderr, "smbXcli_conn_create failed\n");
14683 status = smbXcli_negprot(conn, 0, PROTOCOL_CORE, PROTOCOL_CORE);
14684 if (NT_STATUS_IS_OK(status)) {
14685 d_fprintf(stderr, "smbXcli_negprot succeeded!\n");
14689 ev = samba_tevent_context_init(talloc_tos());
14691 d_fprintf(stderr, "samba_tevent_context_init failed\n");
14695 req = smb1cli_session_setup_nt1_send(
14696 ev, ev, conn, 0, getpid(), NULL, 65503, 2, 1, 0, "", "",
14697 data_blob_null, data_blob_null, 0x40,
14698 "Windows 2000 2195", "Windows 2000 5.0");
14700 d_fprintf(stderr, "smb1cli_session_setup_nt1_send failed\n");
14704 ok = tevent_req_poll_ntstatus(req, ev, &status);
14706 d_fprintf(stderr, "tevent_req_poll failed\n");
14710 status = smb1cli_session_setup_nt1_recv(req, NULL, NULL, NULL, NULL,
14712 if (!NT_STATUS_EQUAL(status, NT_STATUS_CONNECTION_RESET)) {
14713 d_fprintf(stderr, "smb1cli_session_setup_nt1_recv returned "
14714 "%s, expected NT_STATUS_CONNECTION_RESET\n",
14715 nt_errstr(status));
14721 printf("starting ignore bad negprot\n");
14726 static double create_procs(bool (*fn)(int), bool *result)
14729 volatile pid_t *child_status;
14730 volatile bool *child_status_out;
14733 struct timeval start;
14737 child_status = (volatile pid_t *)anonymous_shared_allocate(sizeof(pid_t)*torture_nprocs);
14738 if (!child_status) {
14739 printf("Failed to setup shared memory\n");
14743 child_status_out = (volatile bool *)anonymous_shared_allocate(sizeof(bool)*torture_nprocs);
14744 if (!child_status_out) {
14745 printf("Failed to setup result status shared memory\n");
14749 for (i = 0; i < torture_nprocs; i++) {
14750 child_status[i] = 0;
14751 child_status_out[i] = True;
14754 start = timeval_current();
14756 for (i=0;i<torture_nprocs;i++) {
14759 pid_t mypid = getpid();
14760 sys_srandom(((int)mypid) ^ ((int)time(NULL)));
14762 slprintf(myname,sizeof(myname),"CLIENT%d", i);
14765 if (torture_open_connection(¤t_cli, i)) break;
14766 if (tries-- == 0) {
14767 printf("pid %d failed to start\n", (int)getpid());
14773 child_status[i] = getpid();
14775 while (child_status[i] && timeval_elapsed(&start) < 5) smb_msleep(2);
14777 child_status_out[i] = fn(i);
14784 for (i=0;i<torture_nprocs;i++) {
14785 if (child_status[i]) synccount++;
14787 if (synccount == torture_nprocs) break;
14789 } while (timeval_elapsed(&start) < 30);
14791 if (synccount != torture_nprocs) {
14792 printf("FAILED TO START %d CLIENTS (started %d)\n", torture_nprocs, synccount);
14794 return timeval_elapsed(&start);
14797 /* start the client load */
14798 start = timeval_current();
14800 for (i=0;i<torture_nprocs;i++) {
14801 child_status[i] = 0;
14804 printf("%d clients started\n", torture_nprocs);
14806 for (i=0;i<torture_nprocs;i++) {
14807 while (waitpid(0, &status, 0) == -1 && errno == EINTR) /* noop */ ;
14812 for (i=0;i<torture_nprocs;i++) {
14813 if (!child_status_out[i]) {
14817 return timeval_elapsed(&start);
14820 #define FLAG_MULTIPROC 1
14826 } torture_ops[] = {
14829 .fn = run_fdpasstest,
14833 .fn = run_locktest1,
14837 .fn = run_locktest2,
14841 .fn = run_locktest3,
14845 .fn = run_locktest4,
14849 .fn = run_locktest5,
14853 .fn = run_locktest6,
14857 .fn = run_locktest7,
14861 .fn = run_locktest8,
14865 .fn = run_locktest9a,
14869 .fn = run_locktest9b,
14873 .fn = run_locktest10,
14877 .fn = run_locktest11,
14881 .fn = run_locktest12,
14885 .fn = run_locktest13,
14889 .fn = run_unlinktest,
14893 .fn = run_browsetest,
14897 .fn = run_attrtest,
14901 .fn = run_trans2test,
14905 .fn = run_maxfidtest,
14906 .flags = FLAG_MULTIPROC,
14911 .flags = FLAG_MULTIPROC,
14914 .name = "RANDOMIPC",
14915 .fn = run_randomipc,
14918 .name = "NEGNOWAIT",
14919 .fn = run_negprot_nowait,
14941 #ifdef HAVE_KERNEL_OPLOCKS_LINUX
14953 .fn = run_dirtest1,
14956 .name = "DIR-CREATETIME",
14957 .fn = run_dir_createtime,
14961 .fn = torture_denytest1,
14965 .fn = torture_denytest2,
14969 .fn = run_tcon_test,
14973 .fn = run_tcon_devtype_test,
14977 .fn = run_readwritetest,
14981 .fn = run_readwritemulti,
14982 .flags = FLAG_MULTIPROC
14986 .fn = run_readwritelarge,
14989 .name = "RW-SIGNING",
14990 .fn = run_readwritelarge_signtest,
14994 .fn = run_opentest,
14998 .fn = run_simple_posix_open_test,
15001 .name = "POSIX-APPEND",
15002 .fn = run_posix_append,
15005 .name = "POSIX-SYMLINK-ACL",
15006 .fn = run_acl_symlink_test,
15009 .name = "POSIX-SYMLINK-EA",
15010 .fn = run_ea_symlink_test,
15013 .name = "POSIX-STREAM-DELETE",
15014 .fn = run_posix_stream_delete,
15017 .name = "POSIX-OFD-LOCK",
15018 .fn = run_posix_ofd_lock_test,
15021 .name = "POSIX-BLOCKING-LOCK",
15022 .fn = run_posix_blocking_lock,
15025 .name = "POSIX-MKDIR",
15026 .fn = run_posix_mkdir_test,
15029 .name = "POSIX-ACL-OPLOCK",
15030 .fn = run_posix_acl_oplock_test,
15033 .name = "POSIX-ACL-SHAREROOT",
15034 .fn = run_posix_acl_shareroot_test,
15037 .name = "POSIX-LS-WILDCARD",
15038 .fn = run_posix_ls_wildcard_test,
15041 .name = "POSIX-LS-SINGLE",
15042 .fn = run_posix_ls_single_test,
15045 .name = "POSIX-READLINK",
15046 .fn = run_posix_readlink_test,
15049 .name = "POSIX-STAT",
15050 .fn = run_posix_stat_test,
15053 .name = "POSIX-SYMLINK-PARENT",
15054 .fn = run_posix_symlink_parent_test,
15057 .name = "POSIX-SYMLINK-CHMOD",
15058 .fn = run_posix_symlink_chmod_test,
15061 .name = "POSIX-SYMLINK-RENAME",
15062 .fn = run_posix_symlink_rename_test,
15065 .name = "POSIX-DIR-DEFAULT-ACL",
15066 .fn = run_posix_dir_default_acl_test,
15069 .name = "POSIX-SYMLINK-GETPATHINFO",
15070 .fn = run_posix_symlink_getpathinfo_test,
15073 .name = "POSIX-SYMLINK-SETPATHINFO",
15074 .fn = run_posix_symlink_setpathinfo_test,
15077 .name = "WINDOWS-BAD-SYMLINK",
15078 .fn = run_symlink_open_test,
15081 .name = "SMB1-WILD-MANGLE-UNLINK",
15082 .fn = run_smb1_wild_mangle_unlink_test,
15085 .name = "SMB1-WILD-MANGLE-RENAME",
15086 .fn = run_smb1_wild_mangle_rename_test,
15089 .name = "CASE-INSENSITIVE-CREATE",
15090 .fn = run_case_insensitive_create,
15093 .name = "ASYNC-ECHO",
15094 .fn = run_async_echo,
15097 .name = "UID-REGRESSION-TEST",
15098 .fn = run_uid_regression_test,
15101 .name = "SHORTNAME-TEST",
15102 .fn = run_shortname_test,
15105 .name = "ADDRCHANGE",
15106 .fn = run_addrchange,
15110 .name = "OPENATTR",
15111 .fn = run_openattrtest,
15123 .name = "RENAME-ACCESS",
15124 .fn = run_rename_access,
15127 .name = "OWNER-RIGHTS",
15128 .fn = run_owner_rights,
15132 .fn = run_deletetest,
15135 .name = "DELETE-STREAM",
15136 .fn = run_delete_stream,
15139 .name = "DELETE-PRINT",
15140 .fn = run_delete_print_test,
15143 .name = "DELETE-LN",
15144 .fn = run_deletetest_ln,
15147 .name = "PROPERTIES",
15148 .fn = run_properties,
15152 .fn = torture_mangle,
15159 .name = "MANGLE-ILLEGAL",
15160 .fn = run_mangle_illegal,
15167 .name = "TRANS2SCAN",
15168 .fn = torture_trans2_scan,
15171 .name = "NTTRANSSCAN",
15172 .fn = torture_nttrans_scan,
15176 .fn = torture_utable,
15179 .name = "CASETABLE",
15180 .fn = torture_casetable,
15183 .name = "ERRMAPEXTRACT",
15184 .fn = run_error_map_extract,
15187 .name = "PIPE_NUMBER",
15188 .fn = run_pipe_number,
15192 .fn = run_tcon2_test,
15196 .fn = torture_ioctl_test,
15200 .fn = torture_chkpath_test,
15204 .fn = run_fdsesstest,
15211 .name = "SESSSETUP_BENCH",
15212 .fn = run_sesssetup_bench,
15227 .name = "WINDOWS-WRITE",
15228 .fn = run_windows_write,
15231 .name = "LARGE_READX",
15232 .fn = run_large_readx,
15235 .name = "MSDFS-ATTRIBUTE",
15236 .fn = run_msdfs_attribute,
15239 .name = "NTTRANS-CREATE",
15240 .fn = run_nttrans_create,
15243 .name = "NTTRANS-FSCTL",
15244 .fn = run_nttrans_fsctl,
15247 .name = "CLI_ECHO",
15248 .fn = run_cli_echo,
15251 .name = "CLI_SPLICE",
15252 .fn = run_cli_splice,
15259 .name = "STREAMERROR",
15260 .fn = run_streamerror,
15263 .name = "NOTIFY-BENCH",
15264 .fn = run_notify_bench,
15267 .name = "NOTIFY-BENCH2",
15268 .fn = run_notify_bench2,
15271 .name = "NOTIFY-BENCH3",
15272 .fn = run_notify_bench3,
15275 .name = "BAD-NBT-SESSION",
15276 .fn = run_bad_nbt_session,
15279 .name = "IGN-BAD-NEGPROT",
15280 .fn = run_ign_bad_negprot,
15283 .name = "SMB-ANY-CONNECT",
15284 .fn = run_smb_any_connect,
15287 .name = "NOTIFY-ONLINE",
15288 .fn = run_notify_online,
15291 .name = "SMB2-BASIC",
15292 .fn = run_smb2_basic,
15295 .name = "SMB2-NEGPROT",
15296 .fn = run_smb2_negprot,
15299 .name = "SMB2-ANONYMOUS",
15300 .fn = run_smb2_anonymous,
15303 .name = "SMB2-SESSION-RECONNECT",
15304 .fn = run_smb2_session_reconnect,
15307 .name = "SMB2-TCON-DEPENDENCE",
15308 .fn = run_smb2_tcon_dependence,
15311 .name = "SMB2-MULTI-CHANNEL",
15312 .fn = run_smb2_multi_channel,
15315 .name = "SMB2-SESSION-REAUTH",
15316 .fn = run_smb2_session_reauth,
15319 .name = "SMB2-FTRUNCATE",
15320 .fn = run_smb2_ftruncate,
15323 .name = "SMB2-DIR-FSYNC",
15324 .fn = run_smb2_dir_fsync,
15327 .name = "SMB2-PATH-SLASH",
15328 .fn = run_smb2_path_slash,
15331 .name = "SMB1-SYSTEM-SECURITY",
15332 .fn = run_smb1_system_security,
15335 .name = "SMB2-SACL",
15336 .fn = run_smb2_sacl,
15339 .name = "SMB2-QUOTA1",
15340 .fn = run_smb2_quota1,
15343 .name = "SMB2-STREAM-ACL",
15344 .fn = run_smb2_stream_acl,
15347 .name = "SMB2-LIST-DIR-ASYNC",
15348 .fn = run_list_dir_async_test,
15351 .name = "SMB2-DEL-ON-CLOSE-NONEMPTY",
15352 .fn = run_delete_on_close_non_empty,
15355 .name = "SMB2-DEL-ON-CLOSE-NONWRITE-DELETE-YES",
15356 .fn = run_delete_on_close_nonwrite_delete_yes_test,
15359 .name = "SMB2-DEL-ON-CLOSE-NONWRITE-DELETE-NO",
15360 .fn = run_delete_on_close_nonwrite_delete_no_test,
15363 .name = "SMB2-DFS-PATHS",
15364 .fn = run_smb2_dfs_paths,
15367 .name = "SMB1-DFS-PATHS",
15368 .fn = run_smb1_dfs_paths,
15371 .name = "SMB1-DFS-SEARCH-PATHS",
15372 .fn = run_smb1_dfs_search_paths,
15375 .name = "CLEANUP1",
15376 .fn = run_cleanup1,
15379 .name = "CLEANUP2",
15380 .fn = run_cleanup2,
15383 .name = "CLEANUP4",
15384 .fn = run_cleanup4,
15387 .name = "OPLOCK-CANCEL",
15388 .fn = run_oplock_cancel,
15395 .name = "LOCAL-SUBSTITUTE",
15396 .fn = run_local_substitute,
15399 .name = "LOCAL-GENCACHE",
15400 .fn = run_local_gencache,
15403 .name = "LOCAL-DBWRAP-WATCH1",
15404 .fn = run_dbwrap_watch1,
15407 .name = "LOCAL-DBWRAP-WATCH2",
15408 .fn = run_dbwrap_watch2,
15411 .name = "LOCAL-DBWRAP-WATCH3",
15412 .fn = run_dbwrap_watch3,
15415 .name = "LOCAL-DBWRAP-WATCH4",
15416 .fn = run_dbwrap_watch4,
15419 .name = "LOCAL-DBWRAP-DO-LOCKED1",
15420 .fn = run_dbwrap_do_locked1,
15423 .name = "LOCAL-MESSAGING-READ1",
15424 .fn = run_messaging_read1,
15427 .name = "LOCAL-MESSAGING-READ2",
15428 .fn = run_messaging_read2,
15431 .name = "LOCAL-MESSAGING-READ3",
15432 .fn = run_messaging_read3,
15435 .name = "LOCAL-MESSAGING-READ4",
15436 .fn = run_messaging_read4,
15439 .name = "LOCAL-MESSAGING-FDPASS1",
15440 .fn = run_messaging_fdpass1,
15443 .name = "LOCAL-MESSAGING-FDPASS2",
15444 .fn = run_messaging_fdpass2,
15447 .name = "LOCAL-MESSAGING-FDPASS2a",
15448 .fn = run_messaging_fdpass2a,
15451 .name = "LOCAL-MESSAGING-FDPASS2b",
15452 .fn = run_messaging_fdpass2b,
15455 .name = "LOCAL-MESSAGING-SEND-ALL",
15456 .fn = run_messaging_send_all,
15459 .name = "LOCAL-BASE64",
15460 .fn = run_local_base64,
15463 .name = "LOCAL-RBTREE",
15464 .fn = run_local_rbtree,
15467 .name = "LOCAL-MEMCACHE",
15468 .fn = run_local_memcache,
15471 .name = "LOCAL-STREAM-NAME",
15472 .fn = run_local_stream_name,
15475 .name = "LOCAL-STR-MATCH-MSWILD",
15476 .fn = run_str_match_mswild,
15479 .name = "LOCAL-STR-MATCH-REGEX-SUB1",
15480 .fn = run_str_match_regex_sub1,
15483 .name = "WBCLIENT-MULTI-PING",
15484 .fn = run_wbclient_multi_ping,
15487 .name = "LOCAL-string_to_sid",
15488 .fn = run_local_string_to_sid,
15491 .name = "LOCAL-sid_to_string",
15492 .fn = run_local_sid_to_string,
15495 .name = "LOCAL-binary_to_sid",
15496 .fn = run_local_binary_to_sid,
15499 .name = "LOCAL-DBTRANS",
15500 .fn = run_local_dbtrans,
15503 .name = "LOCAL-TEVENT-POLL",
15504 .fn = run_local_tevent_poll,
15507 .name = "LOCAL-CONVERT-STRING",
15508 .fn = run_local_convert_string,
15511 .name = "LOCAL-CONV-AUTH-INFO",
15512 .fn = run_local_conv_auth_info,
15515 .name = "LOCAL-hex_encode_buf",
15516 .fn = run_local_hex_encode_buf,
15519 .name = "LOCAL-IDMAP-TDB-COMMON",
15520 .fn = run_idmap_tdb_common_test,
15523 .name = "LOCAL-remove_duplicate_addrs2",
15524 .fn = run_local_remove_duplicate_addrs2,
15527 .name = "local-tdb-opener",
15528 .fn = run_local_tdb_opener,
15531 .name = "local-tdb-writer",
15532 .fn = run_local_tdb_writer,
15535 .name = "LOCAL-DBWRAP-CTDB1",
15536 .fn = run_local_dbwrap_ctdb1,
15539 .name = "LOCAL-BENCH-PTHREADPOOL",
15540 .fn = run_bench_pthreadpool,
15543 .name = "LOCAL-PTHREADPOOL-TEVENT",
15544 .fn = run_pthreadpool_tevent,
15547 .name = "LOCAL-G-LOCK1",
15551 .name = "LOCAL-G-LOCK2",
15555 .name = "LOCAL-G-LOCK3",
15559 .name = "LOCAL-G-LOCK4",
15563 .name = "LOCAL-G-LOCK4A",
15564 .fn = run_g_lock4a,
15567 .name = "LOCAL-G-LOCK5",
15571 .name = "LOCAL-G-LOCK6",
15575 .name = "LOCAL-G-LOCK7",
15579 .name = "LOCAL-G-LOCK8",
15583 .name = "LOCAL-G-LOCK-PING-PONG",
15584 .fn = run_g_lock_ping_pong,
15587 .name = "LOCAL-CANONICALIZE-PATH",
15588 .fn = run_local_canonicalize_path,
15591 .name = "LOCAL-NAMEMAP-CACHE1",
15592 .fn = run_local_namemap_cache1,
15595 .name = "LOCAL-IDMAP-CACHE1",
15596 .fn = run_local_idmap_cache1,
15599 .name = "qpathinfo-bufsize",
15600 .fn = run_qpathinfo_bufsize,
15603 .name = "hide-new-files-timeout",
15604 .fn = run_hidenewfiles,
15606 #ifdef CLUSTER_SUPPORT
15608 .name = "ctdbd-conn1",
15609 .fn = run_ctdbd_conn1,
15613 .name = "readdir-timestamp",
15614 .fn = run_readdir_timestamp,
15621 /****************************************************************************
15622 run a specified test or "ALL"
15623 ****************************************************************************/
15624 static bool run_test(const char *name)
15627 bool result = True;
15628 bool found = False;
15631 if (strequal(name,"ALL")) {
15632 for (i=0;torture_ops[i].name;i++) {
15633 run_test(torture_ops[i].name);
15638 for (i=0;torture_ops[i].name;i++) {
15639 fstr_sprintf(randomfname, "\\XX%x",
15640 (unsigned)random());
15642 if (strequal(name, torture_ops[i].name)) {
15644 printf("Running %s\n", name);
15645 if (torture_ops[i].flags & FLAG_MULTIPROC) {
15646 t = create_procs(torture_ops[i].fn, &result);
15649 printf("TEST %s FAILED!\n", name);
15652 struct timeval start;
15653 start = timeval_current();
15654 if (!torture_ops[i].fn(0)) {
15656 printf("TEST %s FAILED!\n", name);
15658 t = timeval_elapsed(&start);
15660 printf("%s took %g secs\n\n", name, t);
15665 printf("Did not find a test named %s\n", name);
15673 static void usage(void)
15677 printf("WARNING samba4 test suite is much more complete nowadays.\n");
15678 printf("Please use samba4 torture.\n\n");
15680 printf("Usage: smbtorture //server/share <options> TEST1 TEST2 ...\n");
15682 printf("\t-d debuglevel\n");
15683 printf("\t-U user%%pass\n");
15684 printf("\t-k use kerberos\n");
15685 printf("\t-N numprocs\n");
15686 printf("\t-n my_netbios_name\n");
15687 printf("\t-W workgroup\n");
15688 printf("\t-o num_operations\n");
15689 printf("\t-O socket_options\n");
15690 printf("\t-m maximum protocol\n");
15691 printf("\t-L use oplocks\n");
15692 printf("\t-c CLIENT.TXT specify client load file for NBENCH\n");
15693 printf("\t-A showall\n");
15694 printf("\t-p port\n");
15695 printf("\t-s seed\n");
15696 printf("\t-b unclist_filename specify multiple shares for multiple connections\n");
15697 printf("\t-f filename filename to test\n");
15698 printf("\t-e encrypt\n");
15701 printf("tests are:");
15702 for (i=0;torture_ops[i].name;i++) {
15703 printf(" %s", torture_ops[i].name);
15707 printf("default test is ALL\n");
15712 /****************************************************************************
15714 ****************************************************************************/
15715 int main(int argc,char *argv[])
15721 bool correct = True;
15722 TALLOC_CTX *frame = talloc_stackframe();
15723 int seed = time(NULL);
15725 #ifdef HAVE_SETBUFFER
15726 setbuffer(stdout, NULL, 0);
15729 setup_logging("smbtorture", DEBUG_STDOUT);
15734 if (is_default_dyn_CONFIGFILE()) {
15735 if(getenv("SMB_CONF_PATH")) {
15736 set_dyn_CONFIGFILE(getenv("SMB_CONF_PATH"));
15739 lp_load_global(get_dyn_CONFIGFILE());
15746 for(p = argv[1]; *p; p++)
15750 if (strncmp(argv[1], "//", 2)) {
15754 fstrcpy(host, &argv[1][2]);
15755 p = strchr_m(&host[2],'/');
15760 fstrcpy(share, p+1);
15762 fstrcpy(myname, get_myname(talloc_tos()));
15764 fprintf(stderr, "Failed to get my hostname.\n");
15768 if (*username == 0 && getenv("LOGNAME")) {
15769 fstrcpy(username,getenv("LOGNAME"));
15775 fstrcpy(workgroup, lp_workgroup());
15777 while ((opt = getopt(argc, argv, "p:hW:U:n:N:O:o:m:Ll:d:Aec:ks:b:B:f:"))
15781 port_to_use = atoi(optarg);
15784 seed = atoi(optarg);
15787 fstrcpy(workgroup,optarg);
15790 lp_set_cmdline("client max protocol", optarg);
15793 torture_nprocs = atoi(optarg);
15796 torture_numops = atoi(optarg);
15799 lp_set_cmdline("log level", optarg);
15805 use_oplocks = True;
15808 local_path = optarg;
15811 torture_showall = True;
15814 fstrcpy(myname, optarg);
15817 client_txt = optarg;
15824 use_kerberos = True;
15826 d_printf("No kerberos support compiled in\n");
15832 fstrcpy(username,optarg);
15833 p = strchr_m(username,'%');
15836 fstrcpy(password, p+1);
15841 fstrcpy(multishare_conn_fname, optarg);
15842 use_multishare_conn = True;
15845 torture_blocksize = atoi(optarg);
15848 test_filename = SMB_STRDUP(optarg);
15851 printf("Unknown option %c (%d)\n", (char)opt, opt);
15856 d_printf("using seed %d\n", seed);
15860 if(use_kerberos && !gotuser) gotpass = True;
15863 char pwd[256] = {0};
15866 rc = samba_getpass("Password:", pwd, sizeof(pwd), false, false);
15868 fstrcpy(password, pwd);
15873 printf("host=%s share=%s user=%s myname=%s\n",
15874 host, share, username, myname);
15876 torture_creds = cli_session_creds_init(frame,
15882 false, /* fallback_after_kerberos */
15883 false, /* use_ccache */
15884 false); /* password_is_nt_hash */
15885 if (torture_creds == NULL) {
15886 d_printf("cli_session_creds_init() failed.\n");
15890 if (argc == optind) {
15891 correct = run_test("ALL");
15893 for (i=optind;i<argc;i++) {
15894 if (!run_test(argv[i])) {
15900 TALLOC_FREE(frame);