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"
54 #include <gnutls/gnutls.h>
55 #include <gnutls/crypto.h>
60 fstring host, workgroup, share, password, username, myname;
61 struct cli_credentials *torture_creds;
62 static const char *sockops="TCP_NODELAY";
64 static int port_to_use=0;
65 int torture_numops=100;
66 int torture_blocksize=1024*1024;
67 static int procnum; /* records process count number when forking */
68 static struct cli_state *current_cli;
69 static fstring randomfname;
70 static bool use_oplocks;
71 static bool use_level_II_oplocks;
72 static const char *client_txt = "client_oplocks.txt";
73 static bool disable_spnego;
74 static bool use_kerberos;
75 static bool force_dos_errors;
76 static fstring multishare_conn_fname;
77 static bool use_multishare_conn = False;
78 static bool do_encrypt;
79 static const char *local_path = NULL;
80 static enum smb_signing_setting signing_state = SMB_SIGNING_DEFAULT;
83 bool torture_showall = False;
85 static double create_procs(bool (*fn)(int), bool *result);
87 /********************************************************************
88 Ensure a connection is encrypted.
89 ********************************************************************/
91 static bool force_cli_encryption(struct cli_state *c,
92 const char *sharename)
94 uint16_t major, minor;
95 uint32_t caplow, caphigh;
98 if (!SERVER_HAS_UNIX_CIFS(c)) {
99 d_printf("Encryption required and "
100 "server that doesn't support "
101 "UNIX extensions - failing connect\n");
105 status = cli_unix_extensions_version(c, &major, &minor, &caplow,
107 if (!NT_STATUS_IS_OK(status)) {
108 d_printf("Encryption required and "
109 "can't get UNIX CIFS extensions "
110 "version from server: %s\n", nt_errstr(status));
114 if (!(caplow & CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP)) {
115 d_printf("Encryption required and "
116 "share %s doesn't support "
117 "encryption.\n", sharename);
121 status = cli_smb1_setup_encryption(c, torture_creds);
122 if (!NT_STATUS_IS_OK(status)) {
123 d_printf("Encryption required and "
124 "setup failed with error %s.\n",
133 static struct cli_state *open_nbt_connection(void)
139 if (disable_spnego) {
140 flags |= CLI_FULL_CONNECTION_DONT_SPNEGO;
144 flags |= CLI_FULL_CONNECTION_OPLOCKS;
147 if (use_level_II_oplocks) {
148 flags |= CLI_FULL_CONNECTION_LEVEL_II_OPLOCKS;
151 if (force_dos_errors) {
152 flags |= CLI_FULL_CONNECTION_FORCE_DOS_ERRORS;
155 status = cli_connect_nb(host, NULL, port_to_use, 0x20, myname,
156 signing_state, flags, &c);
157 if (!NT_STATUS_IS_OK(status)) {
158 printf("Failed to connect with %s. Error %s\n", host, nt_errstr(status) );
162 cli_set_timeout(c, 120000); /* set a really long timeout (2 minutes) */
167 /****************************************************************************
168 Send a corrupt session request. See rfc1002.txt 4.3 and 4.3.2.
169 ****************************************************************************/
171 static bool cli_bad_session_request(int fd,
172 struct nmb_name *calling, struct nmb_name *called)
181 uint8_t message_type;
183 struct tevent_context *ev;
184 struct tevent_req *req;
186 frame = talloc_stackframe();
188 iov[0].iov_base = len_buf;
189 iov[0].iov_len = sizeof(len_buf);
191 /* put in the destination name */
193 iov[1].iov_base = name_mangle(talloc_tos(), called->name,
195 if (iov[1].iov_base == NULL) {
198 iov[1].iov_len = name_len((unsigned char *)iov[1].iov_base,
199 talloc_get_size(iov[1].iov_base));
203 iov[2].iov_base = name_mangle(talloc_tos(), calling->name,
205 if (iov[2].iov_base == NULL) {
208 iov[2].iov_len = name_len((unsigned char *)iov[2].iov_base,
209 talloc_get_size(iov[2].iov_base));
211 /* Deliberately corrupt the name len (first byte) */
212 *((uint8_t *)iov[2].iov_base) = 100;
214 /* send a session request (RFC 1002) */
215 /* setup the packet length
216 * Remove four bytes from the length count, since the length
217 * field in the NBT Session Service header counts the number
218 * of bytes which follow. The cli_send_smb() function knows
219 * about this and accounts for those four bytes.
223 _smb_setlen(len_buf, iov[1].iov_len + iov[2].iov_len);
224 SCVAL(len_buf,0,0x81);
226 len = write_data_iov(fd, iov, 3);
231 ev = samba_tevent_context_init(frame);
235 req = read_smb_send(frame, ev, fd);
239 if (!tevent_req_poll(req, ev)) {
242 len = read_smb_recv(req, talloc_tos(), &inbuf, &err);
249 message_type = CVAL(inbuf, 0);
250 if (message_type != 0x83) {
251 d_fprintf(stderr, "Expected msg type 0x83, got 0x%2.2x\n",
256 if (smb_len(inbuf) != 1) {
257 d_fprintf(stderr, "Expected smb_len 1, got %d\n",
258 (int)smb_len(inbuf));
262 error = CVAL(inbuf, 4);
264 d_fprintf(stderr, "Expected error 0x82, got %d\n",
275 /* Insert a NULL at the first separator of the given path and return a pointer
276 * to the remainder of the string.
279 terminate_path_at_separator(char * path)
287 if ((p = strchr_m(path, '/'))) {
292 if ((p = strchr_m(path, '\\'))) {
302 parse a //server/share type UNC name
304 bool smbcli_parse_unc(const char *unc_name, TALLOC_CTX *mem_ctx,
305 char **hostname, char **sharename)
309 *hostname = *sharename = NULL;
311 if (strncmp(unc_name, "\\\\", 2) &&
312 strncmp(unc_name, "//", 2)) {
316 *hostname = talloc_strdup(mem_ctx, &unc_name[2]);
317 p = terminate_path_at_separator(*hostname);
320 *sharename = talloc_strdup(mem_ctx, p);
321 terminate_path_at_separator(*sharename);
324 if (*hostname && *sharename) {
328 TALLOC_FREE(*hostname);
329 TALLOC_FREE(*sharename);
333 static bool torture_open_connection_share(struct cli_state **c,
334 const char *hostname,
335 const char *sharename,
340 status = cli_full_connection_creds(c,
350 if (!NT_STATUS_IS_OK(status)) {
351 printf("failed to open share connection: //%s/%s port:%d - %s\n",
352 hostname, sharename, port_to_use, nt_errstr(status));
356 cli_set_timeout(*c, 120000); /* set a really long timeout (2 minutes) */
359 return force_cli_encryption(*c,
365 bool torture_open_connection_flags(struct cli_state **c, int conn_index, int flags)
367 char **unc_list = NULL;
368 int num_unc_names = 0;
371 if (use_multishare_conn==True) {
373 unc_list = file_lines_load(multishare_conn_fname, &num_unc_names, 0, NULL);
374 if (!unc_list || num_unc_names <= 0) {
375 printf("Failed to load unc names list from '%s'\n", multishare_conn_fname);
379 if (!smbcli_parse_unc(unc_list[conn_index % num_unc_names],
381 printf("Failed to parse UNC name %s\n",
382 unc_list[conn_index % num_unc_names]);
383 TALLOC_FREE(unc_list);
387 result = torture_open_connection_share(c, h, s, flags);
389 /* h, s were copied earlier */
390 TALLOC_FREE(unc_list);
394 return torture_open_connection_share(c, host, share, flags);
397 bool torture_open_connection(struct cli_state **c, int conn_index)
399 int flags = CLI_FULL_CONNECTION_FORCE_SMB1;
402 flags |= CLI_FULL_CONNECTION_OPLOCKS;
404 if (use_level_II_oplocks) {
405 flags |= CLI_FULL_CONNECTION_LEVEL_II_OPLOCKS;
408 return torture_open_connection_flags(c, conn_index, flags);
411 bool torture_init_connection(struct cli_state **pcli)
413 struct cli_state *cli;
415 cli = open_nbt_connection();
424 bool torture_cli_session_setup2(struct cli_state *cli, uint16_t *new_vuid)
426 uint16_t old_vuid = cli_state_get_uid(cli);
430 cli_state_set_uid(cli, 0);
431 status = cli_session_setup_creds(cli, torture_creds);
432 ret = NT_STATUS_IS_OK(status);
433 *new_vuid = cli_state_get_uid(cli);
434 cli_state_set_uid(cli, old_vuid);
439 bool torture_close_connection(struct cli_state *c)
444 status = cli_tdis(c);
445 if (!NT_STATUS_IS_OK(status)) {
446 printf("tdis failed (%s)\n", nt_errstr(status));
456 /* check if the server produced the expected dos or nt error code */
457 static bool check_both_error(int line, NTSTATUS status,
458 uint8_t eclass, uint32_t ecode, NTSTATUS nterr)
460 if (NT_STATUS_IS_DOS(status)) {
464 /* Check DOS error */
465 cclass = NT_STATUS_DOS_CLASS(status);
466 num = NT_STATUS_DOS_CODE(status);
468 if (eclass != cclass || ecode != num) {
469 printf("unexpected error code class=%d code=%d\n",
470 (int)cclass, (int)num);
471 printf(" expected %d/%d %s (line=%d)\n",
472 (int)eclass, (int)ecode, nt_errstr(nterr), line);
477 if (!NT_STATUS_EQUAL(nterr, status)) {
478 printf("unexpected error code %s\n",
480 printf(" expected %s (line=%d)\n",
481 nt_errstr(nterr), line);
490 /* check if the server produced the expected error code */
491 static bool check_error(int line, NTSTATUS status,
492 uint8_t eclass, uint32_t ecode, NTSTATUS nterr)
494 if (NT_STATUS_IS_DOS(status)) {
498 /* Check DOS error */
500 cclass = NT_STATUS_DOS_CLASS(status);
501 num = NT_STATUS_DOS_CODE(status);
503 if (eclass != cclass || ecode != num) {
504 printf("unexpected error code class=%d code=%d\n",
505 (int)cclass, (int)num);
506 printf(" expected %d/%d %s (line=%d)\n",
507 (int)eclass, (int)ecode, nt_errstr(nterr),
515 if (NT_STATUS_V(nterr) != NT_STATUS_V(status)) {
516 printf("unexpected error code %s\n",
518 printf(" expected %s (line=%d)\n", nt_errstr(nterr),
528 static bool wait_lock(struct cli_state *c, int fnum, uint32_t offset, uint32_t len)
532 status = cli_lock32(c, fnum, offset, len, -1, WRITE_LOCK);
534 while (!NT_STATUS_IS_OK(status)) {
535 if (!check_both_error(__LINE__, status, ERRDOS,
536 ERRlock, NT_STATUS_LOCK_NOT_GRANTED)) {
540 status = cli_lock32(c, fnum, offset, len, -1, WRITE_LOCK);
547 static bool rw_torture(struct cli_state *c)
549 const char *lockfname = "\\torture.lck";
553 pid_t pid2, pid = getpid();
560 memset(buf, '\0', sizeof(buf));
562 status = cli_openx(c, lockfname, O_RDWR | O_CREAT | O_EXCL,
564 if (!NT_STATUS_IS_OK(status)) {
565 status = cli_openx(c, lockfname, O_RDWR, DENY_NONE, &fnum2);
567 if (!NT_STATUS_IS_OK(status)) {
568 printf("open of %s failed (%s)\n",
569 lockfname, nt_errstr(status));
573 for (i=0;i<torture_numops;i++) {
574 unsigned n = (unsigned)sys_random()%10;
577 printf("%d\r", i); fflush(stdout);
579 slprintf(fname, sizeof(fstring) - 1, "\\torture.%u", n);
581 if (!wait_lock(c, fnum2, n*sizeof(int), sizeof(int))) {
585 status = cli_openx(c, fname, O_RDWR | O_CREAT | O_TRUNC,
587 if (!NT_STATUS_IS_OK(status)) {
588 printf("open failed (%s)\n", nt_errstr(status));
593 status = cli_writeall(c, fnum, 0, (uint8_t *)&pid, 0,
595 if (!NT_STATUS_IS_OK(status)) {
596 printf("write failed (%s)\n", nt_errstr(status));
601 status = cli_writeall(c, fnum, 0, (uint8_t *)buf,
602 sizeof(pid)+(j*sizeof(buf)),
604 if (!NT_STATUS_IS_OK(status)) {
605 printf("write failed (%s)\n",
613 status = cli_read(c, fnum, (char *)&pid2, 0, sizeof(pid),
615 if (!NT_STATUS_IS_OK(status)) {
616 printf("read failed (%s)\n", nt_errstr(status));
618 } else if (nread != sizeof(pid)) {
619 printf("read/write compare failed: "
620 "recv %ld req %ld\n", (unsigned long)nread,
621 (unsigned long)sizeof(pid));
626 printf("data corruption!\n");
630 status = cli_close(c, fnum);
631 if (!NT_STATUS_IS_OK(status)) {
632 printf("close failed (%s)\n", nt_errstr(status));
636 status = cli_unlink(c, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
637 if (!NT_STATUS_IS_OK(status)) {
638 printf("unlink failed (%s)\n", nt_errstr(status));
642 status = cli_unlock(c, fnum2, n*sizeof(int), sizeof(int));
643 if (!NT_STATUS_IS_OK(status)) {
644 printf("unlock failed (%s)\n", nt_errstr(status));
650 cli_unlink(c, lockfname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
657 static bool run_torture(int dummy)
659 struct cli_state *cli;
664 smbXcli_conn_set_sockopt(cli->conn, sockops);
666 ret = rw_torture(cli);
668 if (!torture_close_connection(cli)) {
675 static bool rw_torture3(struct cli_state *c, char *lockfname)
677 uint16_t fnum = (uint16_t)-1;
682 unsigned countprev = 0;
685 NTSTATUS status = NT_STATUS_OK;
688 for (i = 0; i < sizeof(buf); i += sizeof(uint32_t))
690 SIVAL(buf, i, sys_random());
697 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
698 if (!NT_STATUS_IS_OK(status)) {
699 printf("unlink failed (%s) (normal, this file should "
700 "not exist)\n", nt_errstr(status));
703 status = cli_openx(c, lockfname, O_RDWR | O_CREAT | O_EXCL,
705 if (!NT_STATUS_IS_OK(status)) {
706 printf("first open read/write of %s failed (%s)\n",
707 lockfname, nt_errstr(status));
713 for (i = 0; i < 500 && fnum == (uint16_t)-1; i++)
715 status = cli_openx(c, lockfname, O_RDONLY,
717 if (NT_STATUS_IS_OK(status)) {
722 if (!NT_STATUS_IS_OK(status)) {
723 printf("second open read-only of %s failed (%s)\n",
724 lockfname, nt_errstr(status));
730 for (count = 0; count < sizeof(buf); count += sent)
732 if (count >= countprev) {
733 printf("%d %8d\r", i, count);
736 countprev += (sizeof(buf) / 20);
741 sent = ((unsigned)sys_random()%(20))+ 1;
742 if (sent > sizeof(buf) - count)
744 sent = sizeof(buf) - count;
747 status = cli_writeall(c, fnum, 0, (uint8_t *)buf+count,
749 if (!NT_STATUS_IS_OK(status)) {
750 printf("write failed (%s)\n",
757 status = cli_read(c, fnum, buf_rd+count, count,
758 sizeof(buf)-count, &sent);
759 if(!NT_STATUS_IS_OK(status)) {
760 printf("read failed offset:%d size:%ld (%s)\n",
761 count, (unsigned long)sizeof(buf)-count,
765 } else if (sent > 0) {
766 if (memcmp(buf_rd+count, buf+count, sent) != 0)
768 printf("read/write compare failed\n");
769 printf("offset: %d req %ld recvd %ld\n", count, (unsigned long)sizeof(buf)-count, (unsigned long)sent);
778 status = cli_close(c, fnum);
779 if (!NT_STATUS_IS_OK(status)) {
780 printf("close failed (%s)\n", nt_errstr(status));
787 static bool rw_torture2(struct cli_state *c1, struct cli_state *c2)
789 const char *lockfname = "\\torture2.lck";
799 status = cli_unlink(c1, lockfname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
800 if (!NT_STATUS_IS_OK(status)) {
801 printf("unlink failed (%s) (normal, this file should not exist)\n", nt_errstr(status));
804 status = cli_openx(c1, lockfname, O_RDWR | O_CREAT | O_EXCL,
806 if (!NT_STATUS_IS_OK(status)) {
807 printf("first open read/write of %s failed (%s)\n",
808 lockfname, nt_errstr(status));
812 status = cli_openx(c2, lockfname, O_RDONLY, DENY_NONE, &fnum2);
813 if (!NT_STATUS_IS_OK(status)) {
814 printf("second open read-only of %s failed (%s)\n",
815 lockfname, nt_errstr(status));
816 cli_close(c1, fnum1);
820 for (i = 0; i < torture_numops; i++)
822 size_t buf_size = ((unsigned)sys_random()%(sizeof(buf)-1))+ 1;
824 printf("%d\r", i); fflush(stdout);
827 generate_random_buffer((unsigned char *)buf, buf_size);
829 status = cli_writeall(c1, fnum1, 0, (uint8_t *)buf, 0,
831 if (!NT_STATUS_IS_OK(status)) {
832 printf("write failed (%s)\n", nt_errstr(status));
837 status = cli_read(c2, fnum2, buf_rd, 0, buf_size, &bytes_read);
838 if(!NT_STATUS_IS_OK(status)) {
839 printf("read failed (%s)\n", nt_errstr(status));
842 } else if (bytes_read != buf_size) {
843 printf("read failed\n");
844 printf("read %ld, expected %ld\n",
845 (unsigned long)bytes_read,
846 (unsigned long)buf_size);
851 if (memcmp(buf_rd, buf, buf_size) != 0)
853 printf("read/write compare failed\n");
859 status = cli_close(c2, fnum2);
860 if (!NT_STATUS_IS_OK(status)) {
861 printf("close failed (%s)\n", nt_errstr(status));
865 status = cli_close(c1, fnum1);
866 if (!NT_STATUS_IS_OK(status)) {
867 printf("close failed (%s)\n", nt_errstr(status));
871 status = cli_unlink(c1, lockfname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
872 if (!NT_STATUS_IS_OK(status)) {
873 printf("unlink failed (%s)\n", nt_errstr(status));
880 static bool run_readwritetest(int dummy)
882 struct cli_state *cli1, *cli2;
883 bool test1, test2 = False;
885 if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
888 smbXcli_conn_set_sockopt(cli1->conn, sockops);
889 smbXcli_conn_set_sockopt(cli2->conn, sockops);
891 printf("starting readwritetest\n");
893 test1 = rw_torture2(cli1, cli2);
894 printf("Passed readwritetest v1: %s\n", BOOLSTR(test1));
897 test2 = rw_torture2(cli1, cli1);
898 printf("Passed readwritetest v2: %s\n", BOOLSTR(test2));
901 if (!torture_close_connection(cli1)) {
905 if (!torture_close_connection(cli2)) {
909 return (test1 && test2);
912 static bool run_readwritemulti(int dummy)
914 struct cli_state *cli;
919 smbXcli_conn_set_sockopt(cli->conn, sockops);
921 printf("run_readwritemulti: fname %s\n", randomfname);
922 test = rw_torture3(cli, randomfname);
924 if (!torture_close_connection(cli)) {
931 static bool run_readwritelarge_internal(void)
933 static struct cli_state *cli1;
935 const char *lockfname = "\\large.dat";
941 if (!torture_open_connection(&cli1, 0)) {
944 smbXcli_conn_set_sockopt(cli1->conn, sockops);
945 memset(buf,'\0',sizeof(buf));
947 printf("starting readwritelarge_internal\n");
949 cli_unlink(cli1, lockfname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
951 status = cli_openx(cli1, lockfname, O_RDWR | O_CREAT | O_EXCL,
953 if (!NT_STATUS_IS_OK(status)) {
954 printf("open read/write of %s failed (%s)\n", lockfname, nt_errstr(status));
958 cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 0, sizeof(buf), NULL);
960 status = cli_qfileinfo_basic(cli1, fnum1, NULL, &fsize, NULL, NULL,
962 if (!NT_STATUS_IS_OK(status)) {
963 printf("qfileinfo failed (%s)\n", nt_errstr(status));
967 if (fsize == sizeof(buf))
968 printf("readwritelarge_internal test 1 succeeded (size = %lx)\n",
969 (unsigned long)fsize);
971 printf("readwritelarge_internal test 1 failed (size = %lx)\n",
972 (unsigned long)fsize);
976 status = cli_close(cli1, fnum1);
977 if (!NT_STATUS_IS_OK(status)) {
978 printf("close failed (%s)\n", nt_errstr(status));
982 status = cli_unlink(cli1, lockfname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
983 if (!NT_STATUS_IS_OK(status)) {
984 printf("unlink failed (%s)\n", nt_errstr(status));
988 status = cli_openx(cli1, lockfname, O_RDWR | O_CREAT | O_EXCL,
990 if (!NT_STATUS_IS_OK(status)) {
991 printf("open read/write of %s failed (%s)\n", lockfname, nt_errstr(status));
995 cli_smbwrite(cli1, fnum1, buf, 0, sizeof(buf), NULL);
997 status = cli_qfileinfo_basic(cli1, fnum1, NULL, &fsize, NULL, NULL,
999 if (!NT_STATUS_IS_OK(status)) {
1000 printf("qfileinfo failed (%s)\n", nt_errstr(status));
1004 if (fsize == sizeof(buf))
1005 printf("readwritelarge_internal test 2 succeeded (size = %lx)\n",
1006 (unsigned long)fsize);
1008 printf("readwritelarge_internal test 2 failed (size = %lx)\n",
1009 (unsigned long)fsize);
1013 status = cli_close(cli1, fnum1);
1014 if (!NT_STATUS_IS_OK(status)) {
1015 printf("close failed (%s)\n", nt_errstr(status));
1019 if (!torture_close_connection(cli1)) {
1025 static bool run_readwritelarge(int dummy)
1027 return run_readwritelarge_internal();
1030 static bool run_readwritelarge_signtest(int dummy)
1033 signing_state = SMB_SIGNING_REQUIRED;
1034 ret = run_readwritelarge_internal();
1035 signing_state = SMB_SIGNING_DEFAULT;
1042 #define ival(s) strtol(s, NULL, 0)
1044 /* run a test that simulates an approximate netbench client load */
1045 static bool run_netbench(int client)
1047 struct cli_state *cli;
1052 const char *params[20];
1053 bool correct = True;
1059 smbXcli_conn_set_sockopt(cli->conn, sockops);
1063 slprintf(cname,sizeof(cname)-1, "client%d", client);
1065 f = fopen(client_txt, "r");
1072 while (fgets(line, sizeof(line)-1, f)) {
1076 line[strlen(line)-1] = 0;
1078 /* printf("[%d] %s\n", line_count, line); */
1080 all_string_sub(line,"client1", cname, sizeof(line));
1082 /* parse the command parameters */
1083 params[0] = strtok_r(line, " ", &saveptr);
1085 while (params[i]) params[++i] = strtok_r(NULL, " ", &saveptr);
1089 if (i < 2) continue;
1091 if (!strncmp(params[0],"SMB", 3)) {
1092 printf("ERROR: You are using a dbench 1 load file\n");
1096 if (!strcmp(params[0],"NTCreateX")) {
1097 nb_createx(params[1], ival(params[2]), ival(params[3]),
1099 } else if (!strcmp(params[0],"Close")) {
1100 nb_close(ival(params[1]));
1101 } else if (!strcmp(params[0],"Rename")) {
1102 nb_rename(params[1], params[2]);
1103 } else if (!strcmp(params[0],"Unlink")) {
1104 nb_unlink(params[1]);
1105 } else if (!strcmp(params[0],"Deltree")) {
1106 nb_deltree(params[1]);
1107 } else if (!strcmp(params[0],"Rmdir")) {
1108 nb_rmdir(params[1]);
1109 } else if (!strcmp(params[0],"QUERY_PATH_INFORMATION")) {
1110 nb_qpathinfo(params[1]);
1111 } else if (!strcmp(params[0],"QUERY_FILE_INFORMATION")) {
1112 nb_qfileinfo(ival(params[1]));
1113 } else if (!strcmp(params[0],"QUERY_FS_INFORMATION")) {
1114 nb_qfsinfo(ival(params[1]));
1115 } else if (!strcmp(params[0],"FIND_FIRST")) {
1116 nb_findfirst(params[1]);
1117 } else if (!strcmp(params[0],"WriteX")) {
1118 nb_writex(ival(params[1]),
1119 ival(params[2]), ival(params[3]), ival(params[4]));
1120 } else if (!strcmp(params[0],"ReadX")) {
1121 nb_readx(ival(params[1]),
1122 ival(params[2]), ival(params[3]), ival(params[4]));
1123 } else if (!strcmp(params[0],"Flush")) {
1124 nb_flush(ival(params[1]));
1126 printf("Unknown operation %s\n", params[0]);
1134 if (!torture_close_connection(cli)) {
1142 /* run a test that simulates an approximate netbench client load */
1143 static bool run_nbench(int dummy)
1146 bool correct = True;
1148 nbio_shmem(torture_nprocs);
1152 signal(SIGALRM, nb_alarm);
1154 t = create_procs(run_netbench, &correct);
1157 printf("\nThroughput %g MB/sec\n",
1158 1.0e-6 * nbio_total() / t);
1164 This test checks for two things:
1166 1) correct support for retaining locks over a close (ie. the server
1167 must not use posix semantics)
1168 2) support for lock timeouts
1170 static bool run_locktest1(int dummy)
1172 struct cli_state *cli1, *cli2;
1173 const char *fname = "\\lockt1.lck";
1174 uint16_t fnum1, fnum2, fnum3;
1176 unsigned lock_timeout;
1179 if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
1182 smbXcli_conn_set_sockopt(cli1->conn, sockops);
1183 smbXcli_conn_set_sockopt(cli2->conn, sockops);
1185 printf("starting locktest1\n");
1187 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1189 status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
1191 if (!NT_STATUS_IS_OK(status)) {
1192 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
1196 status = cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum2);
1197 if (!NT_STATUS_IS_OK(status)) {
1198 printf("open2 of %s failed (%s)\n", fname, nt_errstr(status));
1202 status = cli_openx(cli2, fname, O_RDWR, DENY_NONE, &fnum3);
1203 if (!NT_STATUS_IS_OK(status)) {
1204 printf("open3 of %s failed (%s)\n", fname, nt_errstr(status));
1208 status = cli_lock32(cli1, fnum1, 0, 4, 0, WRITE_LOCK);
1209 if (!NT_STATUS_IS_OK(status)) {
1210 printf("lock1 failed (%s)\n", nt_errstr(status));
1214 status = cli_lock32(cli2, fnum3, 0, 4, 0, WRITE_LOCK);
1215 if (NT_STATUS_IS_OK(status)) {
1216 printf("lock2 succeeded! This is a locking bug\n");
1219 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1220 NT_STATUS_LOCK_NOT_GRANTED)) {
1225 lock_timeout = (1 + (random() % 20));
1226 printf("Testing lock timeout with timeout=%u\n", lock_timeout);
1228 status = cli_lock32(cli2, fnum3, 0, 4, lock_timeout * 1000, WRITE_LOCK);
1229 if (NT_STATUS_IS_OK(status)) {
1230 printf("lock3 succeeded! This is a locking bug\n");
1233 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1234 NT_STATUS_FILE_LOCK_CONFLICT)) {
1240 if (ABS(t2 - t1) < lock_timeout-1) {
1241 printf("error: This server appears not to support timed lock requests\n");
1244 printf("server slept for %u seconds for a %u second timeout\n",
1245 (unsigned int)(t2-t1), lock_timeout);
1247 status = cli_close(cli1, fnum2);
1248 if (!NT_STATUS_IS_OK(status)) {
1249 printf("close1 failed (%s)\n", nt_errstr(status));
1253 status = cli_lock32(cli2, fnum3, 0, 4, 0, WRITE_LOCK);
1254 if (NT_STATUS_IS_OK(status)) {
1255 printf("lock4 succeeded! This is a locking bug\n");
1258 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1259 NT_STATUS_FILE_LOCK_CONFLICT)) {
1264 status = cli_close(cli1, fnum1);
1265 if (!NT_STATUS_IS_OK(status)) {
1266 printf("close2 failed (%s)\n", nt_errstr(status));
1270 status = cli_close(cli2, fnum3);
1271 if (!NT_STATUS_IS_OK(status)) {
1272 printf("close3 failed (%s)\n", nt_errstr(status));
1276 status = cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1277 if (!NT_STATUS_IS_OK(status)) {
1278 printf("unlink failed (%s)\n", nt_errstr(status));
1283 if (!torture_close_connection(cli1)) {
1287 if (!torture_close_connection(cli2)) {
1291 printf("Passed locktest1\n");
1296 this checks to see if a secondary tconx can use open files from an
1299 static bool run_tcon_test(int dummy)
1301 static struct cli_state *cli;
1302 const char *fname = "\\tcontest.tmp";
1304 uint32_t cnum1, cnum2, cnum3;
1305 struct smbXcli_tcon *orig_tcon = NULL;
1306 uint16_t vuid1, vuid2;
1311 memset(buf, '\0', sizeof(buf));
1313 if (!torture_open_connection(&cli, 0)) {
1316 smbXcli_conn_set_sockopt(cli->conn, sockops);
1318 printf("starting tcontest\n");
1320 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1322 status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
1323 if (!NT_STATUS_IS_OK(status)) {
1324 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
1328 cnum1 = cli_state_get_tid(cli);
1329 vuid1 = cli_state_get_uid(cli);
1331 status = cli_writeall(cli, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
1332 if (!NT_STATUS_IS_OK(status)) {
1333 printf("initial write failed (%s)", nt_errstr(status));
1337 orig_tcon = cli_state_save_tcon(cli);
1338 if (orig_tcon == NULL) {
1342 status = cli_tree_connect_creds(cli, share, "?????", torture_creds);
1343 if (!NT_STATUS_IS_OK(status)) {
1344 printf("%s refused 2nd tree connect (%s)\n", host,
1350 cnum2 = cli_state_get_tid(cli);
1351 cnum3 = MAX(cnum1, cnum2) + 1; /* any invalid number */
1352 vuid2 = cli_state_get_uid(cli) + 1;
1354 /* try a write with the wrong tid */
1355 cli_state_set_tid(cli, cnum2);
1357 status = cli_writeall(cli, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
1358 if (NT_STATUS_IS_OK(status)) {
1359 printf("* server allows write with wrong TID\n");
1362 printf("server fails write with wrong TID : %s\n",
1367 /* try a write with an invalid tid */
1368 cli_state_set_tid(cli, cnum3);
1370 status = cli_writeall(cli, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
1371 if (NT_STATUS_IS_OK(status)) {
1372 printf("* server allows write with invalid TID\n");
1375 printf("server fails write with invalid TID : %s\n",
1379 /* try a write with an invalid vuid */
1380 cli_state_set_uid(cli, vuid2);
1381 cli_state_set_tid(cli, cnum1);
1383 status = cli_writeall(cli, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
1384 if (NT_STATUS_IS_OK(status)) {
1385 printf("* server allows write with invalid VUID\n");
1388 printf("server fails write with invalid VUID : %s\n",
1392 cli_state_set_tid(cli, cnum1);
1393 cli_state_set_uid(cli, vuid1);
1395 status = cli_close(cli, fnum1);
1396 if (!NT_STATUS_IS_OK(status)) {
1397 printf("close failed (%s)\n", nt_errstr(status));
1401 cli_state_set_tid(cli, cnum2);
1403 status = cli_tdis(cli);
1404 if (!NT_STATUS_IS_OK(status)) {
1405 printf("secondary tdis failed (%s)\n", nt_errstr(status));
1409 cli_state_restore_tcon(cli, orig_tcon);
1411 cli_state_set_tid(cli, cnum1);
1413 if (!torture_close_connection(cli)) {
1422 checks for old style tcon support
1424 static bool run_tcon2_test(int dummy)
1426 static struct cli_state *cli;
1427 uint16_t cnum, max_xmit;
1431 if (!torture_open_connection(&cli, 0)) {
1434 smbXcli_conn_set_sockopt(cli->conn, sockops);
1436 printf("starting tcon2 test\n");
1438 if (asprintf(&service, "\\\\%s\\%s", host, share) == -1) {
1442 status = cli_raw_tcon(cli, service, password, "?????", &max_xmit, &cnum);
1446 if (!NT_STATUS_IS_OK(status)) {
1447 printf("tcon2 failed : %s\n", nt_errstr(status));
1449 printf("tcon OK : max_xmit=%d cnum=%d\n",
1450 (int)max_xmit, (int)cnum);
1453 if (!torture_close_connection(cli)) {
1457 printf("Passed tcon2 test\n");
1461 static bool tcon_devtest(struct cli_state *cli,
1462 const char *myshare, const char *devtype,
1463 const char *return_devtype,
1464 NTSTATUS expected_error)
1469 status = cli_tree_connect_creds(cli, myshare, devtype, torture_creds);
1471 if (NT_STATUS_IS_OK(expected_error)) {
1472 if (NT_STATUS_IS_OK(status)) {
1473 if (return_devtype != NULL &&
1474 strequal(cli->dev, return_devtype)) {
1477 printf("tconX to share %s with type %s "
1478 "succeeded but returned the wrong "
1479 "device type (got [%s] but should have got [%s])\n",
1480 myshare, devtype, cli->dev, return_devtype);
1484 printf("tconX to share %s with type %s "
1485 "should have succeeded but failed\n",
1491 if (NT_STATUS_IS_OK(status)) {
1492 printf("tconx to share %s with type %s "
1493 "should have failed but succeeded\n",
1497 if (NT_STATUS_EQUAL(status, expected_error)) {
1500 printf("Returned unexpected error\n");
1509 checks for correct tconX support
1511 static bool run_tcon_devtype_test(int dummy)
1513 static struct cli_state *cli1 = NULL;
1514 int flags = CLI_FULL_CONNECTION_FORCE_SMB1;
1518 status = cli_full_connection_creds(&cli1,
1524 NULL, /* service_type */
1529 if (!NT_STATUS_IS_OK(status)) {
1530 printf("could not open connection\n");
1534 if (!tcon_devtest(cli1, "IPC$", "A:", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1537 if (!tcon_devtest(cli1, "IPC$", "?????", "IPC", NT_STATUS_OK))
1540 if (!tcon_devtest(cli1, "IPC$", "LPT:", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1543 if (!tcon_devtest(cli1, "IPC$", "IPC", "IPC", NT_STATUS_OK))
1546 if (!tcon_devtest(cli1, "IPC$", "FOOBA", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1549 if (!tcon_devtest(cli1, share, "A:", "A:", NT_STATUS_OK))
1552 if (!tcon_devtest(cli1, share, "?????", "A:", NT_STATUS_OK))
1555 if (!tcon_devtest(cli1, share, "LPT:", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1558 if (!tcon_devtest(cli1, share, "IPC", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1561 if (!tcon_devtest(cli1, share, "FOOBA", NULL, NT_STATUS_BAD_DEVICE_TYPE))
1567 printf("Passed tcondevtest\n");
1574 This test checks that
1576 1) the server supports multiple locking contexts on the one SMB
1577 connection, distinguished by PID.
1579 2) the server correctly fails overlapping locks made by the same PID (this
1580 goes against POSIX behaviour, which is why it is tricky to implement)
1582 3) the server denies unlock requests by an incorrect client PID
1584 static bool run_locktest2(int dummy)
1586 static struct cli_state *cli;
1587 const char *fname = "\\lockt2.lck";
1588 uint16_t fnum1, fnum2, fnum3;
1589 bool correct = True;
1592 if (!torture_open_connection(&cli, 0)) {
1596 smbXcli_conn_set_sockopt(cli->conn, sockops);
1598 printf("starting locktest2\n");
1600 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1604 status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
1605 if (!NT_STATUS_IS_OK(status)) {
1606 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
1610 status = cli_openx(cli, fname, O_RDWR, DENY_NONE, &fnum2);
1611 if (!NT_STATUS_IS_OK(status)) {
1612 printf("open2 of %s failed (%s)\n", fname, nt_errstr(status));
1618 status = cli_openx(cli, fname, O_RDWR, DENY_NONE, &fnum3);
1619 if (!NT_STATUS_IS_OK(status)) {
1620 printf("open3 of %s failed (%s)\n", fname, nt_errstr(status));
1626 status = cli_lock32(cli, fnum1, 0, 4, 0, WRITE_LOCK);
1627 if (!NT_STATUS_IS_OK(status)) {
1628 printf("lock1 failed (%s)\n", nt_errstr(status));
1632 status = cli_lock32(cli, fnum1, 0, 4, 0, WRITE_LOCK);
1633 if (NT_STATUS_IS_OK(status)) {
1634 printf("WRITE lock1 succeeded! This is a locking bug\n");
1637 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1638 NT_STATUS_LOCK_NOT_GRANTED)) {
1643 status = cli_lock32(cli, fnum2, 0, 4, 0, WRITE_LOCK);
1644 if (NT_STATUS_IS_OK(status)) {
1645 printf("WRITE lock2 succeeded! This is a locking bug\n");
1648 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1649 NT_STATUS_LOCK_NOT_GRANTED)) {
1654 status = cli_lock32(cli, fnum2, 0, 4, 0, READ_LOCK);
1655 if (NT_STATUS_IS_OK(status)) {
1656 printf("READ lock2 succeeded! This is a locking bug\n");
1659 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1660 NT_STATUS_FILE_LOCK_CONFLICT)) {
1665 status = cli_lock32(cli, fnum1, 100, 4, 0, WRITE_LOCK);
1666 if (!NT_STATUS_IS_OK(status)) {
1667 printf("lock at 100 failed (%s)\n", nt_errstr(status));
1670 if (NT_STATUS_IS_OK(cli_unlock(cli, fnum1, 100, 4))) {
1671 printf("unlock at 100 succeeded! This is a locking bug\n");
1675 status = cli_unlock(cli, fnum1, 0, 4);
1676 if (NT_STATUS_IS_OK(status)) {
1677 printf("unlock1 succeeded! This is a locking bug\n");
1680 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1681 NT_STATUS_RANGE_NOT_LOCKED)) {
1686 status = cli_unlock(cli, fnum1, 0, 8);
1687 if (NT_STATUS_IS_OK(status)) {
1688 printf("unlock2 succeeded! This is a locking bug\n");
1691 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1692 NT_STATUS_RANGE_NOT_LOCKED)) {
1697 status = cli_lock32(cli, fnum3, 0, 4, 0, WRITE_LOCK);
1698 if (NT_STATUS_IS_OK(status)) {
1699 printf("lock3 succeeded! This is a locking bug\n");
1702 if (!check_both_error(__LINE__, status, ERRDOS, ERRlock,
1703 NT_STATUS_LOCK_NOT_GRANTED)) {
1710 status = cli_close(cli, fnum1);
1711 if (!NT_STATUS_IS_OK(status)) {
1712 printf("close1 failed (%s)\n", nt_errstr(status));
1716 status = cli_close(cli, fnum2);
1717 if (!NT_STATUS_IS_OK(status)) {
1718 printf("close2 failed (%s)\n", nt_errstr(status));
1722 status = cli_close(cli, fnum3);
1723 if (!NT_STATUS_IS_OK(status)) {
1724 printf("close3 failed (%s)\n", nt_errstr(status));
1728 if (!torture_close_connection(cli)) {
1732 printf("locktest2 finished\n");
1739 This test checks that
1741 1) the server supports the full offset range in lock requests
1743 static bool run_locktest3(int dummy)
1745 static struct cli_state *cli1, *cli2;
1746 const char *fname = "\\lockt3.lck";
1747 uint16_t fnum1, fnum2;
1750 bool correct = True;
1753 #define NEXT_OFFSET offset += (~(uint32_t)0) / torture_numops
1755 if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
1758 smbXcli_conn_set_sockopt(cli1->conn, sockops);
1759 smbXcli_conn_set_sockopt(cli2->conn, sockops);
1761 printf("starting locktest3\n");
1763 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1765 status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
1767 if (!NT_STATUS_IS_OK(status)) {
1768 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
1772 status = cli_openx(cli2, fname, O_RDWR, DENY_NONE, &fnum2);
1773 if (!NT_STATUS_IS_OK(status)) {
1774 printf("open2 of %s failed (%s)\n", fname, nt_errstr(status));
1778 for (offset=i=0;i<torture_numops;i++) {
1781 status = cli_lock32(cli1, fnum1, offset-1, 1, 0, WRITE_LOCK);
1782 if (!NT_STATUS_IS_OK(status)) {
1783 printf("lock1 %d failed (%s)\n",
1789 status = cli_lock32(cli2, fnum2, offset-2, 1, 0, WRITE_LOCK);
1790 if (!NT_STATUS_IS_OK(status)) {
1791 printf("lock2 %d failed (%s)\n",
1798 for (offset=i=0;i<torture_numops;i++) {
1801 status = cli_lock32(cli1, fnum1, offset-2, 1, 0, WRITE_LOCK);
1802 if (NT_STATUS_IS_OK(status)) {
1803 printf("error: lock1 %d succeeded!\n", i);
1807 status = cli_lock32(cli2, fnum2, offset-1, 1, 0, WRITE_LOCK);
1808 if (NT_STATUS_IS_OK(status)) {
1809 printf("error: lock2 %d succeeded!\n", i);
1813 status = cli_lock32(cli1, fnum1, offset-1, 1, 0, WRITE_LOCK);
1814 if (NT_STATUS_IS_OK(status)) {
1815 printf("error: lock3 %d succeeded!\n", i);
1819 status = cli_lock32(cli2, fnum2, offset-2, 1, 0, WRITE_LOCK);
1820 if (NT_STATUS_IS_OK(status)) {
1821 printf("error: lock4 %d succeeded!\n", i);
1826 for (offset=i=0;i<torture_numops;i++) {
1829 status = cli_unlock(cli1, fnum1, offset-1, 1);
1830 if (!NT_STATUS_IS_OK(status)) {
1831 printf("unlock1 %d failed (%s)\n",
1837 status = cli_unlock(cli2, fnum2, offset-2, 1);
1838 if (!NT_STATUS_IS_OK(status)) {
1839 printf("unlock2 %d failed (%s)\n",
1846 status = cli_close(cli1, fnum1);
1847 if (!NT_STATUS_IS_OK(status)) {
1848 printf("close1 failed (%s)\n", nt_errstr(status));
1852 status = cli_close(cli2, fnum2);
1853 if (!NT_STATUS_IS_OK(status)) {
1854 printf("close2 failed (%s)\n", nt_errstr(status));
1858 status = cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1859 if (!NT_STATUS_IS_OK(status)) {
1860 printf("unlink failed (%s)\n", nt_errstr(status));
1864 if (!torture_close_connection(cli1)) {
1868 if (!torture_close_connection(cli2)) {
1872 printf("finished locktest3\n");
1877 static bool test_cli_read(struct cli_state *cli, uint16_t fnum,
1878 char *buf, off_t offset, size_t size,
1879 size_t *nread, size_t expect)
1884 status = cli_read(cli, fnum, buf, offset, size, &l_nread);
1886 if(!NT_STATUS_IS_OK(status)) {
1888 } else if (l_nread != expect) {
1899 #define EXPECTED(ret, v) if ((ret) != (v)) { \
1900 printf("** "); correct = False; \
1904 looks at overlapping locks
1906 static bool run_locktest4(int dummy)
1908 static struct cli_state *cli1, *cli2;
1909 const char *fname = "\\lockt4.lck";
1910 uint16_t fnum1, fnum2, f;
1913 bool correct = True;
1916 if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
1920 smbXcli_conn_set_sockopt(cli1->conn, sockops);
1921 smbXcli_conn_set_sockopt(cli2->conn, sockops);
1923 printf("starting locktest4\n");
1925 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1927 cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
1928 cli_openx(cli2, fname, O_RDWR, DENY_NONE, &fnum2);
1930 memset(buf, 0, sizeof(buf));
1932 status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 0, sizeof(buf),
1934 if (!NT_STATUS_IS_OK(status)) {
1935 printf("Failed to create file: %s\n", nt_errstr(status));
1940 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 4, 0, WRITE_LOCK)) &&
1941 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 2, 4, 0, WRITE_LOCK));
1942 EXPECTED(ret, False);
1943 printf("the same process %s set overlapping write locks\n", ret?"can":"cannot");
1945 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 10, 4, 0, READ_LOCK)) &&
1946 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 12, 4, 0, READ_LOCK));
1947 EXPECTED(ret, True);
1948 printf("the same process %s set overlapping read locks\n", ret?"can":"cannot");
1950 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 20, 4, 0, WRITE_LOCK)) &&
1951 NT_STATUS_IS_OK(cli_lock32(cli2, fnum2, 22, 4, 0, WRITE_LOCK));
1952 EXPECTED(ret, False);
1953 printf("a different connection %s set overlapping write locks\n", ret?"can":"cannot");
1955 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 30, 4, 0, READ_LOCK)) &&
1956 NT_STATUS_IS_OK(cli_lock32(cli2, fnum2, 32, 4, 0, READ_LOCK));
1957 EXPECTED(ret, True);
1958 printf("a different connection %s set overlapping read locks\n", ret?"can":"cannot");
1960 ret = (cli_setpid(cli1, 1),
1961 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 40, 4, 0, WRITE_LOCK))) &&
1962 (cli_setpid(cli1, 2),
1963 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 42, 4, 0, WRITE_LOCK)));
1964 EXPECTED(ret, False);
1965 printf("a different pid %s set overlapping write locks\n", ret?"can":"cannot");
1967 ret = (cli_setpid(cli1, 1),
1968 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 50, 4, 0, READ_LOCK))) &&
1969 (cli_setpid(cli1, 2),
1970 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 52, 4, 0, READ_LOCK)));
1971 EXPECTED(ret, True);
1972 printf("a different pid %s set overlapping read locks\n", ret?"can":"cannot");
1974 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 60, 4, 0, READ_LOCK)) &&
1975 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 60, 4, 0, READ_LOCK));
1976 EXPECTED(ret, True);
1977 printf("the same process %s set the same read lock twice\n", ret?"can":"cannot");
1979 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 70, 4, 0, WRITE_LOCK)) &&
1980 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 70, 4, 0, WRITE_LOCK));
1981 EXPECTED(ret, False);
1982 printf("the same process %s set the same write lock twice\n", ret?"can":"cannot");
1984 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 80, 4, 0, READ_LOCK)) &&
1985 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 80, 4, 0, WRITE_LOCK));
1986 EXPECTED(ret, False);
1987 printf("the same process %s overlay a read lock with a write lock\n", ret?"can":"cannot");
1989 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 90, 4, 0, WRITE_LOCK)) &&
1990 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 90, 4, 0, READ_LOCK));
1991 EXPECTED(ret, True);
1992 printf("the same process %s overlay a write lock with a read lock\n", ret?"can":"cannot");
1994 ret = (cli_setpid(cli1, 1),
1995 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 100, 4, 0, WRITE_LOCK))) &&
1996 (cli_setpid(cli1, 2),
1997 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 100, 4, 0, READ_LOCK)));
1998 EXPECTED(ret, False);
1999 printf("a different pid %s overlay a write lock with a read lock\n", ret?"can":"cannot");
2001 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 110, 4, 0, READ_LOCK)) &&
2002 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 112, 4, 0, READ_LOCK)) &&
2003 NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 110, 6));
2004 EXPECTED(ret, False);
2005 printf("the same process %s coalesce read locks\n", ret?"can":"cannot");
2008 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 120, 4, 0, WRITE_LOCK)) &&
2009 test_cli_read(cli2, fnum2, buf, 120, 4, NULL, 4);
2010 EXPECTED(ret, False);
2011 printf("this server %s strict write locking\n", ret?"doesn't do":"does");
2013 status = cli_lock32(cli1, fnum1, 130, 4, 0, READ_LOCK);
2014 ret = NT_STATUS_IS_OK(status);
2016 status = cli_writeall(cli2, fnum2, 0, (uint8_t *)buf, 130, 4,
2018 ret = NT_STATUS_IS_OK(status);
2020 EXPECTED(ret, False);
2021 printf("this server %s strict read locking\n", ret?"doesn't do":"does");
2024 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 140, 4, 0, READ_LOCK)) &&
2025 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 140, 4, 0, READ_LOCK)) &&
2026 NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 140, 4)) &&
2027 NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 140, 4));
2028 EXPECTED(ret, True);
2029 printf("this server %s do recursive read locking\n", ret?"does":"doesn't");
2032 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 150, 4, 0, WRITE_LOCK)) &&
2033 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 150, 4, 0, READ_LOCK)) &&
2034 NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 150, 4)) &&
2035 test_cli_read(cli2, fnum2, buf, 150, 4, NULL, 4) &&
2036 !(NT_STATUS_IS_OK(cli_writeall(cli2, fnum2, 0, (uint8_t *)buf,
2038 NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 150, 4));
2039 EXPECTED(ret, True);
2040 printf("this server %s do recursive lock overlays\n", ret?"does":"doesn't");
2042 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 160, 4, 0, READ_LOCK)) &&
2043 NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 160, 4)) &&
2044 NT_STATUS_IS_OK(cli_writeall(cli2, fnum2, 0, (uint8_t *)buf,
2046 test_cli_read(cli2, fnum2, buf, 160, 4, NULL, 4);
2047 EXPECTED(ret, True);
2048 printf("the same process %s remove a read lock using write locking\n", ret?"can":"cannot");
2050 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 170, 4, 0, WRITE_LOCK)) &&
2051 NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 170, 4)) &&
2052 NT_STATUS_IS_OK(cli_writeall(cli2, fnum2, 0, (uint8_t *)buf,
2054 test_cli_read(cli2, fnum2, buf, 170, 4, NULL, 4);
2055 EXPECTED(ret, True);
2056 printf("the same process %s remove a write lock using read locking\n", ret?"can":"cannot");
2058 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 190, 4, 0, WRITE_LOCK)) &&
2059 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 190, 4, 0, READ_LOCK)) &&
2060 NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 190, 4)) &&
2061 !NT_STATUS_IS_OK(cli_writeall(cli2, fnum2, 0, (uint8_t *)buf,
2063 test_cli_read(cli2, fnum2, buf, 190, 4, NULL, 4);
2064 EXPECTED(ret, True);
2065 printf("the same process %s remove the first lock first\n", ret?"does":"doesn't");
2067 cli_close(cli1, fnum1);
2068 cli_close(cli2, fnum2);
2069 cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
2070 cli_openx(cli1, fname, O_RDWR, DENY_NONE, &f);
2071 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 8, 0, READ_LOCK)) &&
2072 NT_STATUS_IS_OK(cli_lock32(cli1, f, 0, 1, 0, READ_LOCK)) &&
2073 NT_STATUS_IS_OK(cli_close(cli1, fnum1)) &&
2074 NT_STATUS_IS_OK(cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1)) &&
2075 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 7, 1, 0, WRITE_LOCK));
2077 cli_close(cli1, fnum1);
2078 EXPECTED(ret, True);
2079 printf("the server %s have the NT byte range lock bug\n", !ret?"does":"doesn't");
2082 cli_close(cli1, fnum1);
2083 cli_close(cli2, fnum2);
2084 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2085 torture_close_connection(cli1);
2086 torture_close_connection(cli2);
2088 printf("finished locktest4\n");
2093 looks at lock upgrade/downgrade.
2095 static bool run_locktest5(int dummy)
2097 static struct cli_state *cli1, *cli2;
2098 const char *fname = "\\lockt5.lck";
2099 uint16_t fnum1, fnum2, fnum3;
2102 bool correct = True;
2105 if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
2109 smbXcli_conn_set_sockopt(cli1->conn, sockops);
2110 smbXcli_conn_set_sockopt(cli2->conn, sockops);
2112 printf("starting locktest5\n");
2114 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2116 cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
2117 cli_openx(cli2, fname, O_RDWR, DENY_NONE, &fnum2);
2118 cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum3);
2120 memset(buf, 0, sizeof(buf));
2122 status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 0, sizeof(buf),
2124 if (!NT_STATUS_IS_OK(status)) {
2125 printf("Failed to create file: %s\n", nt_errstr(status));
2130 /* Check for NT bug... */
2131 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 8, 0, READ_LOCK)) &&
2132 NT_STATUS_IS_OK(cli_lock32(cli1, fnum3, 0, 1, 0, READ_LOCK));
2133 cli_close(cli1, fnum1);
2134 cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
2135 status = cli_lock32(cli1, fnum1, 7, 1, 0, WRITE_LOCK);
2136 ret = NT_STATUS_IS_OK(status);
2137 EXPECTED(ret, True);
2138 printf("this server %s the NT locking bug\n", ret ? "doesn't have" : "has");
2139 cli_close(cli1, fnum1);
2140 cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
2141 cli_unlock(cli1, fnum3, 0, 1);
2143 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 4, 0, WRITE_LOCK)) &&
2144 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 1, 1, 0, READ_LOCK));
2145 EXPECTED(ret, True);
2146 printf("the same process %s overlay a write with a read lock\n", ret?"can":"cannot");
2148 status = cli_lock32(cli2, fnum2, 0, 4, 0, READ_LOCK);
2149 ret = NT_STATUS_IS_OK(status);
2150 EXPECTED(ret, False);
2152 printf("a different process %s get a read lock on the first process lock stack\n", ret?"can":"cannot");
2154 /* Unlock the process 2 lock. */
2155 cli_unlock(cli2, fnum2, 0, 4);
2157 status = cli_lock32(cli1, fnum3, 0, 4, 0, READ_LOCK);
2158 ret = NT_STATUS_IS_OK(status);
2159 EXPECTED(ret, False);
2161 printf("the same process on a different fnum %s get a read lock\n", ret?"can":"cannot");
2163 /* Unlock the process 1 fnum3 lock. */
2164 cli_unlock(cli1, fnum3, 0, 4);
2166 /* Stack 2 more locks here. */
2167 ret = NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 4, 0, READ_LOCK)) &&
2168 NT_STATUS_IS_OK(cli_lock32(cli1, fnum1, 0, 4, 0, READ_LOCK));
2170 EXPECTED(ret, True);
2171 printf("the same process %s stack read locks\n", ret?"can":"cannot");
2173 /* Unlock the first process lock, then check this was the WRITE lock that was
2176 ret = NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 0, 4)) &&
2177 NT_STATUS_IS_OK(cli_lock32(cli2, fnum2, 0, 4, 0, READ_LOCK));
2179 EXPECTED(ret, True);
2180 printf("the first unlock removes the %s lock\n", ret?"WRITE":"READ");
2182 /* Unlock the process 2 lock. */
2183 cli_unlock(cli2, fnum2, 0, 4);
2185 /* We should have 3 stacked locks here. Ensure we need to do 3 unlocks. */
2187 ret = NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 1, 1)) &&
2188 NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 0, 4)) &&
2189 NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 0, 4));
2191 EXPECTED(ret, True);
2192 printf("the same process %s unlock the stack of 4 locks\n", ret?"can":"cannot");
2194 /* Ensure the next unlock fails. */
2195 ret = NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 0, 4));
2196 EXPECTED(ret, False);
2197 printf("the same process %s count the lock stack\n", !ret?"can":"cannot");
2199 /* Ensure connection 2 can get a write lock. */
2200 status = cli_lock32(cli2, fnum2, 0, 4, 0, WRITE_LOCK);
2201 ret = NT_STATUS_IS_OK(status);
2202 EXPECTED(ret, True);
2204 printf("a different process %s get a write lock on the unlocked stack\n", ret?"can":"cannot");
2208 cli_close(cli1, fnum1);
2209 cli_close(cli2, fnum2);
2210 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2211 if (!torture_close_connection(cli1)) {
2214 if (!torture_close_connection(cli2)) {
2218 printf("finished locktest5\n");
2224 tries the unusual lockingX locktype bits
2226 static bool run_locktest6(int dummy)
2228 static struct cli_state *cli;
2229 const char *fname[1] = { "\\lock6.txt" };
2234 if (!torture_open_connection(&cli, 0)) {
2238 smbXcli_conn_set_sockopt(cli->conn, sockops);
2240 printf("starting locktest6\n");
2243 printf("Testing %s\n", fname[i]);
2245 cli_unlink(cli, fname[i], FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2247 cli_openx(cli, fname[i], O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
2248 status = cli_locktype(cli, fnum, 0, 8, 0, LOCKING_ANDX_CHANGE_LOCKTYPE);
2249 cli_close(cli, fnum);
2250 printf("CHANGE_LOCKTYPE gave %s\n", nt_errstr(status));
2252 cli_openx(cli, fname[i], O_RDWR, DENY_NONE, &fnum);
2253 status = cli_locktype(cli, fnum, 0, 8, 0, LOCKING_ANDX_CANCEL_LOCK);
2254 cli_close(cli, fnum);
2255 printf("CANCEL_LOCK gave %s\n", nt_errstr(status));
2257 cli_unlink(cli, fname[i], FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2260 torture_close_connection(cli);
2262 printf("finished locktest6\n");
2266 static bool run_locktest7(int dummy)
2268 struct cli_state *cli1;
2269 const char *fname = "\\lockt7.lck";
2272 bool correct = False;
2276 if (!torture_open_connection(&cli1, 0)) {
2280 smbXcli_conn_set_sockopt(cli1->conn, sockops);
2282 printf("starting locktest7\n");
2284 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2286 cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
2288 memset(buf, 0, sizeof(buf));
2290 status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 0, sizeof(buf),
2292 if (!NT_STATUS_IS_OK(status)) {
2293 printf("Failed to create file: %s\n", nt_errstr(status));
2297 cli_setpid(cli1, 1);
2299 status = cli_lock32(cli1, fnum1, 130, 4, 0, READ_LOCK);
2300 if (!NT_STATUS_IS_OK(status)) {
2301 printf("Unable to apply read lock on range 130:4, "
2302 "error was %s\n", nt_errstr(status));
2305 printf("pid1 successfully locked range 130:4 for READ\n");
2308 status = cli_read(cli1, fnum1, buf, 130, 4, &nread);
2309 if (!NT_STATUS_IS_OK(status)) {
2310 printf("pid1 unable to read the range 130:4, error was %s\n",
2313 } else if (nread != 4) {
2314 printf("pid1 unable to read the range 130:4, "
2315 "recv %ld req %d\n", (unsigned long)nread, 4);
2318 printf("pid1 successfully read the range 130:4\n");
2321 status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
2322 if (!NT_STATUS_IS_OK(status)) {
2323 printf("pid1 unable to write to the range 130:4, error was "
2324 "%s\n", nt_errstr(status));
2325 if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
2326 printf("Incorrect error (should be NT_STATUS_FILE_LOCK_CONFLICT)\n");
2330 printf("pid1 successfully wrote to the range 130:4 (should be denied)\n");
2334 cli_setpid(cli1, 2);
2336 status = cli_read(cli1, fnum1, buf, 130, 4, &nread);
2337 if (!NT_STATUS_IS_OK(status)) {
2338 printf("pid2 unable to read the range 130:4, error was %s\n",
2341 } else if (nread != 4) {
2342 printf("pid2 unable to read the range 130:4, "
2343 "recv %ld req %d\n", (unsigned long)nread, 4);
2346 printf("pid2 successfully read the range 130:4\n");
2349 status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
2350 if (!NT_STATUS_IS_OK(status)) {
2351 printf("pid2 unable to write to the range 130:4, error was "
2352 "%s\n", nt_errstr(status));
2353 if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
2354 printf("Incorrect error (should be NT_STATUS_FILE_LOCK_CONFLICT)\n");
2358 printf("pid2 successfully wrote to the range 130:4 (should be denied)\n");
2362 cli_setpid(cli1, 1);
2363 cli_unlock(cli1, fnum1, 130, 4);
2365 status = cli_lock32(cli1, fnum1, 130, 4, 0, WRITE_LOCK);
2366 if (!NT_STATUS_IS_OK(status)) {
2367 printf("Unable to apply write lock on range 130:4, error was %s\n", nt_errstr(status));
2370 printf("pid1 successfully locked range 130:4 for WRITE\n");
2373 status = cli_read(cli1, fnum1, buf, 130, 4, &nread);
2374 if (!NT_STATUS_IS_OK(status)) {
2375 printf("pid1 unable to read the range 130:4, error was %s\n",
2378 } else if (nread != 4) {
2379 printf("pid1 unable to read the range 130:4, "
2380 "recv %ld req %d\n", (unsigned long)nread, 4);
2383 printf("pid1 successfully read the range 130:4\n");
2386 status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
2387 if (!NT_STATUS_IS_OK(status)) {
2388 printf("pid1 unable to write to the range 130:4, error was "
2389 "%s\n", nt_errstr(status));
2392 printf("pid1 successfully wrote to the range 130:4\n");
2395 cli_setpid(cli1, 2);
2397 status = cli_read(cli1, fnum1, buf, 130, 4, &nread);
2398 if (!NT_STATUS_IS_OK(status)) {
2399 printf("pid2 unable to read the range 130:4, error was "
2400 "%s\n", nt_errstr(status));
2401 if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
2402 printf("Incorrect error (should be NT_STATUS_FILE_LOCK_CONFLICT)\n");
2406 printf("pid2 successfully read the range 130:4 (should be denied) recv %ld\n",
2407 (unsigned long)nread);
2411 status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 130, 4, NULL);
2412 if (!NT_STATUS_IS_OK(status)) {
2413 printf("pid2 unable to write to the range 130:4, error was "
2414 "%s\n", nt_errstr(status));
2415 if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
2416 printf("Incorrect error (should be NT_STATUS_FILE_LOCK_CONFLICT)\n");
2420 printf("pid2 successfully wrote to the range 130:4 (should be denied)\n");
2424 cli_unlock(cli1, fnum1, 130, 0);
2428 cli_close(cli1, fnum1);
2429 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2430 torture_close_connection(cli1);
2432 printf("finished locktest7\n");
2437 * This demonstrates a problem with our use of GPFS share modes: A file
2438 * descriptor sitting in the pending close queue holding a GPFS share mode
2439 * blocks opening a file another time. Happens with Word 2007 temp files.
2440 * With "posix locking = yes" and "gpfs:sharemodes = yes" enabled, the third
2441 * open is denied with NT_STATUS_SHARING_VIOLATION.
2444 static bool run_locktest8(int dummy)
2446 struct cli_state *cli1;
2447 const char *fname = "\\lockt8.lck";
2448 uint16_t fnum1, fnum2;
2450 bool correct = False;
2453 if (!torture_open_connection(&cli1, 0)) {
2457 smbXcli_conn_set_sockopt(cli1->conn, sockops);
2459 printf("starting locktest8\n");
2461 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2463 status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_WRITE,
2465 if (!NT_STATUS_IS_OK(status)) {
2466 d_fprintf(stderr, "cli_openx returned %s\n", nt_errstr(status));
2470 memset(buf, 0, sizeof(buf));
2472 status = cli_openx(cli1, fname, O_RDONLY, DENY_NONE, &fnum2);
2473 if (!NT_STATUS_IS_OK(status)) {
2474 d_fprintf(stderr, "cli_openx second time returned %s\n",
2479 status = cli_lock32(cli1, fnum2, 1, 1, 0, READ_LOCK);
2480 if (!NT_STATUS_IS_OK(status)) {
2481 printf("Unable to apply read lock on range 1:1, error was "
2482 "%s\n", nt_errstr(status));
2486 status = cli_close(cli1, fnum1);
2487 if (!NT_STATUS_IS_OK(status)) {
2488 d_fprintf(stderr, "cli_close(fnum1) %s\n", nt_errstr(status));
2492 status = cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
2493 if (!NT_STATUS_IS_OK(status)) {
2494 d_fprintf(stderr, "cli_openx third time returned %s\n",
2502 cli_close(cli1, fnum1);
2503 cli_close(cli1, fnum2);
2504 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2505 torture_close_connection(cli1);
2507 printf("finished locktest8\n");
2512 * This test is designed to be run in conjunction with
2513 * external NFS or POSIX locks taken in the filesystem.
2514 * It checks that the smbd server will block until the
2515 * lock is released and then acquire it. JRA.
2518 static bool got_alarm;
2519 static struct cli_state *alarm_cli;
2521 static void alarm_handler(int dummy)
2526 static void alarm_handler_parent(int dummy)
2528 smbXcli_conn_disconnect(alarm_cli->conn, NT_STATUS_LOCAL_DISCONNECT);
2531 static void do_local_lock(const char *fname, int read_fd, int write_fd)
2536 const char *local_pathname = NULL;
2539 local_pathname = talloc_asprintf(talloc_tos(),
2540 "%s/%s", local_path, fname);
2541 if (!local_pathname) {
2542 printf("child: alloc fail\n");
2546 unlink(local_pathname);
2547 fd = open(local_pathname, O_RDWR|O_CREAT, 0666);
2549 printf("child: open of %s failed %s.\n",
2550 local_pathname, strerror(errno));
2554 /* Now take a fcntl lock. */
2555 lock.l_type = F_WRLCK;
2556 lock.l_whence = SEEK_SET;
2559 lock.l_pid = getpid();
2561 ret = fcntl(fd,F_SETLK,&lock);
2563 printf("child: failed to get lock 0:4 on file %s. Error %s\n",
2564 local_pathname, strerror(errno));
2567 printf("child: got lock 0:4 on file %s.\n",
2572 CatchSignal(SIGALRM, alarm_handler);
2574 /* Signal the parent. */
2575 if (write(write_fd, &c, 1) != 1) {
2576 printf("child: start signal fail %s.\n",
2583 /* Wait for the parent to be ready. */
2584 if (read(read_fd, &c, 1) != 1) {
2585 printf("child: reply signal fail %s.\n",
2593 printf("child: released lock 0:4 on file %s.\n",
2599 static bool _run_locktest9X(const char *fname, int timeout)
2601 struct cli_state *cli1;
2602 char *fpath = talloc_asprintf(talloc_tos(), "\\%s", fname);
2604 bool correct = False;
2605 int pipe_in[2], pipe_out[2];
2609 struct timeval start;
2613 printf("starting locktest9X: %s\n", fname);
2615 if (local_path == NULL) {
2616 d_fprintf(stderr, "locktest9X must be given a local path via -l <localpath>\n");
2620 if (pipe(pipe_in) == -1 || pipe(pipe_out) == -1) {
2625 if (child_pid == -1) {
2629 if (child_pid == 0) {
2631 do_local_lock(fname, pipe_out[0], pipe_in[1]);
2641 ret = read(pipe_in[0], &c, 1);
2643 d_fprintf(stderr, "failed to read start signal from child. %s\n",
2648 if (!torture_open_connection(&cli1, 0)) {
2652 smbXcli_conn_set_sockopt(cli1->conn, sockops);
2654 status = cli_openx(cli1, fpath, O_RDWR, DENY_NONE,
2656 if (!NT_STATUS_IS_OK(status)) {
2657 d_fprintf(stderr, "cli_openx returned %s\n", nt_errstr(status));
2661 /* Ensure the child has the lock. */
2662 status = cli_lock32(cli1, fnum, 0, 4, 0, WRITE_LOCK);
2663 if (NT_STATUS_IS_OK(status)) {
2664 d_fprintf(stderr, "Got the lock on range 0:4 - this should not happen !\n");
2667 d_printf("Child has the lock.\n");
2670 /* Tell the child to wait 5 seconds then exit. */
2671 ret = write(pipe_out[1], &c, 1);
2673 d_fprintf(stderr, "failed to send exit signal to child. %s\n",
2678 /* Wait 20 seconds for the lock. */
2680 CatchSignal(SIGALRM, alarm_handler_parent);
2683 start = timeval_current();
2685 status = cli_lock32(cli1, fnum, 0, 4, timeout, WRITE_LOCK);
2686 if (!NT_STATUS_IS_OK(status)) {
2687 d_fprintf(stderr, "Unable to apply write lock on range 0:4, error was "
2688 "%s\n", nt_errstr(status));
2693 seconds = timeval_elapsed(&start);
2695 printf("Parent got the lock after %.2f seconds.\n",
2698 status = cli_close(cli1, fnum);
2699 if (!NT_STATUS_IS_OK(status)) {
2700 d_fprintf(stderr, "cli_close(fnum1) %s\n", nt_errstr(status));
2707 cli_close(cli1, fnum);
2708 torture_close_connection(cli1);
2712 printf("finished locktest9X: %s\n", fname);
2716 static bool run_locktest9a(int dummy)
2718 return _run_locktest9X("lock9a.dat", -1);
2721 static bool run_locktest9b(int dummy)
2723 return _run_locktest9X("lock9b.dat", 10000);
2726 struct locktest10_state {
2731 static void locktest10_lockingx_done(struct tevent_req *subreq);
2732 static void locktest10_read_andx_done(struct tevent_req *subreq);
2734 static bool run_locktest10(int dummy)
2736 struct tevent_context *ev = NULL;
2737 struct cli_state *cli1 = NULL;
2738 struct cli_state *cli2 = NULL;
2739 struct smb1_lock_element lck = { 0 };
2740 struct tevent_req *reqs[2] = { NULL };
2741 struct tevent_req *smbreqs[2] = { NULL };
2742 const char fname[] = "\\lockt10.lck";
2743 uint16_t fnum1, fnum2;
2747 struct locktest10_state state = { .ok = true };
2750 printf("starting locktest10\n");
2752 ev = samba_tevent_context_init(NULL);
2754 d_fprintf(stderr, "samba_tevent_context_init failed\n");
2758 ok = torture_open_connection(&cli1, 0);
2762 smbXcli_conn_set_sockopt(cli1->conn, sockops);
2764 ok = torture_open_connection(&cli2, 1);
2768 smbXcli_conn_set_sockopt(cli2->conn, sockops);
2770 status = cli_openx(cli1, fname, O_CREAT|O_RDWR, DENY_NONE, &fnum1);
2771 if (!NT_STATUS_IS_OK(status)) {
2773 "cli_openx failed: %s\n",
2778 status = cli_writeall(cli1, fnum1, 0, &data, 0, sizeof(data), NULL);
2779 if (!NT_STATUS_IS_OK(status)) {
2781 "cli_writeall failed: %s\n",
2786 status = cli_openx(cli2, fname, O_CREAT|O_RDWR, DENY_NONE, &fnum2);
2787 if (!NT_STATUS_IS_OK(status)) {
2789 "cli_openx failed: %s\n",
2794 status = cli_locktype(
2795 cli2, fnum2, 0, 1, 0, LOCKING_ANDX_EXCLUSIVE_LOCK);
2796 if (!NT_STATUS_IS_OK(status)) {
2798 "cli_locktype failed: %s\n",
2803 lck = (struct smb1_lock_element) {
2804 .pid = cli_getpid(cli1), .offset = 0, .length = 1,
2807 reqs[0] = cli_lockingx_create(
2809 ev, /* tevent_context */
2812 LOCKING_ANDX_EXCLUSIVE_LOCK, /* typeoflock */
2813 0, /* newoplocklevel */
2815 0, /* num_unlocks */
2819 &smbreqs[0]); /* psmbreq */
2820 if (reqs[0] == NULL) {
2821 d_fprintf(stderr, "cli_lockingx_create failed\n");
2824 tevent_req_set_callback(reqs[0], locktest10_lockingx_done, &state);
2826 reqs[1] = cli_read_andx_create(
2833 &smbreqs[1]); /* psmbreq */
2834 if (reqs[1] == NULL) {
2835 d_fprintf(stderr, "cli_read_andx_create failed\n");
2838 tevent_req_set_callback(reqs[1], locktest10_read_andx_done, &state);
2840 status = smb1cli_req_chain_submit(smbreqs, ARRAY_SIZE(smbreqs));
2841 if (!NT_STATUS_IS_OK(status)) {
2843 "smb1cli_req_chain_submit failed: %s\n",
2848 while (!state.done) {
2849 tevent_loop_once(ev);
2852 torture_close_connection(cli1);
2861 static void locktest10_lockingx_done(struct tevent_req *subreq)
2863 struct locktest10_state *state = tevent_req_callback_data_void(subreq);
2866 status = cli_lockingx_recv(subreq);
2867 TALLOC_FREE(subreq);
2869 if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
2870 d_printf("cli_lockingx returned %s\n", nt_errstr(status));
2875 static void locktest10_read_andx_done(struct tevent_req *subreq)
2877 struct locktest10_state *state = tevent_req_callback_data_void(subreq);
2878 ssize_t received = -1;
2879 uint8_t *rcvbuf = NULL;
2882 status = cli_read_andx_recv(subreq, &received, &rcvbuf);
2884 if (!NT_STATUS_EQUAL(status, NT_STATUS_REQUEST_ABORTED)) {
2885 d_printf("cli_read_andx returned %s\n", nt_errstr(status));
2890 TALLOC_FREE(subreq);
2893 static bool run_locktest11(int dummy)
2895 struct cli_state *cli1;
2896 const char *fname = "\\lockt11.lck";
2901 if (!torture_open_connection(&cli1, 0)) {
2905 smbXcli_conn_set_sockopt(cli1->conn, sockops);
2907 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2909 status = cli_openx(cli1, fname, O_CREAT|O_RDWR, DENY_NONE, &fnum);
2910 if (!NT_STATUS_IS_OK(status)) {
2912 "cli_openx returned %s\n",
2918 * Test that LOCKING_ANDX_CANCEL_LOCK without any locks
2919 * returns NT_STATUS_OK
2922 status = cli_lockingx(
2925 LOCKING_ANDX_CANCEL_LOCK, /* typeoflock */
2926 0, /* newoplocklevel */
2928 0, /* num_unlocks */
2933 if (!NT_STATUS_IS_OK(status)) {
2934 d_printf("cli_lockingX returned %s\n", nt_errstr(status));
2940 cli_close(cli1, fnum);
2941 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2946 struct deferred_close_state {
2947 struct tevent_context *ev;
2948 struct cli_state *cli;
2952 static void deferred_close_waited(struct tevent_req *subreq);
2953 static void deferred_close_done(struct tevent_req *subreq);
2955 static struct tevent_req *deferred_close_send(
2956 TALLOC_CTX *mem_ctx,
2957 struct tevent_context *ev,
2959 struct cli_state *cli,
2962 struct tevent_req *req = NULL, *subreq = NULL;
2963 struct deferred_close_state *state = NULL;
2964 struct timeval wakeup_time = timeval_current_ofs(wait_secs, 0);
2966 req = tevent_req_create(
2967 mem_ctx, &state, struct deferred_close_state);
2975 subreq = tevent_wakeup_send(state, state->ev, wakeup_time);
2976 if (tevent_req_nomem(subreq, req)) {
2977 return tevent_req_post(req, ev);
2979 tevent_req_set_callback(subreq, deferred_close_waited, req);
2983 static void deferred_close_waited(struct tevent_req *subreq)
2985 struct tevent_req *req = tevent_req_callback_data(
2986 subreq, struct tevent_req);
2987 struct deferred_close_state *state = tevent_req_data(
2988 req, struct deferred_close_state);
2991 ok = tevent_wakeup_recv(subreq);
2992 TALLOC_FREE(subreq);
2994 tevent_req_oom(req);
2998 subreq = cli_close_send(state, state->ev, state->cli, state->fnum);
2999 if (tevent_req_nomem(subreq, req)) {
3002 tevent_req_set_callback(subreq, deferred_close_done, req);
3005 static void deferred_close_done(struct tevent_req *subreq)
3007 NTSTATUS status = cli_close_recv(subreq);
3008 tevent_req_simple_finish_ntstatus(subreq, status);
3011 static NTSTATUS deferred_close_recv(struct tevent_req *req)
3013 return tevent_req_simple_recv_ntstatus(req);
3016 struct lockread_state {
3017 struct smb1_lock_element lck;
3018 struct tevent_req *reqs[2];
3019 struct tevent_req *smbreqs[2];
3020 NTSTATUS lock_status;
3021 NTSTATUS read_status;
3025 static void lockread_lockingx_done(struct tevent_req *subreq);
3026 static void lockread_read_andx_done(struct tevent_req *subreq);
3028 static struct tevent_req *lockread_send(
3029 TALLOC_CTX *mem_ctx,
3030 struct tevent_context *ev,
3031 struct cli_state *cli,
3034 struct tevent_req *req = NULL;
3035 struct lockread_state *state = NULL;
3038 req = tevent_req_create(mem_ctx, &state, struct lockread_state);
3043 state->lck = (struct smb1_lock_element) {
3044 .pid = cli_getpid(cli), .offset = 0, .length = 1,
3047 state->reqs[0] = cli_lockingx_create(
3049 ev, /* tevent_context */
3052 LOCKING_ANDX_EXCLUSIVE_LOCK, /* typeoflock */
3053 0, /* newoplocklevel */
3054 10000, /* timeout */
3055 0, /* num_unlocks */
3058 &state->lck, /* locks */
3059 &state->smbreqs[0]); /* psmbreq */
3060 if (tevent_req_nomem(state->reqs[0], req)) {
3061 return tevent_req_post(req, ev);
3063 tevent_req_set_callback(
3064 state->reqs[0], lockread_lockingx_done, req);
3066 state->reqs[1] = cli_read_andx_create(
3073 &state->smbreqs[1]); /* psmbreq */
3074 if (tevent_req_nomem(state->reqs[1], req)) {
3075 return tevent_req_post(req, ev);
3077 tevent_req_set_callback(
3078 state->reqs[1], lockread_read_andx_done, req);
3080 status = smb1cli_req_chain_submit(state->smbreqs, 2);
3081 if (tevent_req_nterror(req, status)) {
3082 return tevent_req_post(req, ev);
3087 static void lockread_lockingx_done(struct tevent_req *subreq)
3089 struct tevent_req *req = tevent_req_callback_data(
3090 subreq, struct tevent_req);
3091 struct lockread_state *state = tevent_req_data(
3092 req, struct lockread_state);
3093 state->lock_status = cli_lockingx_recv(subreq);
3094 TALLOC_FREE(subreq);
3096 "lockingx returned %s\n",
3097 nt_errstr(state->lock_status));
3100 static void lockread_read_andx_done(struct tevent_req *subreq)
3102 struct tevent_req *req = tevent_req_callback_data(
3103 subreq, struct tevent_req);
3104 struct lockread_state *state = tevent_req_data(
3105 req, struct lockread_state);
3106 ssize_t received = -1;
3107 uint8_t *rcvbuf = NULL;
3109 state->read_status = cli_read_andx_recv(subreq, &received, &rcvbuf);
3112 "read returned %s\n",
3113 nt_errstr(state->read_status));
3115 if (!NT_STATUS_IS_OK(state->read_status)) {
3116 TALLOC_FREE(subreq);
3117 tevent_req_done(req);
3122 state->readbuf = talloc_memdup(state, rcvbuf, received);
3123 TALLOC_FREE(subreq);
3124 if (tevent_req_nomem(state->readbuf, req)) {
3128 TALLOC_FREE(subreq);
3129 tevent_req_done(req);
3132 static NTSTATUS lockread_recv(
3133 struct tevent_req *req,
3134 NTSTATUS *lock_status,
3135 NTSTATUS *read_status,
3136 TALLOC_CTX *mem_ctx,
3139 struct lockread_state *state = tevent_req_data(
3140 req, struct lockread_state);
3143 if (tevent_req_is_nterror(req, &status)) {
3147 *lock_status = state->lock_status;
3148 *read_status = state->read_status;
3149 if (state->readbuf != NULL) {
3150 *read_buf = talloc_move(mem_ctx, &state->readbuf);
3155 return NT_STATUS_OK;
3158 struct lock12_state {
3162 static void lock12_closed(struct tevent_req *subreq);
3163 static void lock12_read(struct tevent_req *subreq);
3165 static struct tevent_req *lock12_send(
3166 TALLOC_CTX *mem_ctx,
3167 struct tevent_context *ev,
3168 struct cli_state *cli,
3172 struct tevent_req *req = NULL, *subreq = NULL;
3173 struct lock12_state *state = NULL;
3175 req = tevent_req_create(mem_ctx, &state, struct lock12_state);
3180 subreq = deferred_close_send(state, ev, 1, cli, fnum1);
3181 if (tevent_req_nomem(subreq, req)) {
3182 return tevent_req_post(req, ev);
3184 tevent_req_set_callback(subreq, lock12_closed, req);
3186 subreq = lockread_send(state, ev, cli, fnum2);
3187 if (tevent_req_nomem(subreq, req)) {
3188 return tevent_req_post(req, ev);
3190 tevent_req_set_callback(subreq, lock12_read, req);
3195 static void lock12_closed(struct tevent_req *subreq)
3197 struct tevent_req *req = tevent_req_callback_data(
3198 subreq, struct tevent_req);
3201 status = deferred_close_recv(subreq);
3202 TALLOC_FREE(subreq);
3203 DBG_DEBUG("close returned %s\n", nt_errstr(status));
3204 if (tevent_req_nterror(req, status)) {
3209 static void lock12_read(struct tevent_req *subreq)
3211 struct tevent_req *req = tevent_req_callback_data(
3212 subreq, struct tevent_req);
3213 struct lock12_state *state = tevent_req_data(
3214 req, struct lock12_state);
3215 NTSTATUS status, lock_status, read_status;
3216 uint8_t *buf = NULL;
3218 status = lockread_recv(
3219 subreq, &lock_status, &read_status, state, &buf);
3220 TALLOC_FREE(subreq);
3221 if (tevent_req_nterror(req, status) ||
3222 tevent_req_nterror(req, lock_status) ||
3223 tevent_req_nterror(req, read_status)) {
3226 tevent_req_done(req);
3229 static NTSTATUS lock12_recv(struct tevent_req *req)
3234 if (tevent_req_is_nterror(req, &status)) {
3237 return NT_STATUS_OK;
3240 static bool run_locktest12(int dummy)
3242 struct tevent_context *ev = NULL;
3243 struct tevent_req *req = NULL;
3244 struct cli_state *cli = NULL;
3245 const char fname[] = "\\lockt12.lck";
3246 uint16_t fnum1, fnum2;
3252 printf("starting locktest12\n");
3254 ev = samba_tevent_context_init(NULL);
3256 d_fprintf(stderr, "samba_tevent_context_init failed\n");
3260 ok = torture_open_connection(&cli, 0);
3264 smbXcli_conn_set_sockopt(cli->conn, sockops);
3266 status = cli_openx(cli, fname, O_CREAT|O_RDWR, DENY_NONE, &fnum1);
3267 if (!NT_STATUS_IS_OK(status)) {
3269 "cli_openx failed: %s\n",
3274 status = cli_openx(cli, fname, O_CREAT|O_RDWR, DENY_NONE, &fnum2);
3275 if (!NT_STATUS_IS_OK(status)) {
3277 "cli_openx failed: %s\n",
3282 status = cli_writeall(cli, fnum1, 0, &data, 0, sizeof(data), NULL);
3283 if (!NT_STATUS_IS_OK(status)) {
3285 "cli_writeall failed: %s\n",
3290 status = cli_locktype(
3291 cli, fnum1, 0, 1, 0, LOCKING_ANDX_EXCLUSIVE_LOCK);
3292 if (!NT_STATUS_IS_OK(status)) {
3294 "cli_locktype failed: %s\n",
3299 req = lock12_send(ev, ev, cli, fnum1, fnum2);
3301 d_fprintf(stderr, "lock12_send failed\n");
3305 ok = tevent_req_poll_ntstatus(req, ev, &status);
3307 d_fprintf(stderr, "tevent_req_poll_ntstatus failed\n");
3311 if (!NT_STATUS_IS_OK(status)) {
3313 "tevent_req_poll_ntstatus returned %s\n",
3318 status = lock12_recv(req);
3319 if (!NT_STATUS_IS_OK(status)) {
3320 d_fprintf(stderr, "lock12 returned %s\n", nt_errstr(status));
3327 torture_close_connection(cli);
3332 struct lock_ntcancel_state {
3333 struct timeval start;
3334 struct smb1_lock_element lck;
3335 struct tevent_req *subreq;
3338 static void lock_ntcancel_waited(struct tevent_req *subreq);
3339 static void lock_ntcancel_done(struct tevent_req *subreq);
3341 static struct tevent_req *lock_ntcancel_send(
3342 TALLOC_CTX *mem_ctx,
3343 struct tevent_context *ev,
3344 struct cli_state *cli,
3347 struct tevent_req *req = NULL, *subreq = NULL;
3348 struct lock_ntcancel_state *state = NULL;
3350 req = tevent_req_create(mem_ctx, &state, struct lock_ntcancel_state);
3354 state->lck = (struct smb1_lock_element) {
3355 .pid = cli_getpid(cli), .offset = 0, .length = 1,
3357 state->start = timeval_current();
3359 state->subreq = cli_lockingx_send(
3360 state, /* mem_ctx */
3361 ev, /* tevent_context */
3364 LOCKING_ANDX_EXCLUSIVE_LOCK, /* typeoflock */
3365 0, /* newoplocklevel */
3366 10000, /* timeout */
3367 0, /* num_unlocks */
3370 &state->lck); /* locks */
3371 if (tevent_req_nomem(state->subreq, req)) {
3372 return tevent_req_post(req, ev);
3374 tevent_req_set_callback(state->subreq, lock_ntcancel_done, req);
3376 subreq = tevent_wakeup_send(state, ev, timeval_current_ofs(1, 0));
3377 if (tevent_req_nomem(subreq, req)) {
3378 return tevent_req_post(req, ev);
3380 tevent_req_set_callback(subreq, lock_ntcancel_waited, req);
3384 static void lock_ntcancel_waited(struct tevent_req *subreq)
3386 struct tevent_req *req = tevent_req_callback_data(
3387 subreq, struct tevent_req);
3388 struct lock_ntcancel_state *state = tevent_req_data(
3389 req, struct lock_ntcancel_state);
3392 ok = tevent_wakeup_recv(subreq);
3393 TALLOC_FREE(subreq);
3395 tevent_req_oom(req);
3399 ok = tevent_req_cancel(state->subreq);
3401 d_fprintf(stderr, "Could not cancel subreq\n");
3402 tevent_req_oom(req);
3407 static void lock_ntcancel_done(struct tevent_req *subreq)
3409 struct tevent_req *req = tevent_req_callback_data(
3410 subreq, struct tevent_req);
3411 struct lock_ntcancel_state *state = tevent_req_data(
3412 req, struct lock_ntcancel_state);
3416 status = cli_lockingx_recv(subreq);
3417 TALLOC_FREE(subreq);
3419 if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
3420 d_printf("cli_lockingx returned %s\n", nt_errstr(status));
3421 tevent_req_nterror(req, NT_STATUS_UNSUCCESSFUL);
3425 elapsed = timeval_elapsed(&state->start);
3428 d_printf("cli_lockingx was too slow, cancel did not work\n");
3429 tevent_req_nterror(req, NT_STATUS_UNSUCCESSFUL);
3433 tevent_req_done(req);
3436 static NTSTATUS lock_ntcancel_recv(struct tevent_req *req)
3438 return tevent_req_simple_recv_ntstatus(req);
3441 static bool run_locktest13(int dummy)
3443 struct tevent_context *ev = NULL;
3444 struct tevent_req *req = NULL;
3445 struct cli_state *cli = NULL;
3446 const char fname[] = "\\lockt13.lck";
3447 uint16_t fnum1, fnum2;
3453 printf("starting locktest13\n");
3455 ev = samba_tevent_context_init(NULL);
3457 d_fprintf(stderr, "samba_tevent_context_init failed\n");
3461 ok = torture_open_connection(&cli, 0);
3465 smbXcli_conn_set_sockopt(cli->conn, sockops);
3467 status = cli_openx(cli, fname, O_CREAT|O_RDWR, DENY_NONE, &fnum1);
3468 if (!NT_STATUS_IS_OK(status)) {
3470 "cli_openx failed: %s\n",
3475 status = cli_openx(cli, fname, O_CREAT|O_RDWR, DENY_NONE, &fnum2);
3476 if (!NT_STATUS_IS_OK(status)) {
3478 "cli_openx failed: %s\n",
3483 status = cli_writeall(cli, fnum1, 0, &data, 0, sizeof(data), NULL);
3484 if (!NT_STATUS_IS_OK(status)) {
3486 "cli_writeall failed: %s\n",
3491 status = cli_locktype(
3492 cli, fnum1, 0, 1, 0, LOCKING_ANDX_EXCLUSIVE_LOCK);
3493 if (!NT_STATUS_IS_OK(status)) {
3495 "cli_locktype failed: %s\n",
3500 req = lock_ntcancel_send(ev, ev, cli, fnum2);
3502 d_fprintf(stderr, "lock_ntcancel_send failed\n");
3506 ok = tevent_req_poll_ntstatus(req, ev, &status);
3508 d_fprintf(stderr, "tevent_req_poll_ntstatus failed\n");
3512 if (!NT_STATUS_IS_OK(status)) {
3514 "tevent_req_poll_ntstatus returned %s\n",
3519 status = lock_ntcancel_recv(req);
3520 if (!NT_STATUS_IS_OK(status)) {
3522 "lock_ntcancel returned %s\n",
3530 torture_close_connection(cli);
3536 test whether fnums and tids open on one VC are available on another (a major
3539 static bool run_fdpasstest(int dummy)
3541 struct cli_state *cli1, *cli2;
3542 const char *fname = "\\fdpass.tst";
3547 if (!torture_open_connection(&cli1, 0) || !torture_open_connection(&cli2, 1)) {
3550 smbXcli_conn_set_sockopt(cli1->conn, sockops);
3551 smbXcli_conn_set_sockopt(cli2->conn, sockops);
3553 printf("starting fdpasstest\n");
3555 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3557 status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
3559 if (!NT_STATUS_IS_OK(status)) {
3560 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
3564 status = cli_writeall(cli1, fnum1, 0, (const uint8_t *)"hello world\n", 0,
3566 if (!NT_STATUS_IS_OK(status)) {
3567 printf("write failed (%s)\n", nt_errstr(status));
3571 cli_state_set_uid(cli2, cli_state_get_uid(cli1));
3572 cli_state_set_tid(cli2, cli_state_get_tid(cli1));
3573 cli_setpid(cli2, cli_getpid(cli1));
3575 if (test_cli_read(cli2, fnum1, buf, 0, 13, NULL, 13)) {
3576 printf("read succeeded! nasty security hole [%s]\n", buf);
3580 cli_close(cli1, fnum1);
3581 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3583 torture_close_connection(cli1);
3584 torture_close_connection(cli2);
3586 printf("finished fdpasstest\n");
3590 static bool run_fdsesstest(int dummy)
3592 struct cli_state *cli;
3594 uint16_t saved_vuid;
3596 uint32_t saved_cnum;
3597 const char *fname = "\\fdsess.tst";
3598 const char *fname1 = "\\fdsess1.tst";
3605 if (!torture_open_connection(&cli, 0))
3607 smbXcli_conn_set_sockopt(cli->conn, sockops);
3609 if (!torture_cli_session_setup2(cli, &new_vuid))
3612 saved_cnum = cli_state_get_tid(cli);
3613 if (!NT_STATUS_IS_OK(cli_tree_connect(cli, share, "?????", NULL)))
3615 new_cnum = cli_state_get_tid(cli);
3616 cli_state_set_tid(cli, saved_cnum);
3618 printf("starting fdsesstest\n");
3620 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3621 cli_unlink(cli, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3623 status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
3624 if (!NT_STATUS_IS_OK(status)) {
3625 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
3629 status = cli_writeall(cli, fnum1, 0, (const uint8_t *)"hello world\n", 0, 13,
3631 if (!NT_STATUS_IS_OK(status)) {
3632 printf("write failed (%s)\n", nt_errstr(status));
3636 saved_vuid = cli_state_get_uid(cli);
3637 cli_state_set_uid(cli, new_vuid);
3639 if (test_cli_read(cli, fnum1, buf, 0, 13, NULL, 13)) {
3640 printf("read succeeded with different vuid! "
3641 "nasty security hole [%s]\n", buf);
3644 /* Try to open a file with different vuid, samba cnum. */
3645 if (NT_STATUS_IS_OK(cli_openx(cli, fname1, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum2))) {
3646 printf("create with different vuid, same cnum succeeded.\n");
3647 cli_close(cli, fnum2);
3648 cli_unlink(cli, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3650 printf("create with different vuid, same cnum failed.\n");
3651 printf("This will cause problems with service clients.\n");
3655 cli_state_set_uid(cli, saved_vuid);
3657 /* Try with same vuid, different cnum. */
3658 cli_state_set_tid(cli, new_cnum);
3660 if (test_cli_read(cli, fnum1, buf, 0, 13, NULL, 13)) {
3661 printf("read succeeded with different cnum![%s]\n", buf);
3665 cli_state_set_tid(cli, saved_cnum);
3666 cli_close(cli, fnum1);
3667 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3669 torture_close_connection(cli);
3671 printf("finished fdsesstest\n");
3676 This test checks that
3678 1) the server does not allow an unlink on a file that is open
3680 static bool run_unlinktest(int dummy)
3682 struct cli_state *cli;
3683 const char *fname = "\\unlink.tst";
3685 bool correct = True;
3688 if (!torture_open_connection(&cli, 0)) {
3692 smbXcli_conn_set_sockopt(cli->conn, sockops);
3694 printf("starting unlink test\n");
3696 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3700 status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
3701 if (!NT_STATUS_IS_OK(status)) {
3702 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
3706 status = cli_unlink(cli, fname,
3707 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3708 if (NT_STATUS_IS_OK(status)) {
3709 printf("error: server allowed unlink on an open file\n");
3712 correct = check_error(__LINE__, status, ERRDOS, ERRbadshare,
3713 NT_STATUS_SHARING_VIOLATION);
3716 cli_close(cli, fnum);
3717 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3719 if (!torture_close_connection(cli)) {
3723 printf("unlink test finished\n");
3730 test how many open files this server supports on the one socket
3732 static bool run_maxfidtest(int dummy)
3734 struct cli_state *cli;
3736 uint16_t fnums[0x11000];
3739 bool correct = True;
3745 printf("failed to connect\n");
3749 smbXcli_conn_set_sockopt(cli->conn, sockops);
3751 for (i=0; i<0x11000; i++) {
3752 slprintf(fname,sizeof(fname)-1,"\\maxfid.%d.%d", i,(int)getpid());
3753 status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_TRUNC, DENY_NONE,
3755 if (!NT_STATUS_IS_OK(status)) {
3756 printf("open of %s failed (%s)\n",
3757 fname, nt_errstr(status));
3758 printf("maximum fnum is %d\n", i);
3766 printf("cleaning up\n");
3768 slprintf(fname,sizeof(fname)-1,"\\maxfid.%d.%d", i,(int)getpid());
3769 cli_close(cli, fnums[i]);
3771 status = cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
3772 if (!NT_STATUS_IS_OK(status)) {
3773 printf("unlink of %s failed (%s)\n",
3774 fname, nt_errstr(status));
3781 printf("maxfid test finished\n");
3782 if (!torture_close_connection(cli)) {
3788 /* generate a random buffer */
3789 static void rand_buf(char *buf, int len)
3792 *buf = (char)sys_random();
3797 /* send smb negprot commands, not reading the response */
3798 static bool run_negprot_nowait(int dummy)
3800 struct tevent_context *ev;
3802 struct cli_state *cli;
3803 bool correct = True;
3805 printf("starting negprot nowait test\n");
3807 ev = samba_tevent_context_init(talloc_tos());
3812 if (!(cli = open_nbt_connection())) {
3817 for (i=0;i<50000;i++) {
3818 struct tevent_req *req;
3820 req = smbXcli_negprot_send(ev, ev, cli->conn, cli->timeout,
3821 PROTOCOL_CORE, PROTOCOL_NT1, 0);
3826 if (!tevent_req_poll(req, ev)) {
3827 d_fprintf(stderr, "tevent_req_poll failed: %s\n",
3835 if (torture_close_connection(cli)) {
3839 printf("finished negprot nowait test\n");
3844 /* send smb negprot commands, not reading the response */
3845 static bool run_bad_nbt_session(int dummy)
3847 struct nmb_name called, calling;
3848 struct sockaddr_storage ss;
3853 printf("starting bad nbt session test\n");
3855 make_nmb_name(&calling, myname, 0x0);
3856 make_nmb_name(&called , host, 0x20);
3858 if (!resolve_name(host, &ss, 0x20, true)) {
3859 d_fprintf(stderr, "Could not resolve name %s\n", host);
3863 status = open_socket_out(&ss, NBT_SMB_PORT, 10000, &fd);
3864 if (!NT_STATUS_IS_OK(status)) {
3865 d_fprintf(stderr, "open_socket_out failed: %s\n",
3870 ret = cli_bad_session_request(fd, &calling, &called);
3873 d_fprintf(stderr, "open_socket_out failed: %s\n",
3878 printf("finished bad nbt session test\n");
3882 /* send random IPC commands */
3883 static bool run_randomipc(int dummy)
3885 char *rparam = NULL;
3887 unsigned int rdrcnt,rprcnt;
3889 int api, param_len, i;
3890 struct cli_state *cli;
3891 bool correct = True;
3894 printf("starting random ipc test\n");
3896 if (!torture_open_connection(&cli, 0)) {
3900 for (i=0;i<count;i++) {
3901 api = sys_random() % 500;
3902 param_len = (sys_random() % 64);
3904 rand_buf(param, param_len);
3909 param, param_len, 8,
3910 NULL, 0, CLI_BUFFER_SIZE,
3914 printf("%d/%d\r", i,count);
3917 printf("%d/%d\n", i, count);
3919 if (!torture_close_connection(cli)) {
3926 printf("finished random ipc test\n");
3933 static void browse_callback(const char *sname, uint32_t stype,
3934 const char *comment, void *state)
3936 printf("\t%20.20s %08x %s\n", sname, stype, comment);
3942 This test checks the browse list code
3945 static bool run_browsetest(int dummy)
3947 static struct cli_state *cli;
3948 bool correct = True;
3950 printf("starting browse test\n");
3952 if (!torture_open_connection(&cli, 0)) {
3956 printf("domain list:\n");
3957 cli_NetServerEnum(cli, cli->server_domain,
3958 SV_TYPE_DOMAIN_ENUM,
3959 browse_callback, NULL);
3961 printf("machine list:\n");
3962 cli_NetServerEnum(cli, cli->server_domain,
3964 browse_callback, NULL);
3966 if (!torture_close_connection(cli)) {
3970 printf("browse test finished\n");
3976 static bool check_attributes(struct cli_state *cli,
3978 uint32_t expected_attrs)
3981 NTSTATUS status = cli_getatr(cli,
3986 if (!NT_STATUS_IS_OK(status)) {
3987 printf("cli_getatr failed with %s\n",
3991 if (attrs != expected_attrs) {
3992 printf("Attributes incorrect 0x%x, should be 0x%x\n",
3993 (unsigned int)attrs,
3994 (unsigned int)expected_attrs);
4001 This checks how the getatr calls works
4003 static bool run_attrtest(int dummy)
4005 struct cli_state *cli;
4008 const char *fname = "\\attrib123456789.tst";
4009 bool correct = True;
4012 printf("starting attrib test\n");
4014 if (!torture_open_connection(&cli, 0)) {
4018 /* Ensure we can't unlink with out-of-range (unknown) attribute. */
4019 status = cli_unlink(cli, fname, 0x20000);
4020 if (!NT_STATUS_EQUAL(status, NT_STATUS_INVALID_PARAMETER)) {
4025 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4026 cli_openx(cli, fname,
4027 O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum);
4028 cli_close(cli, fnum);
4030 status = cli_getatr(cli, fname, NULL, NULL, &t);
4031 if (!NT_STATUS_IS_OK(status)) {
4032 printf("getatr failed (%s)\n", nt_errstr(status));
4036 if (labs(t - time(NULL)) > 60*60*24*10) {
4037 printf("ERROR: SMBgetatr bug. time is %s",
4043 t2 = t-60*60*24; /* 1 day ago */
4045 /* Ensure we can't set with out-of-range (unknown) attribute. */
4046 status = cli_setatr(cli, fname, 0x20000, t2);
4047 if (!NT_STATUS_EQUAL(status, NT_STATUS_INVALID_PARAMETER)) {
4052 status = cli_setatr(cli, fname, 0, t2);
4053 if (!NT_STATUS_IS_OK(status)) {
4054 printf("setatr failed (%s)\n", nt_errstr(status));
4058 status = cli_getatr(cli, fname, NULL, NULL, &t);
4059 if (!NT_STATUS_IS_OK(status)) {
4060 printf("getatr failed (%s)\n", nt_errstr(status));
4065 printf("ERROR: getatr/setatr bug. times are\n%s",
4067 printf("%s", ctime(&t2));
4071 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4073 /* Check cli_setpathinfo_ext() */
4074 /* Re-create the file. */
4075 status = cli_openx(cli, fname,
4076 O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum);
4077 if (!NT_STATUS_IS_OK(status)) {
4078 printf("Failed to recreate %s (%s)\n",
4079 fname, nt_errstr(status));
4082 cli_close(cli, fnum);
4084 status = cli_setpathinfo_ext(
4087 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* create */
4088 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* access */
4089 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* write */
4090 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* change */
4091 FILE_ATTRIBUTE_SYSTEM |
4092 FILE_ATTRIBUTE_HIDDEN |
4093 FILE_ATTRIBUTE_READONLY);
4094 if (!NT_STATUS_IS_OK(status)) {
4095 printf("cli_setpathinfo_ext failed with %s\n",
4100 /* Check attributes are correct. */
4101 correct = check_attributes(cli,
4103 FILE_ATTRIBUTE_SYSTEM |
4104 FILE_ATTRIBUTE_HIDDEN |
4105 FILE_ATTRIBUTE_READONLY);
4106 if (correct == false) {
4110 /* Setting to FILE_ATTRIBUTE_NORMAL should be ignored. */
4111 status = cli_setpathinfo_ext(
4114 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* create */
4115 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* access */
4116 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* write */
4117 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* change */
4118 FILE_ATTRIBUTE_NORMAL);
4119 if (!NT_STATUS_IS_OK(status)) {
4120 printf("cli_setpathinfo_ext failed with %s\n",
4125 /* Check attributes are correct. */
4126 correct = check_attributes(cli,
4128 FILE_ATTRIBUTE_SYSTEM |
4129 FILE_ATTRIBUTE_HIDDEN |
4130 FILE_ATTRIBUTE_READONLY);
4131 if (correct == false) {
4135 /* Setting to (uint16_t)-1 should also be ignored. */
4136 status = cli_setpathinfo_ext(
4139 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* create */
4140 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* access */
4141 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* write */
4142 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* change */
4144 if (!NT_STATUS_IS_OK(status)) {
4145 printf("cli_setpathinfo_ext failed with %s\n",
4150 /* Check attributes are correct. */
4151 correct = check_attributes(cli,
4153 FILE_ATTRIBUTE_SYSTEM |
4154 FILE_ATTRIBUTE_HIDDEN |
4155 FILE_ATTRIBUTE_READONLY);
4156 if (correct == false) {
4160 /* Setting to 0 should clear them all. */
4161 status = cli_setpathinfo_ext(
4164 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* create */
4165 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* access */
4166 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* write */
4167 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* change */
4169 if (!NT_STATUS_IS_OK(status)) {
4170 printf("cli_setpathinfo_ext failed with %s\n",
4175 /* Check attributes are correct. */
4176 correct = check_attributes(cli,
4178 FILE_ATTRIBUTE_NORMAL);
4179 if (correct == false) {
4187 FILE_ATTRIBUTE_SYSTEM |
4188 FILE_ATTRIBUTE_HIDDEN|
4189 FILE_ATTRIBUTE_READONLY);
4191 if (!torture_close_connection(cli)) {
4195 printf("attrib test finished\n");
4202 This checks a couple of trans2 calls
4204 static bool run_trans2test(int dummy)
4206 struct cli_state *cli;
4209 time_t c_time, a_time, m_time;
4210 struct timespec c_time_ts, a_time_ts, m_time_ts, w_time_ts, m_time2_ts;
4211 const char *fname = "\\trans2.tst";
4212 const char *dname = "\\trans2";
4213 const char *fname2 = "\\trans2\\trans2.tst";
4215 bool correct = True;
4220 printf("starting trans2 test\n");
4222 if (!torture_open_connection(&cli, 0)) {
4226 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
4227 /* Ensure ino is zero, SMB2 gets a real one. */
4230 /* Ensure ino is -1, SMB1 never gets a real one. */
4234 status = cli_get_fs_attr_info(cli, &fs_attr);
4235 if (!NT_STATUS_IS_OK(status)) {
4236 printf("ERROR: cli_get_fs_attr_info returned %s\n",
4241 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4242 cli_openx(cli, fname, O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum);
4243 status = cli_qfileinfo_basic(cli, fnum, NULL, &size, &c_time_ts,
4244 &a_time_ts, &w_time_ts, &m_time_ts, NULL);
4245 if (!NT_STATUS_IS_OK(status)) {
4246 printf("ERROR: qfileinfo failed (%s)\n", nt_errstr(status));
4250 status = cli_qfilename(cli, fnum, talloc_tos(), &pname);
4251 if (!NT_STATUS_IS_OK(status)) {
4252 printf("ERROR: qfilename failed (%s)\n", nt_errstr(status));
4255 else if (strcmp(pname, fname)) {
4256 printf("qfilename gave different name? [%s] [%s]\n",
4261 cli_close(cli, fnum);
4265 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4266 status = cli_openx(cli, fname, O_RDWR | O_CREAT | O_TRUNC, DENY_NONE,
4268 if (!NT_STATUS_IS_OK(status)) {
4269 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
4272 cli_close(cli, fnum);
4274 status = cli_qpathinfo1(cli, fname, &c_time, &a_time, &m_time, &size,
4276 if (!NT_STATUS_IS_OK(status)) {
4277 printf("ERROR: qpathinfo failed (%s)\n", nt_errstr(status));
4280 time_t t = time(NULL);
4282 if (c_time != m_time) {
4283 printf("create time=%s", ctime(&c_time));
4284 printf("modify time=%s", ctime(&m_time));
4285 printf("This system appears to have sticky create times\n");
4287 if ((labs(a_time - t) > 60) && (a_time % (60*60) == 0)) {
4288 printf("access time=%s", ctime(&a_time));
4289 printf("This system appears to set a midnight access time\n");
4293 if (labs(m_time - t) > 60*60*24*7) {
4294 printf("ERROR: totally incorrect times - maybe word reversed? mtime=%s", ctime(&m_time));
4300 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4301 cli_openx(cli, fname,
4302 O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum);
4303 cli_close(cli, fnum);
4304 status = cli_qpathinfo2(cli, fname, &c_time_ts, &a_time_ts, &w_time_ts,
4305 &m_time_ts, &size, NULL, &ino);
4306 if (!NT_STATUS_IS_OK(status)) {
4307 printf("ERROR: qpathinfo2 failed (%s)\n", nt_errstr(status));
4310 if (w_time_ts.tv_sec < 60*60*24*2) {
4311 printf("write time=%s", ctime(&w_time_ts.tv_sec));
4312 printf("This system appears to set a initial 0 write time\n");
4315 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
4316 /* SMB2 should always return an inode. */
4318 printf("SMB2 bad inode (0)\n");
4322 /* SMB1 must always return zero here. */
4324 printf("SMB1 bad inode (!0)\n");
4330 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4333 /* check if the server updates the directory modification time
4334 when creating a new file */
4335 status = cli_mkdir(cli, dname);
4336 if (!NT_STATUS_IS_OK(status)) {
4337 printf("ERROR: mkdir failed (%s)\n", nt_errstr(status));
4341 status = cli_qpathinfo2(cli, "\\trans2\\", &c_time_ts, &a_time_ts,
4342 &w_time_ts, &m_time_ts, &size, NULL, NULL);
4343 if (!NT_STATUS_IS_OK(status)) {
4344 printf("ERROR: qpathinfo2 failed (%s)\n", nt_errstr(status));
4348 cli_openx(cli, fname2,
4349 O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum);
4350 cli_writeall(cli, fnum, 0, (uint8_t *)&fnum, 0, sizeof(fnum), NULL);
4351 cli_close(cli, fnum);
4352 status = cli_qpathinfo2(cli, "\\trans2\\", &c_time_ts, &a_time_ts,
4353 &w_time_ts, &m_time2_ts, &size, NULL, NULL);
4354 if (!NT_STATUS_IS_OK(status)) {
4355 printf("ERROR: qpathinfo2 failed (%s)\n", nt_errstr(status));
4358 if (memcmp(&m_time_ts, &m_time2_ts, sizeof(struct timespec))
4360 printf("This system does not update directory modification times\n");
4364 cli_unlink(cli, fname2, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4365 cli_rmdir(cli, dname);
4367 if (!torture_close_connection(cli)) {
4371 printf("trans2 test finished\n");
4377 This checks new W2K calls.
4380 static NTSTATUS new_trans(struct cli_state *pcli, int fnum, int level)
4382 uint8_t *buf = NULL;
4386 status = cli_qfileinfo(talloc_tos(), pcli, fnum, level, 0,
4387 CLI_BUFFER_SIZE, NULL, &buf, &len);
4388 if (!NT_STATUS_IS_OK(status)) {
4389 printf("ERROR: qfileinfo (%d) failed (%s)\n", level,
4392 printf("qfileinfo: level %d, len = %u\n", level, len);
4393 dump_data(0, (uint8_t *)buf, len);
4400 static bool run_w2ktest(int dummy)
4402 struct cli_state *cli;
4404 const char *fname = "\\w2ktest\\w2k.tst";
4406 bool correct = True;
4408 printf("starting w2k test\n");
4410 if (!torture_open_connection(&cli, 0)) {
4414 cli_openx(cli, fname,
4415 O_RDWR | O_CREAT , DENY_NONE, &fnum);
4417 for (level = 1004; level < 1040; level++) {
4418 new_trans(cli, fnum, level);
4421 cli_close(cli, fnum);
4423 if (!torture_close_connection(cli)) {
4427 printf("w2k test finished\n");
4434 this is a harness for some oplock tests
4436 static bool run_oplock1(int dummy)
4438 struct cli_state *cli1;
4439 const char *fname = "\\lockt1.lck";
4441 bool correct = True;
4444 printf("starting oplock test 1\n");
4446 if (!torture_open_connection(&cli1, 0)) {
4450 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4452 smbXcli_conn_set_sockopt(cli1->conn, sockops);
4454 cli1->use_oplocks = True;
4456 status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
4458 if (!NT_STATUS_IS_OK(status)) {
4459 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
4463 cli1->use_oplocks = False;
4465 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4466 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4468 status = cli_close(cli1, fnum1);
4469 if (!NT_STATUS_IS_OK(status)) {
4470 printf("close2 failed (%s)\n", nt_errstr(status));
4474 status = cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4475 if (!NT_STATUS_IS_OK(status)) {
4476 printf("unlink failed (%s)\n", nt_errstr(status));
4480 if (!torture_close_connection(cli1)) {
4484 printf("finished oplock test 1\n");
4489 static bool run_oplock2(int dummy)
4491 struct cli_state *cli1, *cli2;
4492 const char *fname = "\\lockt2.lck";
4493 uint16_t fnum1, fnum2;
4494 int saved_use_oplocks = use_oplocks;
4496 bool correct = True;
4497 volatile bool *shared_correct;
4501 shared_correct = (volatile bool *)anonymous_shared_allocate(sizeof(bool));
4502 *shared_correct = True;
4504 use_level_II_oplocks = True;
4507 printf("starting oplock test 2\n");
4509 if (!torture_open_connection(&cli1, 0)) {
4510 use_level_II_oplocks = False;
4511 use_oplocks = saved_use_oplocks;
4515 if (!torture_open_connection(&cli2, 1)) {
4516 use_level_II_oplocks = False;
4517 use_oplocks = saved_use_oplocks;
4521 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4523 smbXcli_conn_set_sockopt(cli1->conn, sockops);
4524 smbXcli_conn_set_sockopt(cli2->conn, sockops);
4526 status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
4528 if (!NT_STATUS_IS_OK(status)) {
4529 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
4533 /* Don't need the globals any more. */
4534 use_level_II_oplocks = False;
4535 use_oplocks = saved_use_oplocks;
4539 status = cli_openx(cli2, fname, O_RDWR, DENY_NONE, &fnum2);
4540 if (!NT_STATUS_IS_OK(status)) {
4541 printf("second open of %s failed (%s)\n", fname, nt_errstr(status));
4542 *shared_correct = False;
4548 status = cli_close(cli2, fnum2);
4549 if (!NT_STATUS_IS_OK(status)) {
4550 printf("close2 failed (%s)\n", nt_errstr(status));
4551 *shared_correct = False;
4559 /* Ensure cli1 processes the break. Empty file should always return 0
4561 status = cli_read(cli1, fnum1, buf, 0, 4, &nread);
4562 if (!NT_STATUS_IS_OK(status)) {
4563 printf("read on fnum1 failed (%s)\n", nt_errstr(status));
4565 } else if (nread != 0) {
4566 printf("read on empty fnum1 failed. recv %ld expected %d\n",
4567 (unsigned long)nread, 0);
4571 /* Should now be at level II. */
4572 /* Test if sending a write locks causes a break to none. */
4573 status = cli_lock32(cli1, fnum1, 0, 4, 0, READ_LOCK);
4574 if (!NT_STATUS_IS_OK(status)) {
4575 printf("lock failed (%s)\n", nt_errstr(status));
4579 cli_unlock(cli1, fnum1, 0, 4);
4583 status = cli_lock32(cli1, fnum1, 0, 4, 0, WRITE_LOCK);
4584 if (!NT_STATUS_IS_OK(status)) {
4585 printf("lock failed (%s)\n", nt_errstr(status));
4589 cli_unlock(cli1, fnum1, 0, 4);
4593 cli_read(cli1, fnum1, buf, 0, 4, NULL);
4595 status = cli_close(cli1, fnum1);
4596 if (!NT_STATUS_IS_OK(status)) {
4597 printf("close1 failed (%s)\n", nt_errstr(status));
4603 status = cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4604 if (!NT_STATUS_IS_OK(status)) {
4605 printf("unlink failed (%s)\n", nt_errstr(status));
4609 if (!torture_close_connection(cli1)) {
4613 if (!*shared_correct) {
4617 printf("finished oplock test 2\n");
4622 struct oplock4_state {
4623 struct tevent_context *ev;
4624 struct cli_state *cli;
4629 static void oplock4_got_break(struct tevent_req *req);
4630 static void oplock4_got_open(struct tevent_req *req);
4632 static bool run_oplock4(int dummy)
4634 struct tevent_context *ev;
4635 struct cli_state *cli1, *cli2;
4636 struct tevent_req *oplock_req, *open_req;
4637 const char *fname = "\\lockt4.lck";
4638 const char *fname_ln = "\\lockt4_ln.lck";
4639 uint16_t fnum1, fnum2;
4640 int saved_use_oplocks = use_oplocks;
4642 bool correct = true;
4646 struct oplock4_state *state;
4648 printf("starting oplock test 4\n");
4650 if (!torture_open_connection(&cli1, 0)) {
4651 use_level_II_oplocks = false;
4652 use_oplocks = saved_use_oplocks;
4656 if (!torture_open_connection(&cli2, 1)) {
4657 use_level_II_oplocks = false;
4658 use_oplocks = saved_use_oplocks;
4662 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4663 cli_unlink(cli1, fname_ln, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4665 smbXcli_conn_set_sockopt(cli1->conn, sockops);
4666 smbXcli_conn_set_sockopt(cli2->conn, sockops);
4668 /* Create the file. */
4669 status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
4671 if (!NT_STATUS_IS_OK(status)) {
4672 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
4676 status = cli_close(cli1, fnum1);
4677 if (!NT_STATUS_IS_OK(status)) {
4678 printf("close1 failed (%s)\n", nt_errstr(status));
4682 /* Now create a hardlink. */
4683 status = cli_hardlink(cli1, fname, fname_ln);
4684 if (!NT_STATUS_IS_OK(status)) {
4685 printf("nt hardlink failed (%s)\n", nt_errstr(status));
4689 /* Prove that opening hardlinks cause deny modes to conflict. */
4690 status = cli_openx(cli1, fname, O_RDWR, DENY_ALL, &fnum1);
4691 if (!NT_STATUS_IS_OK(status)) {
4692 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
4696 status = cli_openx(cli1, fname_ln, O_RDWR, DENY_NONE, &fnum2);
4697 if (NT_STATUS_IS_OK(status)) {
4698 printf("open of %s succeeded - should fail with sharing violation.\n",
4703 if (!NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
4704 printf("open of %s should fail with sharing violation. Got %s\n",
4705 fname_ln, nt_errstr(status));
4709 status = cli_close(cli1, fnum1);
4710 if (!NT_STATUS_IS_OK(status)) {
4711 printf("close1 failed (%s)\n", nt_errstr(status));
4715 cli1->use_oplocks = true;
4716 cli2->use_oplocks = true;
4718 status = cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
4719 if (!NT_STATUS_IS_OK(status)) {
4720 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
4724 ev = samba_tevent_context_init(talloc_tos());
4726 printf("tevent_context_init failed\n");
4730 state = talloc(ev, struct oplock4_state);
4731 if (state == NULL) {
4732 printf("talloc failed\n");
4737 state->got_break = &got_break;
4738 state->fnum2 = &fnum2;
4740 oplock_req = cli_smb_oplock_break_waiter_send(
4741 talloc_tos(), ev, cli1);
4742 if (oplock_req == NULL) {
4743 printf("cli_smb_oplock_break_waiter_send failed\n");
4746 tevent_req_set_callback(oplock_req, oplock4_got_break, state);
4748 open_req = cli_openx_send(
4749 talloc_tos(), ev, cli2, fname_ln, O_RDWR, DENY_NONE);
4750 if (open_req == NULL) {
4751 printf("cli_openx_send failed\n");
4754 tevent_req_set_callback(open_req, oplock4_got_open, state);
4759 while (!got_break || fnum2 == 0xffff) {
4761 ret = tevent_loop_once(ev);
4763 printf("tevent_loop_once failed: %s\n",
4769 status = cli_close(cli2, fnum2);
4770 if (!NT_STATUS_IS_OK(status)) {
4771 printf("close2 failed (%s)\n", nt_errstr(status));
4775 status = cli_close(cli1, fnum1);
4776 if (!NT_STATUS_IS_OK(status)) {
4777 printf("close1 failed (%s)\n", nt_errstr(status));
4781 status = cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4782 if (!NT_STATUS_IS_OK(status)) {
4783 printf("unlink failed (%s)\n", nt_errstr(status));
4787 status = cli_unlink(cli1, fname_ln, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4788 if (!NT_STATUS_IS_OK(status)) {
4789 printf("unlink failed (%s)\n", nt_errstr(status));
4793 if (!torture_close_connection(cli1)) {
4801 printf("finished oplock test 4\n");
4806 static void oplock4_got_break(struct tevent_req *req)
4808 struct oplock4_state *state = tevent_req_callback_data(
4809 req, struct oplock4_state);
4814 status = cli_smb_oplock_break_waiter_recv(req, &fnum, &level);
4816 if (!NT_STATUS_IS_OK(status)) {
4817 printf("cli_smb_oplock_break_waiter_recv returned %s\n",
4821 *state->got_break = true;
4823 req = cli_oplock_ack_send(state, state->ev, state->cli, fnum,
4826 printf("cli_oplock_ack_send failed\n");
4831 static void oplock4_got_open(struct tevent_req *req)
4833 struct oplock4_state *state = tevent_req_callback_data(
4834 req, struct oplock4_state);
4837 status = cli_openx_recv(req, state->fnum2);
4838 if (!NT_STATUS_IS_OK(status)) {
4839 printf("cli_openx_recv returned %s\n", nt_errstr(status));
4840 *state->fnum2 = 0xffff;
4844 #ifdef HAVE_KERNEL_OPLOCKS_LINUX
4846 struct oplock5_state {
4851 * Async open the file that has a kernel oplock, do an echo to get
4852 * that 100% across, close the file to signal to the child fd that the
4853 * oplock can be dropped, wait for the open reply.
4856 static void oplock5_opened(struct tevent_req *subreq);
4857 static void oplock5_pong(struct tevent_req *subreq);
4858 static void oplock5_timedout(struct tevent_req *subreq);
4860 static struct tevent_req *oplock5_send(
4861 TALLOC_CTX *mem_ctx,
4862 struct tevent_context *ev,
4863 struct cli_state *cli,
4867 struct tevent_req *req = NULL, *subreq = NULL;
4868 struct oplock5_state *state = NULL;
4869 static uint8_t data = 0;
4871 req = tevent_req_create(mem_ctx, &state, struct oplock5_state);
4875 state->pipe_down_fd = pipe_down_fd;
4877 subreq = cli_ntcreate_send(
4883 SEC_FILE_READ_DATA, /* DesiredAccess */
4884 FILE_ATTRIBUTE_NORMAL, /* FileAttributes */
4885 FILE_SHARE_WRITE|FILE_SHARE_READ, /* ShareAccess */
4886 FILE_OPEN, /* CreateDisposition */
4887 FILE_NON_DIRECTORY_FILE, /* CreateOptions */
4888 0, /* Impersonation */
4889 0); /* SecurityFlags */
4890 if (tevent_req_nomem(subreq, req)) {
4891 return tevent_req_post(req, ev);
4893 tevent_req_set_callback(subreq, oplock5_opened, req);
4895 subreq = cli_echo_send(
4900 (DATA_BLOB) { .data = &data, .length = sizeof(data) });
4901 if (tevent_req_nomem(subreq, req)) {
4902 return tevent_req_post(req, ev);
4904 tevent_req_set_callback(subreq, oplock5_pong, req);
4906 subreq = tevent_wakeup_send(state, ev, timeval_current_ofs(20, 0));
4907 if (tevent_req_nomem(subreq, req)) {
4908 return tevent_req_post(req, ev);
4910 tevent_req_set_callback(subreq, oplock5_timedout, req);
4915 static void oplock5_opened(struct tevent_req *subreq)
4917 struct tevent_req *req = tevent_req_callback_data(
4918 subreq, struct tevent_req);
4922 status = cli_ntcreate_recv(subreq, &fnum, NULL);
4923 TALLOC_FREE(subreq);
4924 if (tevent_req_nterror(req, status)) {
4927 tevent_req_done(req);
4930 static void oplock5_pong(struct tevent_req *subreq)
4932 struct tevent_req *req = tevent_req_callback_data(
4933 subreq, struct tevent_req);
4934 struct oplock5_state *state = tevent_req_data(
4935 req, struct oplock5_state);
4938 status = cli_echo_recv(subreq);
4939 TALLOC_FREE(subreq);
4940 if (tevent_req_nterror(req, status)) {
4944 close(state->pipe_down_fd);
4947 static void oplock5_timedout(struct tevent_req *subreq)
4949 struct tevent_req *req = tevent_req_callback_data(
4950 subreq, struct tevent_req);
4953 ok = tevent_wakeup_recv(subreq);
4954 TALLOC_FREE(subreq);
4956 tevent_req_oom(req);
4959 tevent_req_nterror(req, NT_STATUS_TIMEOUT);
4962 static NTSTATUS oplock5_recv(struct tevent_req *req)
4964 return tevent_req_simple_recv_ntstatus(req);
4967 static bool run_oplock5(int dummy)
4969 struct tevent_context *ev = NULL;
4970 struct tevent_req *req = NULL;
4971 struct cli_state *cli = NULL;
4972 const char *fname = "oplock5.txt";
4973 int pipe_down[2], pipe_up[2];
4980 printf("starting oplock5\n");
4982 if (local_path == NULL) {
4983 d_fprintf(stderr, "oplock5 must be given a local path via "
4984 "-l <localpath>\n");
4988 ret = pipe(pipe_down);
4990 d_fprintf(stderr, "pipe() failed: %s\n", strerror(errno));
4993 ret = pipe(pipe_up);
4995 d_fprintf(stderr, "pipe() failed: %s\n", strerror(errno));
5000 if (child_pid == -1) {
5001 d_fprintf(stderr, "fork() failed: %s\n", strerror(errno));
5005 if (child_pid == 0) {
5006 char *local_file = NULL;
5009 close(pipe_down[1]);
5012 local_file = talloc_asprintf(
5013 talloc_tos(), "%s/%s", local_path, fname);
5014 if (local_file == 0) {
5018 fd = open(local_file, O_RDWR|O_CREAT, 0644);
5021 "open(%s) in child failed: %s\n",
5028 signal(SIGIO, SIG_IGN);
5030 ret = fcntl(fd, F_SETLEASE, F_WRLCK);
5033 "SETLEASE in child failed: %s\n",
5040 ret = sys_write(pipe_up[1], &c, sizeof(c));
5043 "sys_write failed: %s\n",
5047 ret = sys_read(pipe_down[0], &c, sizeof(c));
5050 "sys_read failed: %s\n",
5058 close(pipe_down[0]);
5060 ret = sys_read(pipe_up[0], &c, sizeof(c));
5063 "sys_read failed: %s\n",
5068 d_fprintf(stderr, "got error code %"PRIu8"\n", c);
5072 ok = torture_open_connection(&cli, 0);
5074 d_fprintf(stderr, "torture_open_connection failed\n");
5078 ev = samba_tevent_context_init(talloc_tos());
5080 d_fprintf(stderr, "samba_tevent_context_init failed\n");
5084 req = oplock5_send(ev, ev, cli, fname, pipe_down[1]);
5086 d_fprintf(stderr, "oplock5_send failed\n");
5090 ok = tevent_req_poll_ntstatus(req, ev, &status);
5093 "tevent_req_poll_ntstatus failed: %s\n",
5098 status = oplock5_recv(req);
5100 if (!NT_STATUS_IS_OK(status)) {
5102 "oplock5 failed: %s\n",
5110 #endif /* HAVE_KERNEL_OPLOCKS_LINUX */
5113 Test delete on close semantics.
5115 static bool run_deletetest(int dummy)
5117 struct cli_state *cli1 = NULL;
5118 struct cli_state *cli2 = NULL;
5119 const char *fname = "\\delete.file";
5120 uint16_t fnum1 = (uint16_t)-1;
5121 uint16_t fnum2 = (uint16_t)-1;
5122 bool correct = false;
5125 printf("starting delete test\n");
5127 if (!torture_open_connection(&cli1, 0)) {
5131 smbXcli_conn_set_sockopt(cli1->conn, sockops);
5133 /* Test 1 - this should delete the file on close. */
5135 cli_setatr(cli1, fname, 0, 0);
5136 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5138 status = cli_ntcreate(cli1, fname, 0, GENERIC_ALL_ACCESS|DELETE_ACCESS,
5139 FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
5140 FILE_DELETE_ON_CLOSE, 0, &fnum1, NULL);
5141 if (!NT_STATUS_IS_OK(status)) {
5142 printf("[1] open of %s failed (%s)\n", fname, nt_errstr(status));
5146 status = cli_close(cli1, fnum1);
5147 if (!NT_STATUS_IS_OK(status)) {
5148 printf("[1] close failed (%s)\n", nt_errstr(status));
5152 status = cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
5153 if (NT_STATUS_IS_OK(status)) {
5154 printf("[1] open of %s succeeded (should fail)\n", fname);
5158 printf("first delete on close test succeeded.\n");
5160 /* Test 2 - this should delete the file on close. */
5162 cli_setatr(cli1, fname, 0, 0);
5163 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5165 status = cli_ntcreate(cli1, fname, 0, GENERIC_ALL_ACCESS,
5166 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
5167 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
5168 if (!NT_STATUS_IS_OK(status)) {
5169 printf("[2] open of %s failed (%s)\n", fname, nt_errstr(status));
5173 status = cli_nt_delete_on_close(cli1, fnum1, true);
5174 if (!NT_STATUS_IS_OK(status)) {
5175 printf("[2] setting delete_on_close failed (%s)\n", nt_errstr(status));
5179 status = cli_close(cli1, fnum1);
5180 if (!NT_STATUS_IS_OK(status)) {
5181 printf("[2] close failed (%s)\n", nt_errstr(status));
5185 status = cli_openx(cli1, fname, O_RDONLY, DENY_NONE, &fnum1);
5186 if (NT_STATUS_IS_OK(status)) {
5187 printf("[2] open of %s succeeded should have been deleted on close !\n", fname);
5188 status = cli_close(cli1, fnum1);
5189 if (!NT_STATUS_IS_OK(status)) {
5190 printf("[2] close failed (%s)\n", nt_errstr(status));
5192 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5196 printf("second delete on close test succeeded.\n");
5199 cli_setatr(cli1, fname, 0, 0);
5200 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5202 status = cli_ntcreate(cli1, fname, 0, GENERIC_ALL_ACCESS,
5203 FILE_ATTRIBUTE_NORMAL,
5204 FILE_SHARE_READ|FILE_SHARE_WRITE,
5205 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
5206 if (!NT_STATUS_IS_OK(status)) {
5207 printf("[3] open - 1 of %s failed (%s)\n", fname, nt_errstr(status));
5211 /* This should fail with a sharing violation - open for delete is only compatible
5212 with SHARE_DELETE. */
5214 status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
5215 FILE_ATTRIBUTE_NORMAL,
5216 FILE_SHARE_READ|FILE_SHARE_WRITE,
5217 FILE_OPEN, 0, 0, &fnum2, NULL);
5218 if (NT_STATUS_IS_OK(status)) {
5219 printf("[3] open - 2 of %s succeeded - should have failed.\n", fname);
5223 /* This should succeed. */
5224 status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
5225 FILE_ATTRIBUTE_NORMAL,
5226 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5227 FILE_OPEN, 0, 0, &fnum2, NULL);
5228 if (!NT_STATUS_IS_OK(status)) {
5229 printf("[3] open - 3 of %s failed (%s)\n", fname, nt_errstr(status));
5233 status = cli_nt_delete_on_close(cli1, fnum1, true);
5234 if (!NT_STATUS_IS_OK(status)) {
5235 printf("[3] setting delete_on_close failed (%s)\n", nt_errstr(status));
5239 status = cli_close(cli1, fnum1);
5240 if (!NT_STATUS_IS_OK(status)) {
5241 printf("[3] close 1 failed (%s)\n", nt_errstr(status));
5245 status = cli_close(cli1, fnum2);
5246 if (!NT_STATUS_IS_OK(status)) {
5247 printf("[3] close 2 failed (%s)\n", nt_errstr(status));
5251 /* This should fail - file should no longer be there. */
5253 status = cli_openx(cli1, fname, O_RDONLY, DENY_NONE, &fnum1);
5254 if (NT_STATUS_IS_OK(status)) {
5255 printf("[3] open of %s succeeded should have been deleted on close !\n", fname);
5256 status = cli_close(cli1, fnum1);
5257 if (!NT_STATUS_IS_OK(status)) {
5258 printf("[3] close failed (%s)\n", nt_errstr(status));
5260 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5264 printf("third delete on close test succeeded.\n");
5267 cli_setatr(cli1, fname, 0, 0);
5268 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5270 status = cli_ntcreate(cli1, fname, 0,
5271 FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
5272 FILE_ATTRIBUTE_NORMAL,
5273 FILE_SHARE_READ|FILE_SHARE_WRITE,
5274 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
5275 if (!NT_STATUS_IS_OK(status)) {
5276 printf("[4] open of %s failed (%s)\n", fname, nt_errstr(status));
5280 /* This should succeed. */
5281 status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
5282 FILE_ATTRIBUTE_NORMAL,
5283 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5284 FILE_OPEN, 0, 0, &fnum2, NULL);
5285 if (!NT_STATUS_IS_OK(status)) {
5286 printf("[4] open - 2 of %s failed (%s)\n", fname, nt_errstr(status));
5290 status = cli_close(cli1, fnum2);
5291 if (!NT_STATUS_IS_OK(status)) {
5292 printf("[4] close - 1 failed (%s)\n", nt_errstr(status));
5296 status = cli_nt_delete_on_close(cli1, fnum1, true);
5297 if (!NT_STATUS_IS_OK(status)) {
5298 printf("[4] setting delete_on_close failed (%s)\n", nt_errstr(status));
5302 /* This should fail - no more opens once delete on close set. */
5303 status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
5304 FILE_ATTRIBUTE_NORMAL,
5305 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5306 FILE_OPEN, 0, 0, &fnum2, NULL);
5307 if (NT_STATUS_IS_OK(status)) {
5308 printf("[4] open - 3 of %s succeeded ! Should have failed.\n", fname );
5312 status = cli_close(cli1, fnum1);
5313 if (!NT_STATUS_IS_OK(status)) {
5314 printf("[4] close - 2 failed (%s)\n", nt_errstr(status));
5318 printf("fourth delete on close test succeeded.\n");
5321 cli_setatr(cli1, fname, 0, 0);
5322 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5324 status = cli_openx(cli1, fname, O_RDWR|O_CREAT, DENY_NONE, &fnum1);
5325 if (!NT_STATUS_IS_OK(status)) {
5326 printf("[5] open of %s failed (%s)\n", fname, nt_errstr(status));
5330 /* This should fail - only allowed on NT opens with DELETE access. */
5332 status = cli_nt_delete_on_close(cli1, fnum1, true);
5333 if (NT_STATUS_IS_OK(status)) {
5334 printf("[5] setting delete_on_close on OpenX file succeeded - should fail !\n");
5338 status = cli_close(cli1, fnum1);
5339 if (!NT_STATUS_IS_OK(status)) {
5340 printf("[5] close failed (%s)\n", nt_errstr(status));
5344 printf("fifth delete on close test succeeded.\n");
5347 cli_setatr(cli1, fname, 0, 0);
5348 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5350 status = cli_ntcreate(cli1, fname, 0, FILE_READ_DATA|FILE_WRITE_DATA,
5351 FILE_ATTRIBUTE_NORMAL,
5352 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5353 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
5354 if (!NT_STATUS_IS_OK(status)) {
5355 printf("[6] open of %s failed (%s)\n", fname,
5360 /* This should fail - only allowed on NT opens with DELETE access. */
5362 status = cli_nt_delete_on_close(cli1, fnum1, true);
5363 if (NT_STATUS_IS_OK(status)) {
5364 printf("[6] setting delete_on_close on file with no delete access succeeded - should fail !\n");
5368 status = cli_close(cli1, fnum1);
5369 if (!NT_STATUS_IS_OK(status)) {
5370 printf("[6] close failed (%s)\n", nt_errstr(status));
5374 printf("sixth delete on close test succeeded.\n");
5377 cli_setatr(cli1, fname, 0, 0);
5378 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5380 status = cli_ntcreate(cli1, fname, 0,
5381 FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
5382 FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
5383 0, 0, &fnum1, NULL);
5384 if (!NT_STATUS_IS_OK(status)) {
5385 printf("[7] open of %s failed (%s)\n", fname, nt_errstr(status));
5389 status = cli_nt_delete_on_close(cli1, fnum1, true);
5390 if (!NT_STATUS_IS_OK(status)) {
5391 printf("[7] setting delete_on_close on file failed !\n");
5395 status = cli_nt_delete_on_close(cli1, fnum1, false);
5396 if (!NT_STATUS_IS_OK(status)) {
5397 printf("[7] unsetting delete_on_close on file failed !\n");
5401 status = cli_close(cli1, fnum1);
5402 if (!NT_STATUS_IS_OK(status)) {
5403 printf("[7] close - 1 failed (%s)\n", nt_errstr(status));
5407 /* This next open should succeed - we reset the flag. */
5408 status = cli_openx(cli1, fname, O_RDONLY, DENY_NONE, &fnum1);
5409 if (!NT_STATUS_IS_OK(status)) {
5410 printf("[7] open of %s failed (%s)\n", fname, nt_errstr(status));
5414 status = cli_close(cli1, fnum1);
5415 if (!NT_STATUS_IS_OK(status)) {
5416 printf("[7] close - 2 failed (%s)\n", nt_errstr(status));
5420 printf("seventh delete on close test succeeded.\n");
5423 cli_setatr(cli1, fname, 0, 0);
5424 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5426 if (!torture_open_connection(&cli2, 1)) {
5427 printf("[8] failed to open second connection.\n");
5431 smbXcli_conn_set_sockopt(cli1->conn, sockops);
5433 status = cli_ntcreate(cli1, fname, 0,
5434 FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
5435 FILE_ATTRIBUTE_NORMAL,
5436 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5437 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
5438 if (!NT_STATUS_IS_OK(status)) {
5439 printf("[8] open 1 of %s failed (%s)\n", fname, nt_errstr(status));
5443 status = cli_ntcreate(cli2, fname, 0,
5444 FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
5445 FILE_ATTRIBUTE_NORMAL,
5446 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5447 FILE_OPEN, 0, 0, &fnum2, NULL);
5448 if (!NT_STATUS_IS_OK(status)) {
5449 printf("[8] open 2 of %s failed (%s)\n", fname, nt_errstr(status));
5453 status = cli_nt_delete_on_close(cli1, fnum1, true);
5454 if (!NT_STATUS_IS_OK(status)) {
5455 printf("[8] setting delete_on_close on file failed !\n");
5459 status = cli_close(cli1, fnum1);
5460 if (!NT_STATUS_IS_OK(status)) {
5461 printf("[8] close - 1 failed (%s)\n", nt_errstr(status));
5465 status = cli_close(cli2, fnum2);
5466 if (!NT_STATUS_IS_OK(status)) {
5467 printf("[8] close - 2 failed (%s)\n", nt_errstr(status));
5471 /* This should fail.. */
5472 status = cli_openx(cli1, fname, O_RDONLY, DENY_NONE, &fnum1);
5473 if (NT_STATUS_IS_OK(status)) {
5474 printf("[8] open of %s succeeded should have been deleted on close !\n", fname);
5478 printf("eighth delete on close test succeeded.\n");
5482 /* This should fail - we need to set DELETE_ACCESS. */
5483 status = cli_ntcreate(cli1, fname, 0, FILE_READ_DATA|FILE_WRITE_DATA,
5484 FILE_ATTRIBUTE_NORMAL,
5487 FILE_DELETE_ON_CLOSE, 0, &fnum1, NULL);
5488 if (NT_STATUS_IS_OK(status)) {
5489 printf("[9] open of %s succeeded should have failed!\n", fname);
5493 printf("ninth delete on close test succeeded.\n");
5497 status = cli_ntcreate(cli1, fname, 0,
5498 FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
5499 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
5500 FILE_OVERWRITE_IF, FILE_DELETE_ON_CLOSE,
5502 if (!NT_STATUS_IS_OK(status)) {
5503 printf("[10] open of %s failed (%s)\n", fname, nt_errstr(status));
5507 /* This should delete the file. */
5508 status = cli_close(cli1, fnum1);
5509 if (!NT_STATUS_IS_OK(status)) {
5510 printf("[10] close failed (%s)\n", nt_errstr(status));
5514 /* This should fail.. */
5515 status = cli_openx(cli1, fname, O_RDONLY, DENY_NONE, &fnum1);
5516 if (NT_STATUS_IS_OK(status)) {
5517 printf("[10] open of %s succeeded should have been deleted on close !\n", fname);
5521 printf("tenth delete on close test succeeded.\n");
5525 cli_setatr(cli1, fname, 0, 0);
5526 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5528 /* Can we open a read-only file with delete access? */
5530 /* Create a readonly file. */
5531 status = cli_ntcreate(cli1, fname, 0, FILE_READ_DATA|FILE_WRITE_DATA,
5532 FILE_ATTRIBUTE_READONLY, FILE_SHARE_NONE,
5533 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
5534 if (!NT_STATUS_IS_OK(status)) {
5535 printf("[11] open of %s failed (%s)\n", fname, nt_errstr(status));
5539 status = cli_close(cli1, fnum1);
5540 if (!NT_STATUS_IS_OK(status)) {
5541 printf("[11] close failed (%s)\n", nt_errstr(status));
5545 /* Now try open for delete access. */
5546 status = cli_ntcreate(cli1, fname, 0,
5547 FILE_READ_ATTRIBUTES|DELETE_ACCESS,
5549 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5550 FILE_OPEN, 0, 0, &fnum1, NULL);
5551 if (!NT_STATUS_IS_OK(status)) {
5552 printf("[11] open of %s failed: %s\n", fname, nt_errstr(status));
5556 cli_close(cli1, fnum1);
5558 printf("eleventh delete on close test succeeded.\n");
5562 * like test 4 but with initial delete on close
5565 cli_setatr(cli1, fname, 0, 0);
5566 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5568 status = cli_ntcreate(cli1, fname, 0,
5569 FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
5570 FILE_ATTRIBUTE_NORMAL,
5571 FILE_SHARE_READ|FILE_SHARE_WRITE,
5573 FILE_DELETE_ON_CLOSE, 0, &fnum1, NULL);
5574 if (!NT_STATUS_IS_OK(status)) {
5575 printf("[12] open 1 of %s failed (%s)\n", fname, nt_errstr(status));
5579 status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
5580 FILE_ATTRIBUTE_NORMAL,
5581 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5582 FILE_OPEN, 0, 0, &fnum2, NULL);
5583 if (!NT_STATUS_IS_OK(status)) {
5584 printf("[12] open 2 of %s failed(%s).\n", fname, nt_errstr(status));
5588 status = cli_close(cli1, fnum2);
5589 if (!NT_STATUS_IS_OK(status)) {
5590 printf("[12] close 1 failed (%s)\n", nt_errstr(status));
5594 status = cli_nt_delete_on_close(cli1, fnum1, true);
5595 if (!NT_STATUS_IS_OK(status)) {
5596 printf("[12] setting delete_on_close failed (%s)\n", nt_errstr(status));
5600 /* This should fail - no more opens once delete on close set. */
5601 status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
5602 FILE_ATTRIBUTE_NORMAL,
5603 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5604 FILE_OPEN, 0, 0, &fnum2, NULL);
5605 if (NT_STATUS_IS_OK(status)) {
5606 printf("[12] open 3 of %s succeeded - should fail).\n", fname);
5610 status = cli_nt_delete_on_close(cli1, fnum1, false);
5611 if (!NT_STATUS_IS_OK(status)) {
5612 printf("[12] unsetting delete_on_close failed (%s)\n", nt_errstr(status));
5616 status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
5617 FILE_ATTRIBUTE_NORMAL,
5618 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5619 FILE_OPEN, 0, 0, &fnum2, NULL);
5620 if (!NT_STATUS_IS_OK(status)) {
5621 printf("[12] open 4 of %s failed (%s)\n", fname, nt_errstr(status));
5625 status = cli_close(cli1, fnum2);
5626 if (!NT_STATUS_IS_OK(status)) {
5627 printf("[12] close 2 failed (%s)\n", nt_errstr(status));
5631 status = cli_close(cli1, fnum1);
5632 if (!NT_STATUS_IS_OK(status)) {
5633 printf("[12] close 3 failed (%s)\n", nt_errstr(status));
5638 * setting delete on close on the handle does
5639 * not unset the initial delete on close...
5641 status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
5642 FILE_ATTRIBUTE_NORMAL,
5643 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5644 FILE_OPEN, 0, 0, &fnum2, NULL);
5645 if (NT_STATUS_IS_OK(status)) {
5646 printf("[12] open 5 of %s succeeded - should fail).\n", fname);
5648 } else if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
5649 printf("ntcreate returned %s, expected "
5650 "NT_STATUS_OBJECT_NAME_NOT_FOUND\n",
5655 printf("twelfth delete on close test succeeded.\n");
5658 printf("finished delete test\n");
5663 /* FIXME: This will crash if we aborted before cli2 got
5664 * intialized, because these functions don't handle
5665 * uninitialized connections. */
5667 if (fnum1 != (uint16_t)-1) cli_close(cli1, fnum1);
5668 if (fnum2 != (uint16_t)-1) cli_close(cli1, fnum2);
5669 cli_setatr(cli1, fname, 0, 0);
5670 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5672 if (cli1 && !torture_close_connection(cli1)) {
5675 if (cli2 && !torture_close_connection(cli2)) {
5681 struct delete_stream_state {
5685 static void delete_stream_unlinked(struct tevent_req *subreq);
5686 static void delete_stream_closed(struct tevent_req *subreq);
5688 static struct tevent_req *delete_stream_send(
5689 TALLOC_CTX *mem_ctx,
5690 struct tevent_context *ev,
5691 struct cli_state *cli,
5692 const char *base_fname,
5693 uint16_t stream_fnum)
5695 struct tevent_req *req = NULL, *subreq = NULL;
5696 struct delete_stream_state *state = NULL;
5698 req = tevent_req_create(
5699 mem_ctx, &state, struct delete_stream_state);
5704 subreq = cli_unlink_send(
5709 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5710 if (tevent_req_nomem(subreq, req)) {
5711 return tevent_req_post(req, ev);
5713 tevent_req_set_callback(subreq, delete_stream_unlinked, req);
5715 subreq = cli_close_send(state, ev, cli, stream_fnum);
5716 if (tevent_req_nomem(subreq, req)) {
5717 return tevent_req_post(req, ev);
5719 tevent_req_set_callback(subreq, delete_stream_closed, req);
5724 static void delete_stream_unlinked(struct tevent_req *subreq)
5726 struct tevent_req *req = tevent_req_callback_data(
5727 subreq, struct tevent_req);
5728 struct delete_stream_state *state = tevent_req_data(
5729 req, struct delete_stream_state);
5732 status = cli_unlink_recv(subreq);
5733 TALLOC_FREE(subreq);
5734 if (!NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
5735 printf("cli_unlink returned %s\n",
5737 tevent_req_nterror(req, NT_STATUS_UNSUCCESSFUL);
5740 if (!state->closed) {
5741 /* close reply should have come in first */
5742 printf("Not closed\n");
5743 tevent_req_nterror(req, NT_STATUS_UNSUCCESSFUL);
5746 tevent_req_done(req);
5749 static void delete_stream_closed(struct tevent_req *subreq)
5751 struct tevent_req *req = tevent_req_callback_data(
5752 subreq, struct tevent_req);
5753 struct delete_stream_state *state = tevent_req_data(
5754 req, struct delete_stream_state);
5757 status = cli_close_recv(subreq);
5758 TALLOC_FREE(subreq);
5759 if (tevent_req_nterror(req, status)) {
5762 /* also waiting for the unlink to come back */
5763 state->closed = true;
5766 static NTSTATUS delete_stream_recv(struct tevent_req *req)
5768 return tevent_req_simple_recv_ntstatus(req);
5771 static bool run_delete_stream(int dummy)
5773 struct tevent_context *ev = NULL;
5774 struct tevent_req *req = NULL;
5775 struct cli_state *cli = NULL;
5776 const char fname[] = "delete_stream";
5777 const char fname_stream[] = "delete_stream:Zone.Identifier:$DATA";
5778 uint16_t fnum1, fnum2;
5782 printf("Starting stream delete test\n");
5784 ok = torture_open_connection(&cli, 0);
5789 cli_setatr(cli, fname, 0, 0);
5790 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5792 /* Create the file. */
5793 status = cli_ntcreate(
5797 READ_CONTROL_ACCESS,
5799 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5805 if (!NT_STATUS_IS_OK(status)) {
5807 "cli_ntcreate of %s failed (%s)\n",
5812 status = cli_close(cli, fnum1);
5813 if (!NT_STATUS_IS_OK(status)) {
5815 "cli_close of %s failed (%s)\n",
5821 /* Now create the stream. */
5822 status = cli_ntcreate(
5828 FILE_SHARE_READ|FILE_SHARE_WRITE,
5835 if (!NT_STATUS_IS_OK(status)) {
5837 "cli_ntcreate of %s failed (%s)\n",
5843 /* open it a second time */
5845 status = cli_ntcreate(
5851 FILE_SHARE_READ|FILE_SHARE_WRITE,
5858 if (!NT_STATUS_IS_OK(status)) {
5860 "2nd cli_ntcreate of %s failed (%s)\n",
5866 ev = samba_tevent_context_init(talloc_tos());
5868 d_fprintf(stderr, "samba_tevent_context_init failed\n");
5872 req = delete_stream_send(ev, ev, cli, fname, fnum1);
5874 d_fprintf(stderr, "delete_stream_send failed\n");
5878 ok = tevent_req_poll_ntstatus(req, ev, &status);
5881 "tevent_req_poll_ntstatus failed: %s\n",
5886 status = delete_stream_recv(req);
5888 if (!NT_STATUS_IS_OK(status)) {
5890 "delete_stream failed: %s\n",
5895 status = cli_close(cli, fnum2);
5896 if (!NT_STATUS_IS_OK(status)) {
5898 "close failed: %s\n",
5903 status = cli_unlink(
5904 cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5905 if (!NT_STATUS_IS_OK(status)) {
5907 "unlink failed: %s\n",
5916 Exercise delete on close semantics - use on the PRINT1 share in torture
5919 static bool run_delete_print_test(int dummy)
5921 struct cli_state *cli1 = NULL;
5922 const char *fname = "print_delete.file";
5923 uint16_t fnum1 = (uint16_t)-1;
5924 bool correct = false;
5925 const char *buf = "print file data\n";
5928 printf("starting print delete test\n");
5930 if (!torture_open_connection(&cli1, 0)) {
5934 smbXcli_conn_set_sockopt(cli1->conn, sockops);
5936 status = cli_ntcreate(cli1, fname, 0, GENERIC_ALL_ACCESS|DELETE_ACCESS,
5937 FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
5938 0, 0, &fnum1, NULL);
5939 if (!NT_STATUS_IS_OK(status)) {
5940 printf("open of %s failed (%s)\n",
5946 status = cli_writeall(cli1,
5949 (const uint8_t *)buf,
5951 strlen(buf), /* size */
5953 if (!NT_STATUS_IS_OK(status)) {
5954 printf("writing print file data failed (%s)\n",
5959 status = cli_nt_delete_on_close(cli1, fnum1, true);
5960 if (!NT_STATUS_IS_OK(status)) {
5961 printf("setting delete_on_close failed (%s)\n",
5966 status = cli_close(cli1, fnum1);
5967 if (!NT_STATUS_IS_OK(status)) {
5968 printf("close failed (%s)\n", nt_errstr(status));
5972 printf("finished print delete test\n");
5978 if (fnum1 != (uint16_t)-1) {
5979 cli_close(cli1, fnum1);
5982 if (cli1 && !torture_close_connection(cli1)) {
5989 Test wildcard delete.
5991 static bool run_wild_deletetest(int dummy)
5993 struct cli_state *cli = NULL;
5994 const char *dname = "\\WTEST";
5995 const char *fname = "\\WTEST\\A";
5996 const char *wunlink_name = "\\WTEST\\*";
5997 uint16_t fnum1 = (uint16_t)-1;
5998 bool correct = false;
6001 printf("starting wildcard delete test\n");
6003 if (!torture_open_connection(&cli, 0)) {
6007 smbXcli_conn_set_sockopt(cli->conn, sockops);
6009 cli_unlink(cli, fname, 0);
6010 cli_rmdir(cli, dname);
6011 status = cli_mkdir(cli, dname);
6012 if (!NT_STATUS_IS_OK(status)) {
6013 printf("mkdir of %s failed %s!\n", dname, nt_errstr(status));
6016 status = cli_openx(cli, fname, O_CREAT|O_RDONLY, DENY_NONE, &fnum1);
6017 if (!NT_STATUS_IS_OK(status)) {
6018 printf("open of %s failed %s!\n", fname, nt_errstr(status));
6021 status = cli_close(cli, fnum1);
6025 * Note the unlink attribute-type of zero. This should
6026 * map into FILE_ATTRIBUTE_NORMAL at the server even
6027 * on a wildcard delete.
6030 status = cli_unlink(cli, wunlink_name, 0);
6031 if (!NT_STATUS_IS_OK(status)) {
6032 printf("unlink of %s failed %s!\n",
6033 wunlink_name, nt_errstr(status));
6037 printf("finished wildcard delete test\n");
6043 if (fnum1 != (uint16_t)-1) cli_close(cli, fnum1);
6044 cli_unlink(cli, fname, 0);
6045 cli_rmdir(cli, dname);
6047 if (cli && !torture_close_connection(cli)) {
6053 static bool run_deletetest_ln(int dummy)
6055 struct cli_state *cli;
6056 const char *fname = "\\delete1";
6057 const char *fname_ln = "\\delete1_ln";
6061 bool correct = true;
6064 printf("starting deletetest-ln\n");
6066 if (!torture_open_connection(&cli, 0)) {
6070 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6071 cli_unlink(cli, fname_ln, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6073 smbXcli_conn_set_sockopt(cli->conn, sockops);
6075 /* Create the file. */
6076 status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
6077 if (!NT_STATUS_IS_OK(status)) {
6078 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
6082 status = cli_close(cli, fnum);
6083 if (!NT_STATUS_IS_OK(status)) {
6084 printf("close1 failed (%s)\n", nt_errstr(status));
6088 /* Now create a hardlink. */
6089 status = cli_hardlink(cli, fname, fname_ln);
6090 if (!NT_STATUS_IS_OK(status)) {
6091 printf("nt hardlink failed (%s)\n", nt_errstr(status));
6095 /* Open the original file. */
6096 status = cli_ntcreate(cli, fname, 0, FILE_READ_DATA,
6097 FILE_ATTRIBUTE_NORMAL,
6098 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6099 FILE_OPEN_IF, 0, 0, &fnum, NULL);
6100 if (!NT_STATUS_IS_OK(status)) {
6101 printf("ntcreate of %s failed (%s)\n", fname, nt_errstr(status));
6105 /* Unlink the hard link path. */
6106 status = cli_ntcreate(cli, fname_ln, 0, DELETE_ACCESS,
6107 FILE_ATTRIBUTE_NORMAL,
6108 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6109 FILE_OPEN_IF, 0, 0, &fnum1, NULL);
6110 if (!NT_STATUS_IS_OK(status)) {
6111 printf("ntcreate of %s failed (%s)\n", fname_ln, nt_errstr(status));
6114 status = cli_nt_delete_on_close(cli, fnum1, true);
6115 if (!NT_STATUS_IS_OK(status)) {
6116 d_printf("(%s) failed to set delete_on_close %s: %s\n",
6117 __location__, fname_ln, nt_errstr(status));
6121 status = cli_close(cli, fnum1);
6122 if (!NT_STATUS_IS_OK(status)) {
6123 printf("close %s failed (%s)\n",
6124 fname_ln, nt_errstr(status));
6128 status = cli_close(cli, fnum);
6129 if (!NT_STATUS_IS_OK(status)) {
6130 printf("close %s failed (%s)\n",
6131 fname, nt_errstr(status));
6135 /* Ensure the original file is still there. */
6136 status = cli_getatr(cli, fname, NULL, NULL, &t);
6137 if (!NT_STATUS_IS_OK(status)) {
6138 printf("%s getatr on file %s failed (%s)\n",
6145 /* Ensure the link path is gone. */
6146 status = cli_getatr(cli, fname_ln, NULL, NULL, &t);
6147 if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
6148 printf("%s, getatr for file %s returned wrong error code %s "
6149 "- should have been deleted\n",
6151 fname_ln, nt_errstr(status));
6155 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6156 cli_unlink(cli, fname_ln, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6158 if (!torture_close_connection(cli)) {
6162 printf("finished deletetest-ln\n");
6168 print out server properties
6170 static bool run_properties(int dummy)
6172 struct cli_state *cli;
6173 bool correct = True;
6175 printf("starting properties test\n");
6179 if (!torture_open_connection(&cli, 0)) {
6183 smbXcli_conn_set_sockopt(cli->conn, sockops);
6185 d_printf("Capabilities 0x%08x\n", smb1cli_conn_capabilities(cli->conn));
6187 if (!torture_close_connection(cli)) {
6196 /* FIRST_DESIRED_ACCESS 0xf019f */
6197 #define FIRST_DESIRED_ACCESS FILE_READ_DATA|FILE_WRITE_DATA|FILE_APPEND_DATA|\
6198 FILE_READ_EA| /* 0xf */ \
6199 FILE_WRITE_EA|FILE_READ_ATTRIBUTES| /* 0x90 */ \
6200 FILE_WRITE_ATTRIBUTES| /* 0x100 */ \
6201 DELETE_ACCESS|READ_CONTROL_ACCESS|\
6202 WRITE_DAC_ACCESS|WRITE_OWNER_ACCESS /* 0xf0000 */
6203 /* SECOND_DESIRED_ACCESS 0xe0080 */
6204 #define SECOND_DESIRED_ACCESS FILE_READ_ATTRIBUTES| /* 0x80 */ \
6205 READ_CONTROL_ACCESS|WRITE_DAC_ACCESS|\
6206 WRITE_OWNER_ACCESS /* 0xe0000 */
6209 #define THIRD_DESIRED_ACCESS FILE_READ_ATTRIBUTES| /* 0x80 */ \
6210 READ_CONTROL_ACCESS|WRITE_DAC_ACCESS|\
6212 WRITE_OWNER_ACCESS /* */
6216 Test ntcreate calls made by xcopy
6218 static bool run_xcopy(int dummy)
6220 static struct cli_state *cli1;
6221 const char *fname = "\\test.txt";
6222 bool correct = True;
6223 uint16_t fnum1, fnum2;
6226 printf("starting xcopy test\n");
6228 if (!torture_open_connection(&cli1, 0)) {
6232 status = cli_ntcreate(cli1, fname, 0, FIRST_DESIRED_ACCESS,
6233 FILE_ATTRIBUTE_ARCHIVE, FILE_SHARE_NONE,
6234 FILE_OVERWRITE_IF, 0x4044, 0, &fnum1, NULL);
6235 if (!NT_STATUS_IS_OK(status)) {
6236 printf("First open failed - %s\n", nt_errstr(status));
6240 status = cli_ntcreate(cli1, fname, 0, SECOND_DESIRED_ACCESS, 0,
6241 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6242 FILE_OPEN, 0x200000, 0, &fnum2, NULL);
6243 if (!NT_STATUS_IS_OK(status)) {
6244 printf("second open failed - %s\n", nt_errstr(status));
6248 if (!torture_close_connection(cli1)) {
6256 Test rename on files open with share delete and no share delete.
6258 static bool run_rename(int dummy)
6260 static struct cli_state *cli1;
6261 const char *fname = "\\test.txt";
6262 const char *fname1 = "\\test1.txt";
6263 bool correct = True;
6268 printf("starting rename test\n");
6270 if (!torture_open_connection(&cli1, 0)) {
6274 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6275 cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6277 status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
6278 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ,
6279 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
6280 if (!NT_STATUS_IS_OK(status)) {
6281 printf("First open failed - %s\n", nt_errstr(status));
6285 status = cli_rename(cli1, fname, fname1, false);
6286 if (!NT_STATUS_IS_OK(status)) {
6287 printf("First rename failed (SHARE_READ) (this is correct) - %s\n", nt_errstr(status));
6289 printf("First rename succeeded (SHARE_READ) - this should have failed !\n");
6293 status = cli_close(cli1, fnum1);
6294 if (!NT_STATUS_IS_OK(status)) {
6295 printf("close - 1 failed (%s)\n", nt_errstr(status));
6299 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6300 cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6301 status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS, FILE_ATTRIBUTE_NORMAL,
6303 FILE_SHARE_DELETE|FILE_SHARE_NONE,
6305 FILE_SHARE_DELETE|FILE_SHARE_READ,
6307 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
6308 if (!NT_STATUS_IS_OK(status)) {
6309 printf("Second open failed - %s\n", nt_errstr(status));
6313 status = cli_rename(cli1, fname, fname1, false);
6314 if (!NT_STATUS_IS_OK(status)) {
6315 printf("Second rename failed (SHARE_DELETE | SHARE_READ) - this should have succeeded - %s\n", nt_errstr(status));
6318 printf("Second rename succeeded (SHARE_DELETE | SHARE_READ)\n");
6321 status = cli_close(cli1, fnum1);
6322 if (!NT_STATUS_IS_OK(status)) {
6323 printf("close - 2 failed (%s)\n", nt_errstr(status));
6327 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6328 cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6330 status = cli_ntcreate(cli1, fname, 0, READ_CONTROL_ACCESS,
6331 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
6332 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
6333 if (!NT_STATUS_IS_OK(status)) {
6334 printf("Third open failed - %s\n", nt_errstr(status));
6339 status = cli_rename(cli1, fname, fname1, false);
6340 if (!NT_STATUS_IS_OK(status)) {
6341 printf("Third rename failed (SHARE_NONE) - this should have succeeded - %s\n", nt_errstr(status));
6344 printf("Third rename succeeded (SHARE_NONE)\n");
6347 status = cli_close(cli1, fnum1);
6348 if (!NT_STATUS_IS_OK(status)) {
6349 printf("close - 3 failed (%s)\n", nt_errstr(status));
6353 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6354 cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6358 status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
6359 FILE_ATTRIBUTE_NORMAL,
6360 FILE_SHARE_READ | FILE_SHARE_WRITE,
6361 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
6362 if (!NT_STATUS_IS_OK(status)) {
6363 printf("Fourth open failed - %s\n", nt_errstr(status));
6367 status = cli_rename(cli1, fname, fname1, false);
6368 if (!NT_STATUS_IS_OK(status)) {
6369 printf("Fourth rename failed (SHARE_READ | SHARE_WRITE) (this is correct) - %s\n", nt_errstr(status));
6371 printf("Fourth rename succeeded (SHARE_READ | SHARE_WRITE) - this should have failed !\n");
6375 status = cli_close(cli1, fnum1);
6376 if (!NT_STATUS_IS_OK(status)) {
6377 printf("close - 4 failed (%s)\n", nt_errstr(status));
6381 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6382 cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6386 status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
6387 FILE_ATTRIBUTE_NORMAL,
6388 FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
6389 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
6390 if (!NT_STATUS_IS_OK(status)) {
6391 printf("Fifth open failed - %s\n", nt_errstr(status));
6395 status = cli_rename(cli1, fname, fname1, false);
6396 if (!NT_STATUS_IS_OK(status)) {
6397 printf("Fifth rename failed (SHARE_READ | SHARE_WRITE | SHARE_DELETE) - this should have succeeded - %s ! \n", nt_errstr(status));
6400 printf("Fifth rename succeeded (SHARE_READ | SHARE_WRITE | SHARE_DELETE) (this is correct) - %s\n", nt_errstr(status));
6404 status = cli_close(cli1, fnum1);
6405 if (!NT_STATUS_IS_OK(status)) {
6406 printf("close - 5 failed (%s)\n", nt_errstr(status));
6410 /* Check that the renamed file has FILE_ATTRIBUTE_ARCHIVE. */
6411 status = cli_getatr(cli1, fname1, &attr, NULL, NULL);
6412 if (!NT_STATUS_IS_OK(status)) {
6413 printf("getatr on file %s failed - %s ! \n",
6414 fname1, nt_errstr(status));
6417 if (attr != FILE_ATTRIBUTE_ARCHIVE) {
6418 printf("Renamed file %s has wrong attr 0x%x "
6419 "(should be 0x%x)\n",
6422 (unsigned int)FILE_ATTRIBUTE_ARCHIVE);
6425 printf("Renamed file %s has archive bit set\n", fname1);
6429 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6430 cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6432 if (!torture_close_connection(cli1)) {
6440 Test rename into a directory with an ACL denying it.
6442 static bool run_rename_access(int dummy)
6444 static struct cli_state *cli = NULL;
6445 static struct cli_state *posix_cli = NULL;
6446 const char *src = "test.txt";
6447 const char *dname = "dir";
6448 const char *dst = "dir\\test.txt";
6449 const char *dsrc = "test.dir";
6450 const char *ddst = "dir\\test.dir";
6451 uint16_t fnum = (uint16_t)-1;
6452 struct security_descriptor *sd = NULL;
6453 struct security_descriptor *newsd = NULL;
6455 TALLOC_CTX *frame = NULL;
6457 frame = talloc_stackframe();
6458 printf("starting rename access test\n");
6460 /* Windows connection. */
6461 if (!torture_open_connection(&cli, 0)) {
6465 smbXcli_conn_set_sockopt(cli->conn, sockops);
6467 /* Posix connection. */
6468 if (!torture_open_connection(&posix_cli, 0)) {
6472 smbXcli_conn_set_sockopt(posix_cli->conn, sockops);
6474 status = torture_setup_unix_extensions(posix_cli);
6475 if (!NT_STATUS_IS_OK(status)) {
6479 /* Start with a clean slate. */
6480 cli_unlink(cli, src, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6481 cli_unlink(cli, dst, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6482 cli_rmdir(cli, dsrc);
6483 cli_rmdir(cli, ddst);
6484 cli_rmdir(cli, dname);
6487 * Setup the destination directory with a DENY ACE to
6488 * prevent new files within it.
6490 status = cli_ntcreate(cli,
6493 FILE_READ_ATTRIBUTES|READ_CONTROL_ACCESS|
6494 WRITE_DAC_ACCESS|FILE_READ_DATA|
6496 FILE_ATTRIBUTE_DIRECTORY,
6497 FILE_SHARE_READ|FILE_SHARE_WRITE,
6499 FILE_DIRECTORY_FILE,
6503 if (!NT_STATUS_IS_OK(status)) {
6504 printf("Create of %s - %s\n", dname, nt_errstr(status));
6508 status = cli_query_secdesc(cli,
6512 if (!NT_STATUS_IS_OK(status)) {
6513 printf("cli_query_secdesc failed for %s (%s)\n",
6514 dname, nt_errstr(status));
6518 newsd = security_descriptor_dacl_create(frame,
6523 SEC_ACE_TYPE_ACCESS_DENIED,
6524 SEC_DIR_ADD_FILE|SEC_DIR_ADD_SUBDIR,
6527 if (newsd == NULL) {
6530 sd->dacl = security_acl_concatenate(frame,
6533 if (sd->dacl == NULL) {
6536 status = cli_set_secdesc(cli, fnum, sd);
6537 if (!NT_STATUS_IS_OK(status)) {
6538 printf("cli_set_secdesc failed for %s (%s)\n",
6539 dname, nt_errstr(status));
6542 status = cli_close(cli, fnum);
6543 if (!NT_STATUS_IS_OK(status)) {
6544 printf("close failed for %s (%s)\n",
6545 dname, nt_errstr(status));
6548 /* Now go around the back and chmod to 777 via POSIX. */
6549 status = cli_posix_chmod(posix_cli, dname, 0777);
6550 if (!NT_STATUS_IS_OK(status)) {
6551 printf("cli_posix_chmod failed for %s (%s)\n",
6552 dname, nt_errstr(status));
6556 /* Check we can't create a file within dname via Windows. */
6557 status = cli_openx(cli, dst, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
6558 if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
6559 cli_close(posix_cli, fnum);
6560 printf("Create of %s should be ACCESS denied, was %s\n",
6561 dst, nt_errstr(status));
6565 /* Make the sample file/directory. */
6566 status = cli_openx(cli, src, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
6567 if (!NT_STATUS_IS_OK(status)) {
6568 printf("open of %s failed (%s)\n", src, nt_errstr(status));
6571 status = cli_close(cli, fnum);
6572 if (!NT_STATUS_IS_OK(status)) {
6573 printf("cli_close failed (%s)\n", nt_errstr(status));
6577 status = cli_mkdir(cli, dsrc);
6578 if (!NT_STATUS_IS_OK(status)) {
6579 printf("cli_mkdir of %s failed (%s)\n",
6580 dsrc, nt_errstr(status));
6585 * OK - renames of the new file and directory into the
6586 * dst directory should fail.
6589 status = cli_rename(cli, src, dst, false);
6590 if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
6591 printf("rename of %s -> %s should be ACCESS denied, was %s\n",
6592 src, dst, nt_errstr(status));
6595 status = cli_rename(cli, dsrc, ddst, false);
6596 if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
6597 printf("rename of %s -> %s should be ACCESS denied, was %s\n",
6598 src, dst, nt_errstr(status));
6608 torture_close_connection(posix_cli);
6612 if (fnum != (uint16_t)-1) {
6613 cli_close(cli, fnum);
6615 cli_unlink(cli, src,
6616 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6617 cli_unlink(cli, dst,
6618 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6619 cli_rmdir(cli, dsrc);
6620 cli_rmdir(cli, ddst);
6621 cli_rmdir(cli, dname);
6623 torture_close_connection(cli);
6631 Test owner rights ACE.
6633 static bool run_owner_rights(int dummy)
6635 static struct cli_state *cli = NULL;
6636 const char *fname = "owner_rights.txt";
6637 uint16_t fnum = (uint16_t)-1;
6638 struct security_descriptor *sd = NULL;
6639 struct security_descriptor *newsd = NULL;
6641 TALLOC_CTX *frame = NULL;
6643 frame = talloc_stackframe();
6644 printf("starting owner rights test\n");
6646 /* Windows connection. */
6647 if (!torture_open_connection(&cli, 0)) {
6651 smbXcli_conn_set_sockopt(cli->conn, sockops);
6653 /* Start with a clean slate. */
6654 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6656 /* Create the test file. */
6657 /* Now try and open for read and write-dac. */
6658 status = cli_ntcreate(cli,
6662 FILE_ATTRIBUTE_NORMAL,
6663 FILE_SHARE_READ|FILE_SHARE_WRITE|
6670 if (!NT_STATUS_IS_OK(status)) {
6671 printf("Create of %s - %s\n", fname, nt_errstr(status));
6675 /* Get the original SD. */
6676 status = cli_query_secdesc(cli,
6680 if (!NT_STATUS_IS_OK(status)) {
6681 printf("cli_query_secdesc failed for %s (%s)\n",
6682 fname, nt_errstr(status));
6687 * Add an "owner-rights" ACE denying WRITE_DATA,
6688 * and an "owner-rights" ACE allowing READ_DATA.
6691 newsd = security_descriptor_dacl_create(frame,
6696 SEC_ACE_TYPE_ACCESS_DENIED,
6700 SEC_ACE_TYPE_ACCESS_ALLOWED,
6704 if (newsd == NULL) {
6707 sd->dacl = security_acl_concatenate(frame,
6710 if (sd->dacl == NULL) {
6713 status = cli_set_secdesc(cli, fnum, sd);
6714 if (!NT_STATUS_IS_OK(status)) {
6715 printf("cli_set_secdesc failed for %s (%s)\n",
6716 fname, nt_errstr(status));
6719 status = cli_close(cli, fnum);
6720 if (!NT_STATUS_IS_OK(status)) {
6721 printf("close failed for %s (%s)\n",
6722 fname, nt_errstr(status));
6725 fnum = (uint16_t)-1;
6727 /* Try and open for FILE_WRITE_DATA */
6728 status = cli_ntcreate(cli,
6732 FILE_ATTRIBUTE_NORMAL,
6733 FILE_SHARE_READ|FILE_SHARE_WRITE|
6740 if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
6741 printf("Open of %s - %s\n", fname, nt_errstr(status));
6745 /* Now try and open for FILE_READ_DATA */
6746 status = cli_ntcreate(cli,
6750 FILE_ATTRIBUTE_NORMAL,
6751 FILE_SHARE_READ|FILE_SHARE_WRITE|
6758 if (!NT_STATUS_IS_OK(status)) {
6759 printf("Open of %s - %s\n", fname, nt_errstr(status));
6763 status = cli_close(cli, fnum);
6764 if (!NT_STATUS_IS_OK(status)) {
6765 printf("close failed for %s (%s)\n",
6766 fname, nt_errstr(status));
6770 /* Restore clean slate. */
6772 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6774 /* Create the test file. */
6775 status = cli_ntcreate(cli,
6779 FILE_ATTRIBUTE_NORMAL,
6780 FILE_SHARE_READ|FILE_SHARE_WRITE|
6787 if (!NT_STATUS_IS_OK(status)) {
6788 printf("Create of %s - %s\n", fname, nt_errstr(status));
6792 /* Get the original SD. */
6793 status = cli_query_secdesc(cli,
6797 if (!NT_STATUS_IS_OK(status)) {
6798 printf("cli_query_secdesc failed for %s (%s)\n",
6799 fname, nt_errstr(status));
6804 * Add an "owner-rights ACE denying WRITE_DATA,
6805 * and an "owner-rights ACE allowing READ_DATA|WRITE_DATA.
6808 newsd = security_descriptor_dacl_create(frame,
6813 SEC_ACE_TYPE_ACCESS_DENIED,
6817 SEC_ACE_TYPE_ACCESS_ALLOWED,
6818 FILE_READ_DATA|FILE_WRITE_DATA,
6821 if (newsd == NULL) {
6824 sd->dacl = security_acl_concatenate(frame,
6827 if (sd->dacl == NULL) {
6830 status = cli_set_secdesc(cli, fnum, sd);
6831 if (!NT_STATUS_IS_OK(status)) {
6832 printf("cli_set_secdesc failed for %s (%s)\n",
6833 fname, nt_errstr(status));
6836 status = cli_close(cli, fnum);
6837 if (!NT_STATUS_IS_OK(status)) {
6838 printf("close failed for %s (%s)\n",
6839 fname, nt_errstr(status));
6842 fnum = (uint16_t)-1;
6844 /* Try and open for FILE_WRITE_DATA */
6845 status = cli_ntcreate(cli,
6849 FILE_ATTRIBUTE_NORMAL,
6850 FILE_SHARE_READ|FILE_SHARE_WRITE|
6857 if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
6858 printf("Open of %s - %s\n", fname, nt_errstr(status));
6862 /* Now try and open for FILE_READ_DATA */
6863 status = cli_ntcreate(cli,
6867 FILE_ATTRIBUTE_NORMAL,
6868 FILE_SHARE_READ|FILE_SHARE_WRITE|
6875 if (!NT_STATUS_IS_OK(status)) {
6876 printf("Open of %s - %s\n", fname, nt_errstr(status));
6880 status = cli_close(cli, fnum);
6881 if (!NT_STATUS_IS_OK(status)) {
6882 printf("close failed for %s (%s)\n",
6883 fname, nt_errstr(status));
6887 /* Restore clean slate. */
6889 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6892 /* Create the test file. */
6893 status = cli_ntcreate(cli,
6897 FILE_ATTRIBUTE_NORMAL,
6898 FILE_SHARE_READ|FILE_SHARE_WRITE|
6905 if (!NT_STATUS_IS_OK(status)) {
6906 printf("Create of %s - %s\n", fname, nt_errstr(status));
6910 /* Get the original SD. */
6911 status = cli_query_secdesc(cli,
6915 if (!NT_STATUS_IS_OK(status)) {
6916 printf("cli_query_secdesc failed for %s (%s)\n",
6917 fname, nt_errstr(status));
6922 * Add an "authenticated users" ACE allowing READ_DATA,
6923 * add an "owner-rights" denying READ_DATA,
6924 * and an "authenticated users" ACE allowing WRITE_DATA.
6927 newsd = security_descriptor_dacl_create(frame,
6931 SID_NT_AUTHENTICATED_USERS,
6932 SEC_ACE_TYPE_ACCESS_ALLOWED,
6936 SEC_ACE_TYPE_ACCESS_DENIED,
6939 SID_NT_AUTHENTICATED_USERS,
6940 SEC_ACE_TYPE_ACCESS_ALLOWED,
6944 if (newsd == NULL) {
6945 printf("newsd == NULL\n");
6948 sd->dacl = security_acl_concatenate(frame,
6951 if (sd->dacl == NULL) {
6952 printf("sd->dacl == NULL\n");
6955 status = cli_set_secdesc(cli, fnum, sd);
6956 if (!NT_STATUS_IS_OK(status)) {
6957 printf("cli_set_secdesc failed for %s (%s)\n",
6958 fname, nt_errstr(status));
6961 status = cli_close(cli, fnum);
6962 if (!NT_STATUS_IS_OK(status)) {
6963 printf("close failed for %s (%s)\n",
6964 fname, nt_errstr(status));
6967 fnum = (uint16_t)-1;
6969 /* Now try and open for FILE_READ_DATA|FILE_WRITE_DATA */
6970 status = cli_ntcreate(cli,
6973 FILE_READ_DATA|FILE_WRITE_DATA,
6974 FILE_ATTRIBUTE_NORMAL,
6975 FILE_SHARE_READ|FILE_SHARE_WRITE|
6982 if (!NT_STATUS_IS_OK(status)) {
6983 printf("Open of %s - %s\n", fname, nt_errstr(status));
6987 status = cli_close(cli, fnum);
6988 if (!NT_STATUS_IS_OK(status)) {
6989 printf("close failed for %s (%s)\n",
6990 fname, nt_errstr(status));
6994 cli_unlink(cli, fname,
6995 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7003 if (fnum != (uint16_t)-1) {
7004 cli_close(cli, fnum);
7006 cli_unlink(cli, fname,
7007 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7008 torture_close_connection(cli);
7016 * Test SMB1-specific open with SEC_FLAG_SYSTEM_SECURITY.
7017 * Note this test only works with a user with SeSecurityPrivilege set.
7019 * NB. This is also tested in samba3.base.createx_access
7020 * but this makes it very explicit what we're looking for.
7022 static bool run_smb1_system_security(int dummy)
7024 static struct cli_state *cli = NULL;
7025 const char *fname = "system_security.txt";
7026 uint16_t fnum = (uint16_t)-1;
7028 TALLOC_CTX *frame = NULL;
7030 frame = talloc_stackframe();
7031 printf("starting smb1 system security test\n");
7033 /* SMB1 connection - torture_open_connection() forces this. */
7034 if (!torture_open_connection(&cli, 0)) {
7038 smbXcli_conn_set_sockopt(cli->conn, sockops);
7040 /* Start with a clean slate. */
7041 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7043 /* Create the test file. */
7044 status = cli_ntcreate(cli,
7048 FILE_ATTRIBUTE_NORMAL,
7049 FILE_SHARE_READ|FILE_SHARE_WRITE|
7056 if (!NT_STATUS_IS_OK(status)) {
7057 printf("Create of %s - %s\n", fname, nt_errstr(status));
7061 status = cli_close(cli, fnum);
7063 /* Open with SEC_FLAG_SYSTEM_SECURITY only. */
7065 * On SMB1 this succeeds - SMB2 it fails,
7066 * see the SMB2-SACL test.
7068 status = cli_ntcreate(cli,
7071 SEC_FLAG_SYSTEM_SECURITY,
7072 FILE_ATTRIBUTE_NORMAL,
7073 FILE_SHARE_READ|FILE_SHARE_WRITE|
7080 if (!NT_STATUS_IS_OK(status)) {
7081 printf("Open of %s - %s\n", fname, nt_errstr(status));
7085 status = cli_close(cli, fnum);
7087 cli_unlink(cli, fname,
7088 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7090 torture_close_connection(cli);
7097 if (fnum != (uint16_t)-1) {
7098 cli_close(cli, fnum);
7100 cli_unlink(cli, fname,
7101 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7102 torture_close_connection(cli);
7109 static bool run_pipe_number(int dummy)
7111 struct cli_state *cli1;
7112 const char *pipe_name = "\\SPOOLSS";
7117 printf("starting pipenumber test\n");
7118 if (!torture_open_connection(&cli1, 0)) {
7122 smbXcli_conn_set_sockopt(cli1->conn, sockops);
7124 status = cli_ntcreate(cli1, pipe_name, 0, FILE_READ_DATA,
7125 FILE_ATTRIBUTE_NORMAL,
7126 FILE_SHARE_READ|FILE_SHARE_WRITE,
7127 FILE_OPEN_IF, 0, 0, &fnum, NULL);
7128 if (!NT_STATUS_IS_OK(status)) {
7129 printf("Open of pipe %s failed with error (%s)\n", pipe_name, nt_errstr(status));
7133 printf("\r%6d", num_pipes);
7136 printf("pipe_number test - we can open %d %s pipes.\n", num_pipes, pipe_name );
7137 torture_close_connection(cli1);
7142 Test open mode returns on read-only files.
7144 static bool run_opentest(int dummy)
7146 static struct cli_state *cli1;
7147 static struct cli_state *cli2;
7148 const char *fname = "\\readonly.file";
7149 uint16_t fnum1, fnum2;
7152 bool correct = True;
7156 printf("starting open test\n");
7158 if (!torture_open_connection(&cli1, 0)) {
7162 cli_setatr(cli1, fname, 0, 0);
7163 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7165 smbXcli_conn_set_sockopt(cli1->conn, sockops);
7167 status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
7168 if (!NT_STATUS_IS_OK(status)) {
7169 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
7173 status = cli_close(cli1, fnum1);
7174 if (!NT_STATUS_IS_OK(status)) {
7175 printf("close2 failed (%s)\n", nt_errstr(status));
7179 status = cli_setatr(cli1, fname, FILE_ATTRIBUTE_READONLY, 0);
7180 if (!NT_STATUS_IS_OK(status)) {
7181 printf("cli_setatr failed (%s)\n", nt_errstr(status));
7185 status = cli_openx(cli1, fname, O_RDONLY, DENY_WRITE, &fnum1);
7186 if (!NT_STATUS_IS_OK(status)) {
7187 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
7191 /* This will fail - but the error should be ERRnoaccess, not ERRbadshare. */
7192 status = cli_openx(cli1, fname, O_RDWR, DENY_ALL, &fnum2);
7194 if (check_error(__LINE__, status, ERRDOS, ERRnoaccess,
7195 NT_STATUS_ACCESS_DENIED)) {
7196 printf("correct error code ERRDOS/ERRnoaccess returned\n");
7199 printf("finished open test 1\n");
7201 cli_close(cli1, fnum1);
7203 /* Now try not readonly and ensure ERRbadshare is returned. */
7205 cli_setatr(cli1, fname, 0, 0);
7207 status = cli_openx(cli1, fname, O_RDONLY, DENY_WRITE, &fnum1);
7208 if (!NT_STATUS_IS_OK(status)) {
7209 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
7213 /* This will fail - but the error should be ERRshare. */
7214 status = cli_openx(cli1, fname, O_RDWR, DENY_ALL, &fnum2);
7216 if (check_error(__LINE__, status, ERRDOS, ERRbadshare,
7217 NT_STATUS_SHARING_VIOLATION)) {
7218 printf("correct error code ERRDOS/ERRbadshare returned\n");
7221 status = cli_close(cli1, fnum1);
7222 if (!NT_STATUS_IS_OK(status)) {
7223 printf("close2 failed (%s)\n", nt_errstr(status));
7227 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7229 printf("finished open test 2\n");
7231 /* Test truncate open disposition on file opened for read. */
7232 status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
7233 if (!NT_STATUS_IS_OK(status)) {
7234 printf("(3) open (1) of %s failed (%s)\n", fname, nt_errstr(status));
7238 /* write 20 bytes. */
7240 memset(buf, '\0', 20);
7242 status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 0, 20, NULL);
7243 if (!NT_STATUS_IS_OK(status)) {
7244 printf("write failed (%s)\n", nt_errstr(status));
7248 status = cli_close(cli1, fnum1);
7249 if (!NT_STATUS_IS_OK(status)) {
7250 printf("(3) close1 failed (%s)\n", nt_errstr(status));
7254 /* Ensure size == 20. */
7255 status = cli_getatr(cli1, fname, NULL, &fsize, NULL);
7256 if (!NT_STATUS_IS_OK(status)) {
7257 printf("(3) getatr failed (%s)\n", nt_errstr(status));
7262 printf("(3) file size != 20\n");
7266 /* Now test if we can truncate a file opened for readonly. */
7267 status = cli_openx(cli1, fname, O_RDONLY|O_TRUNC, DENY_NONE, &fnum1);
7268 if (!NT_STATUS_IS_OK(status)) {
7269 printf("(3) open (2) of %s failed (%s)\n", fname, nt_errstr(status));
7273 status = cli_close(cli1, fnum1);
7274 if (!NT_STATUS_IS_OK(status)) {
7275 printf("close2 failed (%s)\n", nt_errstr(status));
7279 /* Ensure size == 0. */
7280 status = cli_getatr(cli1, fname, NULL, &fsize, NULL);
7281 if (!NT_STATUS_IS_OK(status)) {
7282 printf("(3) getatr failed (%s)\n", nt_errstr(status));
7287 printf("(3) file size != 0\n");
7290 printf("finished open test 3\n");
7292 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7294 printf("Do ctemp tests\n");
7295 status = cli_ctemp(cli1, talloc_tos(), "\\", &fnum1, &tmp_path);
7296 if (!NT_STATUS_IS_OK(status)) {
7297 printf("ctemp failed (%s)\n", nt_errstr(status));
7301 printf("ctemp gave path %s\n", tmp_path);
7302 status = cli_close(cli1, fnum1);
7303 if (!NT_STATUS_IS_OK(status)) {
7304 printf("close of temp failed (%s)\n", nt_errstr(status));
7307 status = cli_unlink(cli1, tmp_path, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7308 if (!NT_STATUS_IS_OK(status)) {
7309 printf("unlink of temp failed (%s)\n", nt_errstr(status));
7312 /* Test the non-io opens... */
7314 if (!torture_open_connection(&cli2, 1)) {
7318 cli_setatr(cli2, fname, 0, 0);
7319 cli_unlink(cli2, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7321 smbXcli_conn_set_sockopt(cli2->conn, sockops);
7323 printf("TEST #1 testing 2 non-io opens (no delete)\n");
7324 status = cli_ntcreate(cli1, fname, 0, FILE_READ_ATTRIBUTES,
7325 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7326 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
7327 if (!NT_STATUS_IS_OK(status)) {
7328 printf("TEST #1 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
7332 status = cli_ntcreate(cli2, fname, 0, FILE_READ_ATTRIBUTES,
7333 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7334 FILE_OPEN_IF, 0, 0, &fnum2, NULL);
7335 if (!NT_STATUS_IS_OK(status)) {
7336 printf("TEST #1 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
7340 status = cli_close(cli1, fnum1);
7341 if (!NT_STATUS_IS_OK(status)) {
7342 printf("TEST #1 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
7346 status = cli_close(cli2, fnum2);
7347 if (!NT_STATUS_IS_OK(status)) {
7348 printf("TEST #1 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
7352 printf("non-io open test #1 passed.\n");
7354 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7356 printf("TEST #2 testing 2 non-io opens (first with delete)\n");
7358 status = cli_ntcreate(cli1, fname, 0,
7359 DELETE_ACCESS|FILE_READ_ATTRIBUTES,
7360 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7361 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
7362 if (!NT_STATUS_IS_OK(status)) {
7363 printf("TEST #2 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
7367 status = cli_ntcreate(cli2, fname, 0, FILE_READ_ATTRIBUTES,
7368 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7369 FILE_OPEN_IF, 0, 0, &fnum2, NULL);
7370 if (!NT_STATUS_IS_OK(status)) {
7371 printf("TEST #2 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
7375 status = cli_close(cli1, fnum1);
7376 if (!NT_STATUS_IS_OK(status)) {
7377 printf("TEST #2 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
7381 status = cli_close(cli2, fnum2);
7382 if (!NT_STATUS_IS_OK(status)) {
7383 printf("TEST #2 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
7387 printf("non-io open test #2 passed.\n");
7389 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7391 printf("TEST #3 testing 2 non-io opens (second with delete)\n");
7393 status = cli_ntcreate(cli1, fname, 0, FILE_READ_ATTRIBUTES,
7394 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7395 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
7396 if (!NT_STATUS_IS_OK(status)) {
7397 printf("TEST #3 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
7401 status = cli_ntcreate(cli2, fname, 0,
7402 DELETE_ACCESS|FILE_READ_ATTRIBUTES,
7403 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7404 FILE_OPEN_IF, 0, 0, &fnum2, NULL);
7405 if (!NT_STATUS_IS_OK(status)) {
7406 printf("TEST #3 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
7410 status = cli_close(cli1, fnum1);
7411 if (!NT_STATUS_IS_OK(status)) {
7412 printf("TEST #3 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
7416 status = cli_close(cli2, fnum2);
7417 if (!NT_STATUS_IS_OK(status)) {
7418 printf("TEST #3 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
7422 printf("non-io open test #3 passed.\n");
7424 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7426 printf("TEST #4 testing 2 non-io opens (both with delete)\n");
7428 status = cli_ntcreate(cli1, fname, 0,
7429 DELETE_ACCESS|FILE_READ_ATTRIBUTES,
7430 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7431 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
7432 if (!NT_STATUS_IS_OK(status)) {
7433 printf("TEST #4 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
7437 status = cli_ntcreate(cli2, fname, 0,
7438 DELETE_ACCESS|FILE_READ_ATTRIBUTES,
7439 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7440 FILE_OPEN_IF, 0, 0, &fnum2, NULL);
7441 if (NT_STATUS_IS_OK(status)) {
7442 printf("TEST #4 open 2 of %s SUCCEEDED - should have failed (%s)\n", fname, nt_errstr(status));
7446 printf("TEST #4 open 2 of %s gave %s (correct error should be %s)\n", fname, nt_errstr(status), "sharing violation");
7448 status = cli_close(cli1, fnum1);
7449 if (!NT_STATUS_IS_OK(status)) {
7450 printf("TEST #4 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
7454 printf("non-io open test #4 passed.\n");
7456 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7458 printf("TEST #5 testing 2 non-io opens (both with delete - both with file share delete)\n");
7460 status = cli_ntcreate(cli1, fname, 0,
7461 DELETE_ACCESS|FILE_READ_ATTRIBUTES,
7462 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_DELETE,
7463 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
7464 if (!NT_STATUS_IS_OK(status)) {
7465 printf("TEST #5 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
7469 status = cli_ntcreate(cli2, fname, 0,
7470 DELETE_ACCESS|FILE_READ_ATTRIBUTES,
7471 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_DELETE,
7472 FILE_OPEN_IF, 0, 0, &fnum2, NULL);
7473 if (!NT_STATUS_IS_OK(status)) {
7474 printf("TEST #5 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
7478 status = cli_close(cli1, fnum1);
7479 if (!NT_STATUS_IS_OK(status)) {
7480 printf("TEST #5 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
7484 status = cli_close(cli2, fnum2);
7485 if (!NT_STATUS_IS_OK(status)) {
7486 printf("TEST #5 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
7490 printf("non-io open test #5 passed.\n");
7492 printf("TEST #6 testing 1 non-io open, one io open\n");
7494 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7496 status = cli_ntcreate(cli1, fname, 0, FILE_READ_DATA,
7497 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7498 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
7499 if (!NT_STATUS_IS_OK(status)) {
7500 printf("TEST #6 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
7504 status = cli_ntcreate(cli2, fname, 0, FILE_READ_ATTRIBUTES,
7505 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ,
7506 FILE_OPEN_IF, 0, 0, &fnum2, NULL);
7507 if (!NT_STATUS_IS_OK(status)) {
7508 printf("TEST #6 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
7512 status = cli_close(cli1, fnum1);
7513 if (!NT_STATUS_IS_OK(status)) {
7514 printf("TEST #6 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
7518 status = cli_close(cli2, fnum2);
7519 if (!NT_STATUS_IS_OK(status)) {
7520 printf("TEST #6 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
7524 printf("non-io open test #6 passed.\n");
7526 printf("TEST #7 testing 1 non-io open, one io open with delete\n");
7528 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7530 status = cli_ntcreate(cli1, fname, 0, FILE_READ_DATA,
7531 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7532 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
7533 if (!NT_STATUS_IS_OK(status)) {
7534 printf("TEST #7 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
7538 status = cli_ntcreate(cli2, fname, 0,
7539 DELETE_ACCESS|FILE_READ_ATTRIBUTES,
7540 FILE_ATTRIBUTE_NORMAL,
7541 FILE_SHARE_READ|FILE_SHARE_DELETE,
7542 FILE_OPEN_IF, 0, 0, &fnum2, NULL);
7543 if (NT_STATUS_IS_OK(status)) {
7544 printf("TEST #7 open 2 of %s SUCCEEDED - should have failed (%s)\n", fname, nt_errstr(status));
7548 printf("TEST #7 open 2 of %s gave %s (correct error should be %s)\n", fname, nt_errstr(status), "sharing violation");
7550 status = cli_close(cli1, fnum1);
7551 if (!NT_STATUS_IS_OK(status)) {
7552 printf("TEST #7 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
7556 printf("non-io open test #7 passed.\n");
7558 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7560 printf("TEST #8 testing open without WRITE_ATTRIBUTES, updating close write time.\n");
7561 status = cli_ntcreate(cli1, fname, 0, FILE_WRITE_DATA, FILE_ATTRIBUTE_NORMAL,
7562 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
7563 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
7564 if (!NT_STATUS_IS_OK(status)) {
7565 printf("TEST #8 open of %s failed (%s)\n", fname, nt_errstr(status));
7570 /* Write to ensure we have to update the file time. */
7571 status = cli_writeall(cli1, fnum1, 0, (const uint8_t *)"TEST DATA\n", 0, 10,
7573 if (!NT_STATUS_IS_OK(status)) {
7574 printf("TEST #8 cli_write failed: %s\n", nt_errstr(status));
7579 status = cli_close(cli1, fnum1);
7580 if (!NT_STATUS_IS_OK(status)) {
7581 printf("TEST #8 close of %s failed (%s)\n", fname, nt_errstr(status));
7587 if (!torture_close_connection(cli1)) {
7590 if (!torture_close_connection(cli2)) {
7597 NTSTATUS torture_setup_unix_extensions(struct cli_state *cli)
7599 uint16_t major, minor;
7600 uint32_t caplow, caphigh;
7603 if (!SERVER_HAS_UNIX_CIFS(cli)) {
7604 printf("Server doesn't support UNIX CIFS extensions.\n");
7605 return NT_STATUS_NOT_SUPPORTED;
7608 status = cli_unix_extensions_version(cli, &major, &minor, &caplow,
7610 if (!NT_STATUS_IS_OK(status)) {
7611 printf("Server didn't return UNIX CIFS extensions: %s\n",
7616 status = cli_set_unix_extensions_capabilities(cli, major, minor,
7618 if (!NT_STATUS_IS_OK(status)) {
7619 printf("Server doesn't support setting UNIX CIFS extensions: "
7620 "%s.\n", nt_errstr(status));
7624 return NT_STATUS_OK;
7628 Test POSIX open /mkdir calls.
7630 static bool run_simple_posix_open_test(int dummy)
7632 static struct cli_state *cli1;
7633 const char *fname = "posix:file";
7634 const char *hname = "posix:hlink";
7635 const char *sname = "posix:symlink";
7636 const char *dname = "posix:dir";
7638 char *target = NULL;
7639 uint16_t fnum1 = (uint16_t)-1;
7640 SMB_STRUCT_STAT sbuf;
7641 bool correct = false;
7644 const char *fname_windows = "windows_file";
7645 uint16_t fnum2 = (uint16_t)-1;
7647 printf("Starting simple POSIX open test\n");
7649 if (!torture_open_connection(&cli1, 0)) {
7653 smbXcli_conn_set_sockopt(cli1->conn, sockops);
7655 status = torture_setup_unix_extensions(cli1);
7656 if (!NT_STATUS_IS_OK(status)) {
7660 cli_setatr(cli1, fname, 0, 0);
7661 cli_posix_unlink(cli1, fname);
7662 cli_setatr(cli1, dname, 0, 0);
7663 cli_posix_rmdir(cli1, dname);
7664 cli_setatr(cli1, hname, 0, 0);
7665 cli_posix_unlink(cli1, hname);
7666 cli_setatr(cli1, sname, 0, 0);
7667 cli_posix_unlink(cli1, sname);
7668 cli_setatr(cli1, fname_windows, 0, 0);
7669 cli_posix_unlink(cli1, fname_windows);
7671 /* Create a directory. */
7672 status = cli_posix_mkdir(cli1, dname, 0777);
7673 if (!NT_STATUS_IS_OK(status)) {
7674 printf("POSIX mkdir of %s failed (%s)\n", dname, nt_errstr(status));
7678 status = cli_posix_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL,
7680 if (!NT_STATUS_IS_OK(status)) {
7681 printf("POSIX create of %s failed (%s)\n", fname, nt_errstr(status));
7685 /* Test ftruncate - set file size. */
7686 status = cli_ftruncate(cli1, fnum1, 1000);
7687 if (!NT_STATUS_IS_OK(status)) {
7688 printf("ftruncate failed (%s)\n", nt_errstr(status));
7692 /* Ensure st_size == 1000 */
7693 status = cli_posix_stat(cli1, fname, &sbuf);
7694 if (!NT_STATUS_IS_OK(status)) {
7695 printf("stat failed (%s)\n", nt_errstr(status));
7699 if (sbuf.st_ex_size != 1000) {
7700 printf("ftruncate - stat size (%u) != 1000\n", (unsigned int)sbuf.st_ex_size);
7704 /* Ensure st_mode == 0600 */
7705 if ((sbuf.st_ex_mode & 07777) != 0600) {
7706 printf("posix_open - bad permissions 0%o != 0600\n",
7707 (unsigned int)(sbuf.st_ex_mode & 07777));
7711 /* Test ftruncate - set file size back to zero. */
7712 status = cli_ftruncate(cli1, fnum1, 0);
7713 if (!NT_STATUS_IS_OK(status)) {
7714 printf("ftruncate failed (%s)\n", nt_errstr(status));
7718 status = cli_close(cli1, fnum1);
7719 if (!NT_STATUS_IS_OK(status)) {
7720 printf("close failed (%s)\n", nt_errstr(status));
7724 /* Now open the file again for read only. */
7725 status = cli_posix_open(cli1, fname, O_RDONLY, 0, &fnum1);
7726 if (!NT_STATUS_IS_OK(status)) {
7727 printf("POSIX open of %s failed (%s)\n", fname, nt_errstr(status));
7731 /* Now unlink while open. */
7732 status = cli_posix_unlink(cli1, fname);
7733 if (!NT_STATUS_IS_OK(status)) {
7734 printf("POSIX unlink of %s failed (%s)\n", fname, nt_errstr(status));
7738 status = cli_close(cli1, fnum1);
7739 if (!NT_STATUS_IS_OK(status)) {
7740 printf("close(2) failed (%s)\n", nt_errstr(status));
7744 /* Ensure the file has gone. */
7745 status = cli_posix_open(cli1, fname, O_RDONLY, 0, &fnum1);
7746 if (NT_STATUS_IS_OK(status)) {
7747 printf("POSIX open of %s succeeded, should have been deleted.\n", fname);
7751 /* Create again to test open with O_TRUNC. */
7752 status = cli_posix_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL, 0600, &fnum1);
7753 if (!NT_STATUS_IS_OK(status)) {
7754 printf("POSIX create of %s failed (%s)\n", fname, nt_errstr(status));
7758 /* Test ftruncate - set file size. */
7759 status = cli_ftruncate(cli1, fnum1, 1000);
7760 if (!NT_STATUS_IS_OK(status)) {
7761 printf("ftruncate failed (%s)\n", nt_errstr(status));
7765 /* Ensure st_size == 1000 */
7766 status = cli_posix_stat(cli1, fname, &sbuf);
7767 if (!NT_STATUS_IS_OK(status)) {
7768 printf("stat failed (%s)\n", nt_errstr(status));
7772 if (sbuf.st_ex_size != 1000) {
7773 printf("ftruncate - stat size (%u) != 1000\n", (unsigned int)sbuf.st_ex_size);
7777 status = cli_close(cli1, fnum1);
7778 if (!NT_STATUS_IS_OK(status)) {
7779 printf("close(2) failed (%s)\n", nt_errstr(status));
7783 /* Re-open with O_TRUNC. */
7784 status = cli_posix_open(cli1, fname, O_WRONLY|O_TRUNC, 0600, &fnum1);
7785 if (!NT_STATUS_IS_OK(status)) {
7786 printf("POSIX create of %s failed (%s)\n", fname, nt_errstr(status));
7790 /* Ensure st_size == 0 */
7791 status = cli_posix_stat(cli1, fname, &sbuf);
7792 if (!NT_STATUS_IS_OK(status)) {
7793 printf("stat failed (%s)\n", nt_errstr(status));
7797 if (sbuf.st_ex_size != 0) {
7798 printf("O_TRUNC - stat size (%u) != 0\n", (unsigned int)sbuf.st_ex_size);
7802 status = cli_close(cli1, fnum1);
7803 if (!NT_STATUS_IS_OK(status)) {
7804 printf("close failed (%s)\n", nt_errstr(status));
7808 status = cli_posix_unlink(cli1, fname);
7809 if (!NT_STATUS_IS_OK(status)) {
7810 printf("POSIX unlink of %s failed (%s)\n", fname, nt_errstr(status));
7814 status = cli_posix_open(cli1, dname, O_RDONLY, 0, &fnum1);
7815 if (!NT_STATUS_IS_OK(status)) {
7816 printf("POSIX open directory O_RDONLY of %s failed (%s)\n",
7817 dname, nt_errstr(status));
7821 cli_close(cli1, fnum1);
7823 /* What happens when we try and POSIX open a directory for write ? */
7824 status = cli_posix_open(cli1, dname, O_RDWR, 0, &fnum1);
7825 if (NT_STATUS_IS_OK(status)) {
7826 printf("POSIX open of directory %s succeeded, "
7827 "should have failed.\n",
7831 if (!check_both_error(__LINE__, status, ERRDOS, EISDIR,
7832 NT_STATUS_FILE_IS_A_DIRECTORY)) {
7837 /* Create the file. */
7838 status = cli_posix_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL,
7840 if (!NT_STATUS_IS_OK(status)) {
7841 printf("POSIX create of %s failed (%s)\n", fname, nt_errstr(status));
7845 /* Write some data into it. */
7846 status = cli_writeall(cli1, fnum1, 0, (const uint8_t *)"TEST DATA\n", 0, 10,
7848 if (!NT_STATUS_IS_OK(status)) {
7849 printf("cli_write failed: %s\n", nt_errstr(status));
7853 cli_close(cli1, fnum1);
7855 /* Now create a hardlink. */
7856 status = cli_posix_hardlink(cli1, fname, hname);
7857 if (!NT_STATUS_IS_OK(status)) {
7858 printf("POSIX hardlink of %s failed (%s)\n", hname, nt_errstr(status));
7862 /* Now create a symlink. */
7863 status = cli_posix_symlink(cli1, fname, sname);
7864 if (!NT_STATUS_IS_OK(status)) {
7865 printf("POSIX symlink of %s failed (%s)\n", sname, nt_errstr(status));
7869 /* Open the hardlink for read. */
7870 status = cli_posix_open(cli1, hname, O_RDONLY, 0, &fnum1);
7871 if (!NT_STATUS_IS_OK(status)) {
7872 printf("POSIX open of %s failed (%s)\n", hname, nt_errstr(status));
7876 status = cli_read(cli1, fnum1, buf, 0, 10, &nread);
7877 if (!NT_STATUS_IS_OK(status)) {
7878 printf("POSIX read of %s failed (%s)\n", hname,
7881 } else if (nread != 10) {
7882 printf("POSIX read of %s failed. Received %ld, expected %d\n",
7883 hname, (unsigned long)nread, 10);
7887 if (memcmp(buf, "TEST DATA\n", 10)) {
7888 printf("invalid data read from hardlink\n");
7892 /* Do a POSIX lock/unlock. */
7893 status = cli_posix_lock(cli1, fnum1, 0, 100, true, READ_LOCK);
7894 if (!NT_STATUS_IS_OK(status)) {
7895 printf("POSIX lock failed %s\n", nt_errstr(status));
7899 /* Punch a hole in the locked area. */
7900 status = cli_posix_unlock(cli1, fnum1, 10, 80);
7901 if (!NT_STATUS_IS_OK(status)) {
7902 printf("POSIX unlock failed %s\n", nt_errstr(status));
7906 cli_close(cli1, fnum1);
7908 /* Open the symlink for read - this should fail. A POSIX
7909 client should not be doing opens on a symlink. */
7910 status = cli_posix_open(cli1, sname, O_RDONLY, 0, &fnum1);
7911 if (NT_STATUS_IS_OK(status)) {
7912 printf("POSIX open of %s succeeded (should have failed)\n", sname);
7915 if (!check_both_error(__LINE__, status, ERRDOS, ERRbadpath,
7916 NT_STATUS_OBJECT_PATH_NOT_FOUND)) {
7917 printf("POSIX open of %s should have failed "
7918 "with NT_STATUS_OBJECT_PATH_NOT_FOUND, "
7919 "failed with %s instead.\n",
7920 sname, nt_errstr(status));
7925 status = cli_posix_readlink(cli1, sname, talloc_tos(), &target);
7926 if (!NT_STATUS_IS_OK(status)) {
7927 printf("POSIX readlink on %s failed (%s)\n", sname, nt_errstr(status));
7931 if (strcmp(target, fname) != 0) {
7932 printf("POSIX readlink on %s failed to match name %s (read %s)\n",
7933 sname, fname, target);
7937 status = cli_posix_rmdir(cli1, dname);
7938 if (!NT_STATUS_IS_OK(status)) {
7939 printf("POSIX rmdir failed (%s)\n", nt_errstr(status));
7943 /* Check directory opens with a specific permission. */
7944 status = cli_posix_mkdir(cli1, dname, 0700);
7945 if (!NT_STATUS_IS_OK(status)) {
7946 printf("POSIX mkdir of %s failed (%s)\n", dname, nt_errstr(status));
7950 /* Ensure st_mode == 0700 */
7951 status = cli_posix_stat(cli1, dname, &sbuf);
7952 if (!NT_STATUS_IS_OK(status)) {
7953 printf("stat failed (%s)\n", nt_errstr(status));
7957 if ((sbuf.st_ex_mode & 07777) != 0700) {
7958 printf("posix_mkdir - bad permissions 0%o != 0700\n",
7959 (unsigned int)(sbuf.st_ex_mode & 07777));
7964 * Now create a Windows file, and attempt a POSIX unlink.
7965 * This should fail with a sharing violation but due to:
7967 * [Bug 9571] Unlink after open causes smbd to panic
7969 * ensure we've fixed the lock ordering violation.
7972 status = cli_ntcreate(cli1, fname_windows, 0,
7973 FILE_READ_DATA|FILE_WRITE_DATA, 0,
7974 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
7976 0x0, 0x0, &fnum2, NULL);
7977 if (!NT_STATUS_IS_OK(status)) {
7978 printf("Windows create of %s failed (%s)\n", fname_windows,
7983 /* Now try posix_unlink. */
7984 status = cli_posix_unlink(cli1, fname_windows);
7985 if (!NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
7986 printf("POSIX unlink of %s should fail "
7987 "with NT_STATUS_SHARING_VIOLATION "
7988 "got %s instead !\n",
7994 cli_close(cli1, fnum2);
7996 printf("Simple POSIX open test passed\n");
8001 if (fnum1 != (uint16_t)-1) {
8002 cli_close(cli1, fnum1);
8003 fnum1 = (uint16_t)-1;
8006 if (fnum2 != (uint16_t)-1) {
8007 cli_close(cli1, fnum2);
8008 fnum2 = (uint16_t)-1;
8011 cli_setatr(cli1, sname, 0, 0);
8012 cli_posix_unlink(cli1, sname);
8013 cli_setatr(cli1, hname, 0, 0);
8014 cli_posix_unlink(cli1, hname);
8015 cli_setatr(cli1, fname, 0, 0);
8016 cli_posix_unlink(cli1, fname);
8017 cli_setatr(cli1, dname, 0, 0);
8018 cli_posix_rmdir(cli1, dname);
8019 cli_setatr(cli1, fname_windows, 0, 0);
8020 cli_posix_unlink(cli1, fname_windows);
8022 if (!torture_close_connection(cli1)) {
8030 Test POSIX and Windows ACLs are rejected on symlinks.
8032 static bool run_acl_symlink_test(int dummy)
8034 static struct cli_state *cli;
8035 const char *fname = "posix_file";
8036 const char *sname = "posix_symlink";
8037 uint16_t fnum = (uint16_t)-1;
8038 bool correct = false;
8040 char *posix_acl = NULL;
8041 size_t posix_acl_len = 0;
8042 char *posix_acl_sym = NULL;
8043 size_t posix_acl_len_sym = 0;
8044 struct security_descriptor *sd = NULL;
8045 struct security_descriptor *sd_sym = NULL;
8046 TALLOC_CTX *frame = NULL;
8048 frame = talloc_stackframe();
8050 printf("Starting acl symlink test\n");
8052 if (!torture_open_connection(&cli, 0)) {
8057 smbXcli_conn_set_sockopt(cli->conn, sockops);
8059 status = torture_setup_unix_extensions(cli);
8060 if (!NT_STATUS_IS_OK(status)) {
8065 cli_setatr(cli, fname, 0, 0);
8066 cli_posix_unlink(cli, fname);
8067 cli_setatr(cli, sname, 0, 0);
8068 cli_posix_unlink(cli, sname);
8070 status = cli_ntcreate(cli,
8073 READ_CONTROL_ACCESS,
8075 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
8082 if (!NT_STATUS_IS_OK(status)) {
8083 printf("cli_ntcreate of %s failed (%s)\n",
8089 /* Get the Windows ACL on the file. */
8090 status = cli_query_secdesc(cli,
8094 if (!NT_STATUS_IS_OK(status)) {
8095 printf("cli_query_secdesc failed (%s)\n",
8100 /* Get the POSIX ACL on the file. */
8101 status = cli_posix_getacl(cli,
8107 if (!NT_STATUS_IS_OK(status)) {
8108 printf("cli_posix_getacl failed (%s)\n",
8113 status = cli_close(cli, fnum);
8114 if (!NT_STATUS_IS_OK(status)) {
8115 printf("close failed (%s)\n", nt_errstr(status));
8118 fnum = (uint16_t)-1;
8120 /* Now create a symlink. */
8121 status = cli_posix_symlink(cli, fname, sname);
8122 if (!NT_STATUS_IS_OK(status)) {
8123 printf("cli_posix_symlink of %s -> %s failed (%s)\n",
8130 /* Open a handle on the symlink for SD set/get should fail. */
8131 status = cli_ntcreate(cli,
8134 READ_CONTROL_ACCESS|SEC_STD_WRITE_DAC,
8136 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
8143 if (NT_STATUS_IS_OK(status)) {
8144 printf("Symlink open for getsd/setsd of %s "
8145 "succeeded (should fail)\n",
8150 /* Open a handle on the symlink. */
8151 status = cli_ntcreate(cli,
8154 FILE_READ_ATTRIBUTES|FILE_WRITE_ATTRIBUTES,
8156 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
8163 if (!NT_STATUS_IS_OK(status)) {
8164 printf("cli_posix_open of %s failed (%s)\n",
8170 /* Get the Windows ACL on the symlink handle. Should fail */
8171 status = cli_query_secdesc(cli,
8176 if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
8177 printf("cli_query_secdesc on a symlink gave %s. "
8178 "Should be NT_STATUS_ACCESS_DENIED.\n",
8183 /* Get the POSIX ACL on the symlink pathname. Should fail. */
8184 status = cli_posix_getacl(cli,
8190 if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
8191 printf("cli_posix_getacl on a symlink gave %s. "
8192 "Should be NT_STATUS_ACCESS_DENIED.\n",
8197 /* Set the Windows ACL on the symlink handle. Should fail */
8198 status = cli_set_security_descriptor(cli,
8203 if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
8204 printf("cli_query_secdesc on a symlink gave %s. "
8205 "Should be NT_STATUS_ACCESS_DENIED.\n",
8210 /* Set the POSIX ACL on the symlink pathname. Should fail. */
8211 status = cli_posix_setacl(cli,
8216 if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
8217 printf("cli_posix_setacl on a symlink gave %s. "
8218 "Should be NT_STATUS_ACCESS_DENIED.\n",
8223 printf("ACL symlink test passed\n");
8228 if (fnum != (uint16_t)-1) {
8229 cli_close(cli, fnum);
8230 fnum = (uint16_t)-1;
8233 cli_setatr(cli, sname, 0, 0);
8234 cli_posix_unlink(cli, sname);
8235 cli_setatr(cli, fname, 0, 0);
8236 cli_posix_unlink(cli, fname);
8238 if (!torture_close_connection(cli)) {
8247 Test POSIX can delete a file containing streams.
8249 static bool run_posix_stream_delete(int dummy)
8251 struct cli_state *cli1 = NULL;
8252 struct cli_state *cli2 = NULL;
8253 const char *fname = "streamfile";
8254 const char *stream_fname = "streamfile:Zone.Identifier:$DATA";
8255 uint16_t fnum1 = (uint16_t)-1;
8256 bool correct = false;
8258 TALLOC_CTX *frame = NULL;
8260 frame = talloc_stackframe();
8262 printf("Starting POSIX stream delete test\n");
8264 if (!torture_open_connection(&cli1, 0) ||
8265 !torture_open_connection(&cli2, 1)) {
8270 smbXcli_conn_set_sockopt(cli1->conn, sockops);
8271 smbXcli_conn_set_sockopt(cli2->conn, sockops);
8273 status = torture_setup_unix_extensions(cli2);
8274 if (!NT_STATUS_IS_OK(status)) {
8278 cli_setatr(cli1, fname, 0, 0);
8279 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
8281 /* Create the file. */
8282 status = cli_ntcreate(cli1,
8285 READ_CONTROL_ACCESS,
8287 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
8294 if (!NT_STATUS_IS_OK(status)) {
8295 printf("cli_ntcreate of %s failed (%s)\n",
8301 status = cli_close(cli1, fnum1);
8302 if (!NT_STATUS_IS_OK(status)) {
8303 printf("cli_close of %s failed (%s)\n",
8308 fnum1 = (uint16_t)-1;
8310 /* Now create the stream. */
8311 status = cli_ntcreate(cli1,
8316 FILE_SHARE_READ|FILE_SHARE_WRITE,
8323 if (!NT_STATUS_IS_OK(status)) {
8324 printf("cli_ntcreate of %s failed (%s)\n",
8330 /* Leave the stream handle open... */
8332 /* POSIX unlink should fail. */
8333 status = cli_posix_unlink(cli2, fname);
8334 if (NT_STATUS_IS_OK(status)) {
8335 printf("cli_posix_unlink of %s succeeded, should have failed\n",
8340 if (!NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
8341 printf("cli_posix_unlink of %s failed with (%s) "
8342 "should have been NT_STATUS_SHARING_VIOLATION\n",
8348 /* Close the stream handle. */
8349 status = cli_close(cli1, fnum1);
8350 if (!NT_STATUS_IS_OK(status)) {
8351 printf("cli_close of %s failed (%s)\n",
8356 fnum1 = (uint16_t)-1;
8358 /* POSIX unlink after stream handle closed should succeed. */
8359 status = cli_posix_unlink(cli2, fname);
8360 if (!NT_STATUS_IS_OK(status)) {
8361 printf("cli_posix_unlink of %s failed (%s)\n",
8367 printf("POSIX stream delete test passed\n");
8372 if (fnum1 != (uint16_t)-1) {
8373 cli_close(cli1, fnum1);
8374 fnum1 = (uint16_t)-1;
8377 cli_setatr(cli1, fname, 0, 0);
8378 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
8380 if (!torture_close_connection(cli1)) {
8383 if (!torture_close_connection(cli2)) {
8392 Test setting EA's are rejected on symlinks.
8394 static bool run_ea_symlink_test(int dummy)
8396 static struct cli_state *cli;
8397 const char *fname = "posix_file_ea";
8398 const char *sname = "posix_symlink_ea";
8399 const char *ea_name = "testea_name";
8400 const char *ea_value = "testea_value";
8401 uint16_t fnum = (uint16_t)-1;
8402 bool correct = false;
8405 struct ea_struct *eas = NULL;
8406 TALLOC_CTX *frame = NULL;
8408 frame = talloc_stackframe();
8410 printf("Starting EA symlink test\n");
8412 if (!torture_open_connection(&cli, 0)) {
8417 smbXcli_conn_set_sockopt(cli->conn, sockops);
8419 status = torture_setup_unix_extensions(cli);
8420 if (!NT_STATUS_IS_OK(status)) {
8425 cli_setatr(cli, fname, 0, 0);
8426 cli_posix_unlink(cli, fname);
8427 cli_setatr(cli, sname, 0, 0);
8428 cli_posix_unlink(cli, sname);
8430 status = cli_ntcreate(cli,
8433 READ_CONTROL_ACCESS,
8435 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
8442 if (!NT_STATUS_IS_OK(status)) {
8443 printf("cli_ntcreate of %s failed (%s)\n",
8449 status = cli_close(cli, fnum);
8450 if (!NT_STATUS_IS_OK(status)) {
8451 printf("close failed (%s)\n",
8455 fnum = (uint16_t)-1;
8457 /* Set an EA on the path. */
8458 status = cli_set_ea_path(cli,
8462 strlen(ea_value)+1);
8464 if (!NT_STATUS_IS_OK(status)) {
8465 printf("cli_set_ea_path failed (%s)\n",
8470 /* Now create a symlink. */
8471 status = cli_posix_symlink(cli, fname, sname);
8472 if (!NT_STATUS_IS_OK(status)) {
8473 printf("cli_posix_symlink of %s -> %s failed (%s)\n",
8480 /* Get the EA list on the path. Should return value set. */
8481 status = cli_get_ea_list_path(cli,
8487 if (!NT_STATUS_IS_OK(status)) {
8488 printf("cli_get_ea_list_path failed (%s)\n",
8493 /* Ensure the EA we set is there. */
8494 for (i=0; i<num_eas; i++) {
8495 if (strcmp(eas[i].name, ea_name) == 0 &&
8496 eas[i].value.length == strlen(ea_value)+1 &&
8497 memcmp(eas[i].value.data,
8499 eas[i].value.length) == 0) {
8505 printf("Didn't find EA on pathname %s\n",
8513 /* Get the EA list on the symlink. Should return empty list. */
8514 status = cli_get_ea_list_path(cli,
8520 if (!NT_STATUS_IS_OK(status)) {
8521 printf("cli_get_ea_list_path failed (%s)\n",
8527 printf("cli_get_ea_list_path failed (%s)\n",
8532 /* Set an EA on the symlink. Should fail. */
8533 status = cli_set_ea_path(cli,
8537 strlen(ea_value)+1);
8539 if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
8540 printf("cli_set_ea_path on a symlink gave %s. "
8541 "Should be NT_STATUS_ACCESS_DENIED.\n",
8546 printf("EA symlink test passed\n");
8551 if (fnum != (uint16_t)-1) {
8552 cli_close(cli, fnum);
8553 fnum = (uint16_t)-1;
8556 cli_setatr(cli, sname, 0, 0);
8557 cli_posix_unlink(cli, sname);
8558 cli_setatr(cli, fname, 0, 0);
8559 cli_posix_unlink(cli, fname);
8561 if (!torture_close_connection(cli)) {
8570 Test POSIX locks are OFD-locks.
8572 static bool run_posix_ofd_lock_test(int dummy)
8574 static struct cli_state *cli;
8575 const char *fname = "posix_file";
8576 uint16_t fnum1 = (uint16_t)-1;
8577 uint16_t fnum2 = (uint16_t)-1;
8578 bool correct = false;
8580 TALLOC_CTX *frame = NULL;
8582 frame = talloc_stackframe();
8584 printf("Starting POSIX ofd-lock test\n");
8586 if (!torture_open_connection(&cli, 0)) {
8591 smbXcli_conn_set_sockopt(cli->conn, sockops);
8593 status = torture_setup_unix_extensions(cli);
8594 if (!NT_STATUS_IS_OK(status)) {
8599 cli_setatr(cli, fname, 0, 0);
8600 cli_posix_unlink(cli, fname);
8602 /* Open the file twice. */
8603 status = cli_posix_open(cli, fname, O_RDWR|O_CREAT|O_EXCL,
8605 if (!NT_STATUS_IS_OK(status)) {
8606 printf("First POSIX open of %s failed\n", fname);
8610 status = cli_posix_open(cli, fname, O_RDWR, 0, &fnum2);
8611 if (!NT_STATUS_IS_OK(status)) {
8612 printf("First POSIX open of %s failed\n", fname);
8616 /* Set a 0-50 lock on fnum1. */
8617 status = cli_posix_lock(cli, fnum1, 0, 50, false, WRITE_LOCK);
8618 if (!NT_STATUS_IS_OK(status)) {
8619 printf("POSIX lock (1) failed %s\n", nt_errstr(status));
8623 /* Set a 60-100 lock on fnum2. */
8624 status = cli_posix_lock(cli, fnum2, 60, 100, false, WRITE_LOCK);
8625 if (!NT_STATUS_IS_OK(status)) {
8626 printf("POSIX lock (2) failed %s\n", nt_errstr(status));
8630 /* close fnum1 - 0-50 lock should go away. */
8631 status = cli_close(cli, fnum1);
8632 if (!NT_STATUS_IS_OK(status)) {
8633 printf("close failed (%s)\n",
8637 fnum1 = (uint16_t)-1;
8639 /* Change the lock context. */
8640 cli_setpid(cli, cli_getpid(cli) + 1);
8642 /* Re-open fnum1. */
8643 status = cli_posix_open(cli, fname, O_RDWR, 0, &fnum1);
8644 if (!NT_STATUS_IS_OK(status)) {
8645 printf("Third POSIX open of %s failed\n", fname);
8649 /* 60-100 lock should still be there. */
8650 status = cli_posix_lock(cli, fnum1, 60, 100, false, WRITE_LOCK);
8651 if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
8652 printf("POSIX lock 60-100 not there %s\n", nt_errstr(status));
8656 /* 0-50 lock should be gone. */
8657 status = cli_posix_lock(cli, fnum1, 0, 50, false, WRITE_LOCK);
8658 if (!NT_STATUS_IS_OK(status)) {
8659 printf("POSIX lock 0-50 failed %s\n", nt_errstr(status));
8663 printf("POSIX OFD lock test passed\n");
8668 if (fnum1 != (uint16_t)-1) {
8669 cli_close(cli, fnum1);
8670 fnum1 = (uint16_t)-1;
8672 if (fnum2 != (uint16_t)-1) {
8673 cli_close(cli, fnum2);
8674 fnum2 = (uint16_t)-1;
8677 cli_setatr(cli, fname, 0, 0);
8678 cli_posix_unlink(cli, fname);
8680 if (!torture_close_connection(cli)) {
8688 struct posix_blocking_state {
8689 struct tevent_context *ev;
8690 struct cli_state *cli1;
8692 struct cli_state *cli2;
8698 static void posix_blocking_locked(struct tevent_req *subreq);
8699 static void posix_blocking_gotblocked(struct tevent_req *subreq);
8700 static void posix_blocking_gotecho(struct tevent_req *subreq);
8701 static void posix_blocking_unlocked(struct tevent_req *subreq);
8703 static struct tevent_req *posix_blocking_send(
8704 TALLOC_CTX *mem_ctx,
8705 struct tevent_context *ev,
8706 struct cli_state *cli1,
8708 struct cli_state *cli2,
8711 struct tevent_req *req = NULL, *subreq = NULL;
8712 struct posix_blocking_state *state = NULL;
8714 req = tevent_req_create(mem_ctx, &state, struct posix_blocking_state);
8720 state->fnum1 = fnum1;
8722 state->fnum2 = fnum2;
8724 subreq = cli_posix_lock_send(
8733 if (tevent_req_nomem(subreq, req)) {
8734 return tevent_req_post(req, ev);
8736 tevent_req_set_callback(subreq, posix_blocking_locked, req);
8740 static void posix_blocking_locked(struct tevent_req *subreq)
8742 struct tevent_req *req = tevent_req_callback_data(
8743 subreq, struct tevent_req);
8744 struct posix_blocking_state *state = tevent_req_data(
8745 req, struct posix_blocking_state);
8748 status = cli_posix_lock_recv(subreq);
8749 TALLOC_FREE(subreq);
8750 if (tevent_req_nterror(req, status)) {
8754 subreq = cli_posix_lock_send(
8763 if (tevent_req_nomem(subreq, req)) {
8766 tevent_req_set_callback(subreq, posix_blocking_gotblocked, req);
8768 /* Make sure the blocking request is delivered */
8769 subreq = cli_echo_send(
8774 (DATA_BLOB) { .data = (uint8_t *)state, .length = 1 });
8775 if (tevent_req_nomem(subreq, req)) {
8778 tevent_req_set_callback(subreq, posix_blocking_gotecho, req);
8781 static void posix_blocking_gotblocked(struct tevent_req *subreq)
8783 struct tevent_req *req = tevent_req_callback_data(
8784 subreq, struct tevent_req);
8785 struct posix_blocking_state *state = tevent_req_data(
8786 req, struct posix_blocking_state);
8789 status = cli_posix_lock_recv(subreq);
8790 TALLOC_FREE(subreq);
8791 if (tevent_req_nterror(req, status)) {
8794 if (!state->gotecho) {
8795 printf("blocked req got through before echo\n");
8796 tevent_req_nterror(req, NT_STATUS_INVALID_LOCK_SEQUENCE);
8799 tevent_req_done(req);
8802 static void posix_blocking_gotecho(struct tevent_req *subreq)
8804 struct tevent_req *req = tevent_req_callback_data(
8805 subreq, struct tevent_req);
8806 struct posix_blocking_state *state = tevent_req_data(
8807 req, struct posix_blocking_state);
8810 status = cli_echo_recv(subreq);
8811 TALLOC_FREE(subreq);
8812 if (tevent_req_nterror(req, status)) {
8815 if (state->gotblocked) {
8816 printf("blocked req got through before echo\n");
8817 tevent_req_nterror(req, NT_STATUS_INVALID_LOCK_SEQUENCE);
8820 state->gotecho = true;
8822 subreq = cli_posix_lock_send(
8831 if (tevent_req_nomem(subreq, req)) {
8834 tevent_req_set_callback(subreq, posix_blocking_unlocked, req);
8837 static void posix_blocking_unlocked(struct tevent_req *subreq)
8839 struct tevent_req *req = tevent_req_callback_data(
8840 subreq, struct tevent_req);
8843 status = cli_posix_lock_recv(subreq);
8844 TALLOC_FREE(subreq);
8845 if (tevent_req_nterror(req, status)) {
8848 /* tevent_req_done in posix_blocking_gotlocked */
8851 static NTSTATUS posix_blocking_recv(struct tevent_req *req)
8853 return tevent_req_simple_recv_ntstatus(req);
8856 static bool run_posix_blocking_lock(int dummy)
8858 struct tevent_context *ev = NULL;
8859 struct cli_state *cli1 = NULL, *cli2 = NULL;
8860 const char *fname = "posix_blocking";
8861 uint16_t fnum1 = UINT16_MAX, fnum2 = UINT16_MAX;
8862 struct tevent_req *req = NULL;
8867 printf("Starting posix blocking lock test\n");
8869 ev = samba_tevent_context_init(NULL);
8874 ok = torture_open_connection(&cli1, 0);
8878 ok = torture_open_connection(&cli2, 0);
8883 smbXcli_conn_set_sockopt(cli1->conn, sockops);
8885 status = torture_setup_unix_extensions(cli1);
8886 if (!NT_STATUS_IS_OK(status)) {
8890 cli_setatr(cli1, fname, 0, 0);
8891 cli_posix_unlink(cli1, fname);
8893 status = cli_posix_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL,
8895 if (!NT_STATUS_IS_OK(status)) {
8896 printf("First POSIX open of %s failed: %s\n",
8902 status = cli_posix_open(cli2, fname, O_RDWR, 0600, &fnum2);
8903 if (!NT_STATUS_IS_OK(status)) {
8904 printf("Second POSIX open of %s failed: %s\n",
8910 req = posix_blocking_send(ev, ev, cli1, fnum1, cli2, fnum2);
8912 printf("cli_posix_blocking failed\n");
8916 ok = tevent_req_poll_ntstatus(req, ev, &status);
8918 printf("tevent_req_poll_ntstatus failed: %s\n",
8922 status = posix_blocking_recv(req);
8924 if (!NT_STATUS_IS_OK(status)) {
8925 printf("posix_blocking_recv returned %s\n",
8933 if (fnum1 != UINT16_MAX) {
8934 cli_close(cli1, fnum1);
8937 if (fnum2 != UINT16_MAX) {
8938 cli_close(cli2, fnum2);
8943 cli_setatr(cli1, fname, 0, 0);
8944 cli_posix_unlink(cli1, fname);
8950 ok &= torture_close_connection(cli1);
8954 ok &= torture_close_connection(cli2);
8966 Test POSIX mkdir is case-sensitive.
8968 static bool run_posix_mkdir_test(int dummy)
8970 static struct cli_state *cli;
8971 const char *fname_foo = "POSIX_foo";
8972 const char *fname_foo_Foo = "POSIX_foo/Foo";
8973 const char *fname_foo_foo = "POSIX_foo/foo";
8974 const char *fname_Foo = "POSIX_Foo";
8975 const char *fname_Foo_Foo = "POSIX_Foo/Foo";
8976 const char *fname_Foo_foo = "POSIX_Foo/foo";
8977 bool correct = false;
8979 TALLOC_CTX *frame = NULL;
8980 uint16_t fnum = (uint16_t)-1;
8982 frame = talloc_stackframe();
8984 printf("Starting POSIX mkdir test\n");
8986 if (!torture_open_connection(&cli, 0)) {
8991 smbXcli_conn_set_sockopt(cli->conn, sockops);
8993 status = torture_setup_unix_extensions(cli);
8994 if (!NT_STATUS_IS_OK(status)) {
8999 cli_posix_rmdir(cli, fname_foo_foo);
9000 cli_posix_rmdir(cli, fname_foo_Foo);
9001 cli_posix_rmdir(cli, fname_foo);
9003 cli_posix_rmdir(cli, fname_Foo_foo);
9004 cli_posix_rmdir(cli, fname_Foo_Foo);
9005 cli_posix_rmdir(cli, fname_Foo);
9008 * Create a file POSIX_foo then try
9009 * and use it in a directory path by
9010 * doing mkdir POSIX_foo/bar.
9011 * The mkdir should fail with
9012 * NT_STATUS_OBJECT_PATH_NOT_FOUND
9015 status = cli_posix_open(cli,
9020 if (!NT_STATUS_IS_OK(status)) {
9021 printf("cli_posix_open of %s failed error %s\n",
9027 status = cli_posix_mkdir(cli, fname_foo_foo, 0777);
9028 if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_PATH_NOT_FOUND)) {
9029 printf("cli_posix_mkdir of %s should fail with "
9030 "NT_STATUS_OBJECT_PATH_NOT_FOUND got "
9037 status = cli_close(cli, fnum);
9038 if (!NT_STATUS_IS_OK(status)) {
9039 printf("cli_close failed %s\n", nt_errstr(status));
9042 fnum = (uint16_t)-1;
9044 status = cli_posix_unlink(cli, fname_foo);
9045 if (!NT_STATUS_IS_OK(status)) {
9046 printf("cli_posix_unlink of %s failed error %s\n",
9053 * Now we've deleted everything, posix_mkdir, posix_rmdir,
9054 * posix_open, posix_unlink, on
9055 * POSIX_foo/foo should return NT_STATUS_OBJECT_PATH_NOT_FOUND
9056 * not silently create POSIX_foo/foo.
9059 status = cli_posix_mkdir(cli, fname_foo_foo, 0777);
9060 if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_PATH_NOT_FOUND)) {
9061 printf("cli_posix_mkdir of %s should fail with "
9062 "NT_STATUS_OBJECT_PATH_NOT_FOUND got "
9069 status = cli_posix_rmdir(cli, fname_foo_foo);
9070 if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_PATH_NOT_FOUND)) {
9071 printf("cli_posix_rmdir of %s should fail with "
9072 "NT_STATUS_OBJECT_PATH_NOT_FOUND got "
9079 status = cli_posix_open(cli,
9084 if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_PATH_NOT_FOUND)) {
9085 printf("cli_posix_open of %s should fail with "
9086 "NT_STATUS_OBJECT_PATH_NOT_FOUND got "
9093 status = cli_posix_unlink(cli, fname_foo_foo);
9094 if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_PATH_NOT_FOUND)) {
9095 printf("cli_posix_unlink of %s should fail with "
9096 "NT_STATUS_OBJECT_PATH_NOT_FOUND got "
9103 status = cli_posix_mkdir(cli, fname_foo, 0777);
9104 if (!NT_STATUS_IS_OK(status)) {
9105 printf("cli_posix_mkdir of %s failed\n", fname_foo);
9109 status = cli_posix_mkdir(cli, fname_Foo, 0777);
9110 if (!NT_STATUS_IS_OK(status)) {
9111 printf("cli_posix_mkdir of %s failed\n", fname_Foo);
9115 status = cli_posix_mkdir(cli, fname_foo_foo, 0777);
9116 if (!NT_STATUS_IS_OK(status)) {
9117 printf("cli_posix_mkdir of %s failed\n", fname_foo_foo);
9121 status = cli_posix_mkdir(cli, fname_foo_Foo, 0777);
9122 if (!NT_STATUS_IS_OK(status)) {
9123 printf("cli_posix_mkdir of %s failed\n", fname_foo_Foo);
9127 status = cli_posix_mkdir(cli, fname_Foo_foo, 0777);
9128 if (!NT_STATUS_IS_OK(status)) {
9129 printf("cli_posix_mkdir of %s failed\n", fname_Foo_foo);
9133 status = cli_posix_mkdir(cli, fname_Foo_Foo, 0777);
9134 if (!NT_STATUS_IS_OK(status)) {
9135 printf("cli_posix_mkdir of %s failed\n", fname_Foo_Foo);
9139 printf("POSIX mkdir test passed\n");
9144 if (fnum != (uint16_t)-1) {
9145 cli_close(cli, fnum);
9146 fnum = (uint16_t)-1;
9149 cli_posix_rmdir(cli, fname_foo_foo);
9150 cli_posix_rmdir(cli, fname_foo_Foo);
9151 cli_posix_rmdir(cli, fname_foo);
9153 cli_posix_rmdir(cli, fname_Foo_foo);
9154 cli_posix_rmdir(cli, fname_Foo_Foo);
9155 cli_posix_rmdir(cli, fname_Foo);
9157 if (!torture_close_connection(cli)) {
9165 struct posix_acl_oplock_state {
9166 struct tevent_context *ev;
9167 struct cli_state *cli;
9173 static void posix_acl_oplock_got_break(struct tevent_req *req)
9175 struct posix_acl_oplock_state *state = tevent_req_callback_data(
9176 req, struct posix_acl_oplock_state);
9181 status = cli_smb_oplock_break_waiter_recv(req, &fnum, &level);
9183 if (!NT_STATUS_IS_OK(status)) {
9184 printf("cli_smb_oplock_break_waiter_recv returned %s\n",
9188 *state->got_break = true;
9190 req = cli_oplock_ack_send(state, state->ev, state->cli, fnum,
9193 printf("cli_oplock_ack_send failed\n");
9198 static void posix_acl_oplock_got_acl(struct tevent_req *req)
9200 struct posix_acl_oplock_state *state = tevent_req_callback_data(
9201 req, struct posix_acl_oplock_state);
9202 size_t ret_size = 0;
9203 char *ret_data = NULL;
9205 state->status = cli_posix_getacl_recv(req,
9210 if (!NT_STATUS_IS_OK(state->status)) {
9211 printf("cli_posix_getacl_recv returned %s\n",
9212 nt_errstr(state->status));
9214 *state->acl_ret = true;
9217 static bool run_posix_acl_oplock_test(int dummy)
9219 struct tevent_context *ev;
9220 struct cli_state *cli1, *cli2;
9221 struct tevent_req *oplock_req, *getacl_req;
9222 const char *fname = "posix_acl_oplock";
9224 int saved_use_oplocks = use_oplocks;
9226 bool correct = true;
9227 bool got_break = false;
9228 bool acl_ret = false;
9230 struct posix_acl_oplock_state *state;
9232 printf("starting posix_acl_oplock test\n");
9234 if (!torture_open_connection(&cli1, 0)) {
9235 use_level_II_oplocks = false;
9236 use_oplocks = saved_use_oplocks;
9240 if (!torture_open_connection(&cli2, 1)) {
9241 use_level_II_oplocks = false;
9242 use_oplocks = saved_use_oplocks;
9246 /* Setup posix on cli2 only. */
9247 status = torture_setup_unix_extensions(cli2);
9248 if (!NT_STATUS_IS_OK(status)) {
9252 smbXcli_conn_set_sockopt(cli1->conn, sockops);
9253 smbXcli_conn_set_sockopt(cli2->conn, sockops);
9255 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
9257 /* Create the file on the Windows connection. */
9258 status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
9260 if (!NT_STATUS_IS_OK(status)) {
9261 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
9265 status = cli_close(cli1, fnum);
9266 if (!NT_STATUS_IS_OK(status)) {
9267 printf("close1 failed (%s)\n", nt_errstr(status));
9271 cli1->use_oplocks = true;
9273 /* Open with oplock. */
9274 status = cli_ntcreate(cli1,
9278 FILE_ATTRIBUTE_NORMAL,
9279 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
9286 if (!NT_STATUS_IS_OK(status)) {
9287 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
9291 ev = samba_tevent_context_init(talloc_tos());
9293 printf("tevent_context_init failed\n");
9297 state = talloc_zero(ev, struct posix_acl_oplock_state);
9298 if (state == NULL) {
9299 printf("talloc failed\n");
9304 state->got_break = &got_break;
9305 state->acl_ret = &acl_ret;
9307 oplock_req = cli_smb_oplock_break_waiter_send(
9308 talloc_tos(), ev, cli1);
9309 if (oplock_req == NULL) {
9310 printf("cli_smb_oplock_break_waiter_send failed\n");
9313 tevent_req_set_callback(oplock_req, posix_acl_oplock_got_break, state);
9315 /* Get ACL on POSIX connection - should break oplock. */
9316 getacl_req = cli_posix_getacl_send(talloc_tos(),
9320 if (getacl_req == NULL) {
9321 printf("cli_posix_getacl_send failed\n");
9324 tevent_req_set_callback(getacl_req, posix_acl_oplock_got_acl, state);
9326 while (!got_break || !acl_ret) {
9328 ret = tevent_loop_once(ev);
9330 printf("tevent_loop_once failed: %s\n",
9336 if (!NT_STATUS_IS_OK(state->status)) {
9337 printf("getacl failed (%s)\n", nt_errstr(state->status));
9341 status = cli_close(cli1, fnum);
9342 if (!NT_STATUS_IS_OK(status)) {
9343 printf("close2 failed (%s)\n", nt_errstr(status));
9347 status = cli_unlink(cli1,
9349 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
9350 if (!NT_STATUS_IS_OK(status)) {
9351 printf("unlink failed (%s)\n", nt_errstr(status));
9355 if (!torture_close_connection(cli1)) {
9358 if (!torture_close_connection(cli2)) {
9366 printf("finished posix acl oplock test\n");
9371 static bool run_posix_acl_shareroot_test(int dummy)
9373 struct cli_state *cli;
9375 bool correct = false;
9376 char *posix_acl = NULL;
9377 size_t posix_acl_len = 0;
9378 uint16_t num_file_acls = 0;
9379 uint16_t num_dir_acls = 0;
9381 uint32_t expected_size = 0;
9382 bool got_user = false;
9383 bool got_group = false;
9384 bool got_other = false;
9385 TALLOC_CTX *frame = NULL;
9387 frame = talloc_stackframe();
9389 printf("starting posix_acl_shareroot test\n");
9391 if (!torture_open_connection(&cli, 0)) {
9396 smbXcli_conn_set_sockopt(cli->conn, sockops);
9398 status = torture_setup_unix_extensions(cli);
9399 if (!NT_STATUS_IS_OK(status)) {
9400 printf("Failed to setup unix extensions\n");
9404 /* Get the POSIX ACL on the root of the share. */
9405 status = cli_posix_getacl(cli,
9411 if (!NT_STATUS_IS_OK(status)) {
9412 printf("cli_posix_getacl of '.' failed (%s)\n",
9417 if (posix_acl_len < 6 ||
9418 SVAL(posix_acl,0) != SMB_POSIX_ACL_VERSION) {
9419 printf("getfacl ., unknown POSIX acl version %u.\n",
9420 (unsigned int)CVAL(posix_acl,0) );
9424 num_file_acls = SVAL(posix_acl,2);
9425 num_dir_acls = SVAL(posix_acl,4);
9426 expected_size = SMB_POSIX_ACL_HEADER_SIZE +
9427 SMB_POSIX_ACL_ENTRY_SIZE*
9428 (num_file_acls+num_dir_acls);
9430 if (posix_acl_len != expected_size) {
9431 printf("incorrect POSIX acl buffer size "
9432 "(should be %u, was %u).\n",
9433 (unsigned int)expected_size,
9434 (unsigned int)posix_acl_len);
9439 * We don't need to know what the ACL's are
9440 * we just need to know we have at least 3
9441 * file entries (u,g,o).
9444 for (i = 0; i < num_file_acls; i++) {
9445 unsigned char tagtype =
9447 SMB_POSIX_ACL_HEADER_SIZE+
9448 (i*SMB_POSIX_ACL_ENTRY_SIZE));
9451 case SMB_POSIX_ACL_USER_OBJ:
9454 case SMB_POSIX_ACL_GROUP_OBJ:
9457 case SMB_POSIX_ACL_OTHER:
9466 printf("Missing user entry\n");
9471 printf("Missing group entry\n");
9476 printf("Missing other entry\n");
9484 if (!torture_close_connection(cli)) {
9488 printf("finished posix acl shareroot test\n");
9494 static uint32_t open_attrs_table[] = {
9495 FILE_ATTRIBUTE_NORMAL,
9496 FILE_ATTRIBUTE_ARCHIVE,
9497 FILE_ATTRIBUTE_READONLY,
9498 FILE_ATTRIBUTE_HIDDEN,
9499 FILE_ATTRIBUTE_SYSTEM,
9501 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY,
9502 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN,
9503 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM,
9504 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN,
9505 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM,
9506 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM,
9508 FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN,
9509 FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM,
9510 FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM,
9511 FILE_ATTRIBUTE_HIDDEN,FILE_ATTRIBUTE_SYSTEM,
9514 struct trunc_open_results {
9517 uint32_t trunc_attr;
9518 uint32_t result_attr;
9521 static struct trunc_open_results attr_results[] = {
9522 { 0, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_ARCHIVE },
9523 { 1, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_ARCHIVE },
9524 { 2, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_READONLY, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY },
9525 { 16, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_ARCHIVE },
9526 { 17, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_ARCHIVE },
9527 { 18, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_READONLY, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY },
9528 { 51, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
9529 { 54, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
9530 { 56, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN },
9531 { 68, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
9532 { 71, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
9533 { 73, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM },
9534 { 99, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_HIDDEN,FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
9535 { 102, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
9536 { 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 },
9537 { 116, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
9538 { 119, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
9539 { 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 },
9540 { 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 },
9541 { 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 },
9542 { 227, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
9543 { 230, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
9544 { 232, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN },
9545 { 244, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
9546 { 247, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
9547 { 249, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM }
9550 static bool run_openattrtest(int dummy)
9552 static struct cli_state *cli1;
9553 const char *fname = "\\openattr.file";
9555 bool correct = True;
9557 unsigned int i, j, k, l;
9560 printf("starting open attr test\n");
9562 if (!torture_open_connection(&cli1, 0)) {
9566 smbXcli_conn_set_sockopt(cli1->conn, sockops);
9568 for (k = 0, i = 0; i < sizeof(open_attrs_table)/sizeof(uint32_t); i++) {
9569 cli_setatr(cli1, fname, 0, 0);
9570 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
9572 status = cli_ntcreate(cli1, fname, 0, FILE_WRITE_DATA,
9573 open_attrs_table[i], FILE_SHARE_NONE,
9574 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
9575 if (!NT_STATUS_IS_OK(status)) {
9576 printf("open %d (1) of %s failed (%s)\n", i, fname, nt_errstr(status));
9580 status = cli_close(cli1, fnum1);
9581 if (!NT_STATUS_IS_OK(status)) {
9582 printf("close %d (1) of %s failed (%s)\n", i, fname, nt_errstr(status));
9586 for (j = 0; j < sizeof(open_attrs_table)/sizeof(uint32_t); j++) {
9587 status = cli_ntcreate(cli1, fname, 0,
9588 FILE_READ_DATA|FILE_WRITE_DATA,
9589 open_attrs_table[j],
9590 FILE_SHARE_NONE, FILE_OVERWRITE,
9591 0, 0, &fnum1, NULL);
9592 if (!NT_STATUS_IS_OK(status)) {
9593 for (l = 0; l < sizeof(attr_results)/sizeof(struct trunc_open_results); l++) {
9594 if (attr_results[l].num == k) {
9595 printf("[%d] trunc open 0x%x -> 0x%x of %s failed - should have succeeded !(0x%x:%s)\n",
9596 k, open_attrs_table[i],
9597 open_attrs_table[j],
9598 fname, NT_STATUS_V(status), nt_errstr(status));
9603 if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
9604 printf("[%d] trunc open 0x%x -> 0x%x failed with wrong error code %s\n",
9605 k, open_attrs_table[i], open_attrs_table[j],
9610 printf("[%d] trunc open 0x%x -> 0x%x failed\n", k, open_attrs_table[i], open_attrs_table[j]);
9616 status = cli_close(cli1, fnum1);
9617 if (!NT_STATUS_IS_OK(status)) {
9618 printf("close %d (2) of %s failed (%s)\n", j, fname, nt_errstr(status));
9622 status = cli_getatr(cli1, fname, &attr, NULL, NULL);
9623 if (!NT_STATUS_IS_OK(status)) {
9624 printf("getatr(2) failed (%s)\n", nt_errstr(status));
9629 printf("[%d] getatr check [0x%x] trunc [0x%x] got attr 0x%x\n",
9630 k, open_attrs_table[i], open_attrs_table[j], attr );
9633 for (l = 0; l < sizeof(attr_results)/sizeof(struct trunc_open_results); l++) {
9634 if (attr_results[l].num == k) {
9635 if (attr != attr_results[l].result_attr ||
9636 open_attrs_table[i] != attr_results[l].init_attr ||
9637 open_attrs_table[j] != attr_results[l].trunc_attr) {
9638 printf("getatr check failed. [0x%x] trunc [0x%x] got attr 0x%x, should be 0x%x\n",
9639 open_attrs_table[i],
9640 open_attrs_table[j],
9642 attr_results[l].result_attr);
9652 cli_setatr(cli1, fname, 0, 0);
9653 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
9655 printf("open attr test %s.\n", correct ? "passed" : "failed");
9657 if (!torture_close_connection(cli1)) {
9663 static NTSTATUS list_fn(const char *mnt, struct file_info *finfo,
9664 const char *name, void *state)
9666 int *matched = (int *)state;
9667 if (matched != NULL) {
9670 return NT_STATUS_OK;
9674 test directory listing speed
9676 static bool run_dirtest(int dummy)
9679 static struct cli_state *cli;
9681 struct timeval core_start;
9682 bool correct = True;
9685 printf("starting directory test\n");
9687 if (!torture_open_connection(&cli, 0)) {
9691 smbXcli_conn_set_sockopt(cli->conn, sockops);
9694 for (i=0;i<torture_numops;i++) {
9696 slprintf(fname, sizeof(fname), "\\%x", (int)random());
9697 if (!NT_STATUS_IS_OK(cli_openx(cli, fname, O_RDWR|O_CREAT, DENY_NONE, &fnum))) {
9698 fprintf(stderr,"Failed to open %s\n", fname);
9701 cli_close(cli, fnum);
9704 core_start = timeval_current();
9707 cli_list(cli, "a*.*", 0, list_fn, &matched);
9708 printf("Matched %d\n", matched);
9711 cli_list(cli, "b*.*", 0, list_fn, &matched);
9712 printf("Matched %d\n", matched);
9715 cli_list(cli, "xyzabc", 0, list_fn, &matched);
9716 printf("Matched %d\n", matched);
9718 printf("dirtest core %g seconds\n", timeval_elapsed(&core_start));
9721 for (i=0;i<torture_numops;i++) {
9723 slprintf(fname, sizeof(fname), "\\%x", (int)random());
9724 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
9727 if (!torture_close_connection(cli)) {
9731 printf("finished dirtest\n");
9736 static NTSTATUS del_fn(const char *mnt, struct file_info *finfo, const char *mask,
9739 struct cli_state *pcli = (struct cli_state *)state;
9741 slprintf(fname, sizeof(fname), "\\LISTDIR\\%s", finfo->name);
9743 if (strcmp(finfo->name, ".") == 0 || strcmp(finfo->name, "..") == 0)
9744 return NT_STATUS_OK;
9746 if (finfo->attr & FILE_ATTRIBUTE_DIRECTORY) {
9747 if (!NT_STATUS_IS_OK(cli_rmdir(pcli, fname)))
9748 printf("del_fn: failed to rmdir %s\n,", fname );
9750 if (!NT_STATUS_IS_OK(cli_unlink(pcli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN)))
9751 printf("del_fn: failed to unlink %s\n,", fname );
9753 return NT_STATUS_OK;
9758 sees what IOCTLs are supported
9760 bool torture_ioctl_test(int dummy)
9762 static struct cli_state *cli;
9763 uint16_t device, function;
9765 const char *fname = "\\ioctl.dat";
9769 if (!torture_open_connection(&cli, 0)) {
9773 printf("starting ioctl test\n");
9775 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
9777 status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
9778 if (!NT_STATUS_IS_OK(status)) {
9779 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
9783 status = cli_raw_ioctl(cli, fnum, 0x2d0000 | (0x0420<<2), &blob);
9784 printf("ioctl device info: %s\n", nt_errstr(status));
9786 status = cli_raw_ioctl(cli, fnum, IOCTL_QUERY_JOB_INFO, &blob);
9787 printf("ioctl job info: %s\n", nt_errstr(status));
9789 for (device=0;device<0x100;device++) {
9790 printf("ioctl test with device = 0x%x\n", device);
9791 for (function=0;function<0x100;function++) {
9792 uint32_t code = (device<<16) | function;
9794 status = cli_raw_ioctl(cli, fnum, code, &blob);
9796 if (NT_STATUS_IS_OK(status)) {
9797 printf("ioctl 0x%x OK : %d bytes\n", (int)code,
9799 data_blob_free(&blob);
9804 if (!torture_close_connection(cli)) {
9813 tries varients of chkpath
9815 bool torture_chkpath_test(int dummy)
9817 static struct cli_state *cli;
9822 if (!torture_open_connection(&cli, 0)) {
9826 printf("starting chkpath test\n");
9828 /* cleanup from an old run */
9829 cli_rmdir(cli, "\\chkpath.dir\\dir2");
9830 cli_unlink(cli, "\\chkpath.dir\\*", FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
9831 cli_rmdir(cli, "\\chkpath.dir");
9833 status = cli_mkdir(cli, "\\chkpath.dir");
9834 if (!NT_STATUS_IS_OK(status)) {
9835 printf("mkdir1 failed : %s\n", nt_errstr(status));
9839 status = cli_mkdir(cli, "\\chkpath.dir\\dir2");
9840 if (!NT_STATUS_IS_OK(status)) {
9841 printf("mkdir2 failed : %s\n", nt_errstr(status));
9845 status = cli_openx(cli, "\\chkpath.dir\\foo.txt", O_RDWR|O_CREAT|O_EXCL,
9847 if (!NT_STATUS_IS_OK(status)) {
9848 printf("open1 failed (%s)\n", nt_errstr(status));
9851 cli_close(cli, fnum);
9853 status = cli_chkpath(cli, "\\chkpath.dir");
9854 if (!NT_STATUS_IS_OK(status)) {
9855 printf("chkpath1 failed: %s\n", nt_errstr(status));
9859 status = cli_chkpath(cli, "\\chkpath.dir\\dir2");
9860 if (!NT_STATUS_IS_OK(status)) {
9861 printf("chkpath2 failed: %s\n", nt_errstr(status));
9865 status = cli_chkpath(cli, "\\chkpath.dir\\foo.txt");
9866 if (!NT_STATUS_IS_OK(status)) {
9867 ret = check_error(__LINE__, status, ERRDOS, ERRbadpath,
9868 NT_STATUS_NOT_A_DIRECTORY);
9870 printf("* chkpath on a file should fail\n");
9874 status = cli_chkpath(cli, "\\chkpath.dir\\bar.txt");
9875 if (!NT_STATUS_IS_OK(status)) {
9876 ret = check_error(__LINE__, status, ERRDOS, ERRbadfile,
9877 NT_STATUS_OBJECT_NAME_NOT_FOUND);
9879 printf("* chkpath on a non existent file should fail\n");
9883 status = cli_chkpath(cli, "\\chkpath.dir\\dirxx\\bar.txt");
9884 if (!NT_STATUS_IS_OK(status)) {
9885 ret = check_error(__LINE__, status, ERRDOS, ERRbadpath,
9886 NT_STATUS_OBJECT_PATH_NOT_FOUND);
9888 printf("* chkpath on a non existent component should fail\n");
9892 cli_rmdir(cli, "\\chkpath.dir\\dir2");
9893 cli_unlink(cli, "\\chkpath.dir\\*", FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
9894 cli_rmdir(cli, "\\chkpath.dir");
9896 if (!torture_close_connection(cli)) {
9903 static bool run_eatest(int dummy)
9905 static struct cli_state *cli;
9906 const char *fname = "\\eatest.txt";
9907 bool correct = True;
9911 struct ea_struct *ea_list = NULL;
9912 TALLOC_CTX *mem_ctx = talloc_init("eatest");
9915 printf("starting eatest\n");
9917 if (!torture_open_connection(&cli, 0)) {
9918 talloc_destroy(mem_ctx);
9922 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
9924 status = cli_ntcreate(cli, fname, 0,
9925 FIRST_DESIRED_ACCESS, FILE_ATTRIBUTE_ARCHIVE,
9926 FILE_SHARE_NONE, FILE_OVERWRITE_IF,
9927 0x4044, 0, &fnum, NULL);
9928 if (!NT_STATUS_IS_OK(status)) {
9929 printf("open failed - %s\n", nt_errstr(status));
9930 talloc_destroy(mem_ctx);
9934 for (i = 0; i < 10; i++) {
9935 fstring ea_name, ea_val;
9937 slprintf(ea_name, sizeof(ea_name), "EA_%d", i);
9938 memset(ea_val, (char)i+1, i+1);
9939 status = cli_set_ea_fnum(cli, fnum, ea_name, ea_val, i+1);
9940 if (!NT_STATUS_IS_OK(status)) {
9941 printf("ea_set of name %s failed - %s\n", ea_name,
9943 talloc_destroy(mem_ctx);
9948 cli_close(cli, fnum);
9949 for (i = 0; i < 10; i++) {
9950 fstring ea_name, ea_val;
9952 slprintf(ea_name, sizeof(ea_name), "EA_%d", i+10);
9953 memset(ea_val, (char)i+1, i+1);
9954 status = cli_set_ea_path(cli, fname, ea_name, ea_val, i+1);
9955 if (!NT_STATUS_IS_OK(status)) {
9956 printf("ea_set of name %s failed - %s\n", ea_name,
9958 talloc_destroy(mem_ctx);
9963 status = cli_get_ea_list_path(cli, fname, mem_ctx, &num_eas, &ea_list);
9964 if (!NT_STATUS_IS_OK(status)) {
9965 printf("ea_get list failed - %s\n", nt_errstr(status));
9969 printf("num_eas = %d\n", (int)num_eas);
9971 if (num_eas != 20) {
9972 printf("Should be 20 EA's stored... failing.\n");
9976 for (i = 0; i < num_eas; i++) {
9977 printf("%d: ea_name = %s. Val = ", i, ea_list[i].name);
9978 dump_data(0, ea_list[i].value.data,
9979 ea_list[i].value.length);
9982 /* Setting EA's to zero length deletes them. Test this */
9983 printf("Now deleting all EA's - case indepenent....\n");
9986 cli_set_ea_path(cli, fname, "", "", 0);
9988 for (i = 0; i < 20; i++) {
9990 slprintf(ea_name, sizeof(ea_name), "ea_%d", i);
9991 status = cli_set_ea_path(cli, fname, ea_name, "", 0);
9992 if (!NT_STATUS_IS_OK(status)) {
9993 printf("ea_set of name %s failed - %s\n", ea_name,
9995 talloc_destroy(mem_ctx);
10001 status = cli_get_ea_list_path(cli, fname, mem_ctx, &num_eas, &ea_list);
10002 if (!NT_STATUS_IS_OK(status)) {
10003 printf("ea_get list failed - %s\n", nt_errstr(status));
10007 printf("num_eas = %d\n", (int)num_eas);
10008 for (i = 0; i < num_eas; i++) {
10009 printf("%d: ea_name = %s. Val = ", i, ea_list[i].name);
10010 dump_data(0, ea_list[i].value.data,
10011 ea_list[i].value.length);
10014 if (num_eas != 0) {
10015 printf("deleting EA's failed.\n");
10019 /* Try and delete a non existent EA. */
10020 status = cli_set_ea_path(cli, fname, "foo", "", 0);
10021 if (!NT_STATUS_IS_OK(status)) {
10022 printf("deleting non-existent EA 'foo' should succeed. %s\n",
10023 nt_errstr(status));
10027 talloc_destroy(mem_ctx);
10028 if (!torture_close_connection(cli)) {
10035 static bool run_dirtest1(int dummy)
10038 static struct cli_state *cli;
10041 bool correct = True;
10043 printf("starting directory test\n");
10045 if (!torture_open_connection(&cli, 0)) {
10049 smbXcli_conn_set_sockopt(cli->conn, sockops);
10051 cli_list(cli, "\\LISTDIR\\*", 0, del_fn, cli);
10052 cli_list(cli, "\\LISTDIR\\*", FILE_ATTRIBUTE_DIRECTORY, del_fn, cli);
10053 cli_rmdir(cli, "\\LISTDIR");
10054 cli_mkdir(cli, "\\LISTDIR");
10056 /* Create 1000 files and 1000 directories. */
10057 for (i=0;i<1000;i++) {
10059 slprintf(fname, sizeof(fname), "\\LISTDIR\\f%d", i);
10060 if (!NT_STATUS_IS_OK(cli_ntcreate(cli, fname, 0, GENERIC_ALL_ACCESS, FILE_ATTRIBUTE_ARCHIVE,
10061 FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OVERWRITE_IF,
10062 0, 0, &fnum, NULL))) {
10063 fprintf(stderr,"Failed to open %s\n", fname);
10066 cli_close(cli, fnum);
10068 for (i=0;i<1000;i++) {
10070 slprintf(fname, sizeof(fname), "\\LISTDIR\\d%d", i);
10071 if (!NT_STATUS_IS_OK(cli_mkdir(cli, fname))) {
10072 fprintf(stderr,"Failed to open %s\n", fname);
10077 /* Now ensure that doing an old list sees both files and directories. */
10079 cli_list_old(cli, "\\LISTDIR\\*", FILE_ATTRIBUTE_DIRECTORY, list_fn, &num_seen);
10080 printf("num_seen = %d\n", num_seen );
10081 /* We should see 100 files + 1000 directories + . and .. */
10082 if (num_seen != 2002)
10085 /* Ensure if we have the "must have" bits we only see the
10086 * relevent entries.
10089 cli_list_old(cli, "\\LISTDIR\\*", (FILE_ATTRIBUTE_DIRECTORY<<8)|FILE_ATTRIBUTE_DIRECTORY, list_fn, &num_seen);
10090 printf("num_seen = %d\n", num_seen );
10091 if (num_seen != 1002)
10095 cli_list_old(cli, "\\LISTDIR\\*", (FILE_ATTRIBUTE_ARCHIVE<<8)|FILE_ATTRIBUTE_DIRECTORY, list_fn, &num_seen);
10096 printf("num_seen = %d\n", num_seen );
10097 if (num_seen != 1000)
10100 /* Delete everything. */
10101 cli_list(cli, "\\LISTDIR\\*", 0, del_fn, cli);
10102 cli_list(cli, "\\LISTDIR\\*", FILE_ATTRIBUTE_DIRECTORY, del_fn, cli);
10103 cli_rmdir(cli, "\\LISTDIR");
10106 printf("Matched %d\n", cli_list(cli, "a*.*", 0, list_fn, NULL));
10107 printf("Matched %d\n", cli_list(cli, "b*.*", 0, list_fn, NULL));
10108 printf("Matched %d\n", cli_list(cli, "xyzabc", 0, list_fn, NULL));
10111 if (!torture_close_connection(cli)) {
10115 printf("finished dirtest1\n");
10120 static bool run_error_map_extract(int dummy) {
10122 static struct cli_state *c_dos;
10123 static struct cli_state *c_nt;
10131 NTSTATUS nt_status;
10135 /* NT-Error connection */
10137 disable_spnego = true;
10138 if (!(c_nt = open_nbt_connection())) {
10139 disable_spnego = false;
10142 disable_spnego = false;
10144 status = smbXcli_negprot(c_nt->conn, c_nt->timeout, PROTOCOL_CORE,
10147 if (!NT_STATUS_IS_OK(status)) {
10148 printf("%s rejected the NT-error negprot (%s)\n", host,
10149 nt_errstr(status));
10150 cli_shutdown(c_nt);
10154 status = cli_session_setup_anon(c_nt);
10155 if (!NT_STATUS_IS_OK(status)) {
10156 printf("%s rejected the NT-error initial session setup (%s)\n",host, nt_errstr(status));
10160 /* DOS-Error connection */
10162 disable_spnego = true;
10163 force_dos_errors = true;
10164 if (!(c_dos = open_nbt_connection())) {
10165 disable_spnego = false;
10166 force_dos_errors = false;
10169 disable_spnego = false;
10170 force_dos_errors = false;
10172 status = smbXcli_negprot(c_dos->conn, c_dos->timeout, PROTOCOL_CORE,
10174 if (!NT_STATUS_IS_OK(status)) {
10175 printf("%s rejected the DOS-error negprot (%s)\n", host,
10176 nt_errstr(status));
10177 cli_shutdown(c_dos);
10181 status = cli_session_setup_anon(c_dos);
10182 if (!NT_STATUS_IS_OK(status)) {
10183 printf("%s rejected the DOS-error initial session setup (%s)\n",
10184 host, nt_errstr(status));
10188 c_nt->map_dos_errors = false;
10189 c_dos->map_dos_errors = false;
10191 for (error=(0xc0000000 | 0x1); error < (0xc0000000| 0xFFF); error++) {
10192 struct cli_credentials *user_creds = NULL;
10194 fstr_sprintf(user, "%X", error);
10196 user_creds = cli_session_creds_init(talloc_tos(),
10201 false, /* use_kerberos */
10202 false, /* fallback_after_kerberos */
10203 false, /* use_ccache */
10204 false); /* password_is_nt_hash */
10205 if (user_creds == NULL) {
10206 printf("cli_session_creds_init(%s) failed\n", user);
10210 status = cli_session_setup_creds(c_nt, user_creds);
10211 if (NT_STATUS_IS_OK(status)) {
10212 printf("/** Session setup succeeded. This shouldn't happen...*/\n");
10215 /* Case #1: 32-bit NT errors */
10216 if (!NT_STATUS_IS_DOS(status)) {
10217 nt_status = status;
10219 printf("/** Dos error on NT connection! (%s) */\n",
10220 nt_errstr(status));
10221 nt_status = NT_STATUS(0xc0000000);
10224 status = cli_session_setup_creds(c_dos, user_creds);
10225 if (NT_STATUS_IS_OK(status)) {
10226 printf("/** Session setup succeeded. This shouldn't happen...*/\n");
10229 /* Case #1: 32-bit NT errors */
10230 if (NT_STATUS_IS_DOS(status)) {
10231 printf("/** NT error on DOS connection! (%s) */\n",
10232 nt_errstr(status));
10233 errnum = errclass = 0;
10235 errclass = NT_STATUS_DOS_CLASS(status);
10236 errnum = NT_STATUS_DOS_CODE(status);
10239 if (NT_STATUS_V(nt_status) != error) {
10240 printf("/*\t{ This NT error code was 'sqashed'\n\t from %s to %s \n\t during the session setup }\n*/\n",
10241 get_nt_error_c_code(talloc_tos(), NT_STATUS(error)),
10242 get_nt_error_c_code(talloc_tos(), nt_status));
10245 printf("\t{%s,\t%s,\t%s},\n",
10246 smb_dos_err_class(errclass),
10247 smb_dos_err_name(errclass, errnum),
10248 get_nt_error_c_code(talloc_tos(), NT_STATUS(error)));
10250 TALLOC_FREE(user_creds);
10255 static bool run_sesssetup_bench(int dummy)
10257 static struct cli_state *c;
10258 const char *fname = "\\file.dat";
10263 if (!torture_open_connection(&c, 0)) {
10267 status = cli_ntcreate(c, fname, 0, GENERIC_ALL_ACCESS|DELETE_ACCESS,
10268 FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
10269 FILE_DELETE_ON_CLOSE, 0, &fnum, NULL);
10270 if (!NT_STATUS_IS_OK(status)) {
10271 d_printf("open %s failed: %s\n", fname, nt_errstr(status));
10275 for (i=0; i<torture_numops; i++) {
10276 status = cli_session_setup_creds(c, torture_creds);
10277 if (!NT_STATUS_IS_OK(status)) {
10278 d_printf("(%s) cli_session_setup_creds failed: %s\n",
10279 __location__, nt_errstr(status));
10283 d_printf("\r%d ", (int)cli_state_get_uid(c));
10285 status = cli_ulogoff(c);
10286 if (!NT_STATUS_IS_OK(status)) {
10287 d_printf("(%s) cli_ulogoff failed: %s\n",
10288 __location__, nt_errstr(status));
10296 static bool subst_test(const char *str, const char *user, const char *domain,
10297 uid_t uid, gid_t gid, const char *expected)
10300 bool result = true;
10302 subst = talloc_sub_specified(talloc_tos(), str, user, NULL, domain, uid, gid);
10304 if (strcmp(subst, expected) != 0) {
10305 printf("sub_specified(%s, %s, %s, %d, %d) returned [%s], expected "
10306 "[%s]\n", str, user, domain, (int)uid, (int)gid, subst,
10311 TALLOC_FREE(subst);
10315 static void chain1_open_completion(struct tevent_req *req)
10319 status = cli_openx_recv(req, &fnum);
10322 d_printf("cli_openx_recv returned %s: %d\n",
10324 NT_STATUS_IS_OK(status) ? fnum : -1);
10327 static void chain1_write_completion(struct tevent_req *req)
10331 status = cli_write_andx_recv(req, &written);
10334 d_printf("cli_write_andx_recv returned %s: %d\n",
10336 NT_STATUS_IS_OK(status) ? (int)written : -1);
10339 static void chain1_close_completion(struct tevent_req *req)
10342 bool *done = (bool *)tevent_req_callback_data_void(req);
10344 status = cli_close_recv(req);
10349 d_printf("cli_close returned %s\n", nt_errstr(status));
10352 static bool run_chain1(int dummy)
10354 struct cli_state *cli1;
10355 struct tevent_context *evt = samba_tevent_context_init(NULL);
10356 struct tevent_req *reqs[3], *smbreqs[3];
10358 const char *str = "foobar";
10359 const char *fname = "\\test_chain";
10362 printf("starting chain1 test\n");
10363 if (!torture_open_connection(&cli1, 0)) {
10367 smbXcli_conn_set_sockopt(cli1->conn, sockops);
10369 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
10371 reqs[0] = cli_openx_create(talloc_tos(), evt, cli1, fname,
10372 O_CREAT|O_RDWR, 0, &smbreqs[0]);
10373 if (reqs[0] == NULL) return false;
10374 tevent_req_set_callback(reqs[0], chain1_open_completion, NULL);
10377 reqs[1] = cli_write_andx_create(talloc_tos(), evt, cli1, 0, 0,
10378 (const uint8_t *)str, 0, strlen(str)+1,
10379 smbreqs, 1, &smbreqs[1]);
10380 if (reqs[1] == NULL) return false;
10381 tevent_req_set_callback(reqs[1], chain1_write_completion, NULL);
10383 reqs[2] = cli_smb1_close_create(talloc_tos(), evt, cli1, 0, &smbreqs[2]);
10384 if (reqs[2] == NULL) return false;
10385 tevent_req_set_callback(reqs[2], chain1_close_completion, &done);
10387 status = smb1cli_req_chain_submit(smbreqs, ARRAY_SIZE(smbreqs));
10388 if (!NT_STATUS_IS_OK(status)) {
10393 tevent_loop_once(evt);
10396 torture_close_connection(cli1);
10400 static void chain2_sesssetup_completion(struct tevent_req *req)
10403 status = cli_session_setup_guest_recv(req);
10404 d_printf("sesssetup returned %s\n", nt_errstr(status));
10407 static void chain2_tcon_completion(struct tevent_req *req)
10409 bool *done = (bool *)tevent_req_callback_data_void(req);
10411 status = cli_tcon_andx_recv(req);
10412 d_printf("tcon_and_x returned %s\n", nt_errstr(status));
10416 static bool run_chain2(int dummy)
10418 struct cli_state *cli1;
10419 struct tevent_context *evt = samba_tevent_context_init(NULL);
10420 struct tevent_req *reqs[2], *smbreqs[2];
10423 int flags = CLI_FULL_CONNECTION_FORCE_SMB1;
10425 printf("starting chain2 test\n");
10426 status = cli_start_connection(&cli1, lp_netbios_name(), host, NULL,
10427 port_to_use, SMB_SIGNING_DEFAULT, flags);
10428 if (!NT_STATUS_IS_OK(status)) {
10432 smbXcli_conn_set_sockopt(cli1->conn, sockops);
10434 reqs[0] = cli_session_setup_guest_create(talloc_tos(), evt, cli1,
10436 if (reqs[0] == NULL) return false;
10437 tevent_req_set_callback(reqs[0], chain2_sesssetup_completion, NULL);
10439 reqs[1] = cli_tcon_andx_create(talloc_tos(), evt, cli1, "IPC$",
10440 "?????", NULL, 0, &smbreqs[1]);
10441 if (reqs[1] == NULL) return false;
10442 tevent_req_set_callback(reqs[1], chain2_tcon_completion, &done);
10444 status = smb1cli_req_chain_submit(smbreqs, ARRAY_SIZE(smbreqs));
10445 if (!NT_STATUS_IS_OK(status)) {
10450 tevent_loop_once(evt);
10453 torture_close_connection(cli1);
10458 struct torture_createdel_state {
10459 struct tevent_context *ev;
10460 struct cli_state *cli;
10463 static void torture_createdel_created(struct tevent_req *subreq);
10464 static void torture_createdel_closed(struct tevent_req *subreq);
10466 static struct tevent_req *torture_createdel_send(TALLOC_CTX *mem_ctx,
10467 struct tevent_context *ev,
10468 struct cli_state *cli,
10471 struct tevent_req *req, *subreq;
10472 struct torture_createdel_state *state;
10474 req = tevent_req_create(mem_ctx, &state,
10475 struct torture_createdel_state);
10482 subreq = cli_ntcreate_send(
10483 state, ev, cli, name, 0,
10484 FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
10485 FILE_ATTRIBUTE_NORMAL,
10486 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
10487 FILE_OPEN_IF, FILE_DELETE_ON_CLOSE,
10488 SMB2_IMPERSONATION_IMPERSONATION, 0);
10490 if (tevent_req_nomem(subreq, req)) {
10491 return tevent_req_post(req, ev);
10493 tevent_req_set_callback(subreq, torture_createdel_created, req);
10497 static void torture_createdel_created(struct tevent_req *subreq)
10499 struct tevent_req *req = tevent_req_callback_data(
10500 subreq, struct tevent_req);
10501 struct torture_createdel_state *state = tevent_req_data(
10502 req, struct torture_createdel_state);
10506 status = cli_ntcreate_recv(subreq, &fnum, NULL);
10507 TALLOC_FREE(subreq);
10508 if (tevent_req_nterror(req, status)) {
10509 DEBUG(10, ("cli_ntcreate_recv returned %s\n",
10510 nt_errstr(status)));
10514 subreq = cli_close_send(state, state->ev, state->cli, fnum);
10515 if (tevent_req_nomem(subreq, req)) {
10518 tevent_req_set_callback(subreq, torture_createdel_closed, req);
10521 static void torture_createdel_closed(struct tevent_req *subreq)
10523 struct tevent_req *req = tevent_req_callback_data(
10524 subreq, struct tevent_req);
10527 status = cli_close_recv(subreq);
10528 if (tevent_req_nterror(req, status)) {
10529 DEBUG(10, ("cli_close_recv returned %s\n", nt_errstr(status)));
10532 tevent_req_done(req);
10535 static NTSTATUS torture_createdel_recv(struct tevent_req *req)
10537 return tevent_req_simple_recv_ntstatus(req);
10540 struct torture_createdels_state {
10541 struct tevent_context *ev;
10542 struct cli_state *cli;
10543 const char *base_name;
10547 struct tevent_req **reqs;
10550 static void torture_createdels_done(struct tevent_req *subreq);
10552 static struct tevent_req *torture_createdels_send(TALLOC_CTX *mem_ctx,
10553 struct tevent_context *ev,
10554 struct cli_state *cli,
10555 const char *base_name,
10559 struct tevent_req *req;
10560 struct torture_createdels_state *state;
10563 req = tevent_req_create(mem_ctx, &state,
10564 struct torture_createdels_state);
10570 state->base_name = talloc_strdup(state, base_name);
10571 if (tevent_req_nomem(state->base_name, req)) {
10572 return tevent_req_post(req, ev);
10574 state->num_files = MAX(num_parallel, num_files);
10576 state->received = 0;
10578 state->reqs = talloc_array(state, struct tevent_req *, num_parallel);
10579 if (tevent_req_nomem(state->reqs, req)) {
10580 return tevent_req_post(req, ev);
10583 for (i=0; i<num_parallel; i++) {
10586 name = talloc_asprintf(state, "%s%8.8d", state->base_name,
10588 if (tevent_req_nomem(name, req)) {
10589 return tevent_req_post(req, ev);
10591 state->reqs[i] = torture_createdel_send(
10592 state->reqs, state->ev, state->cli, name);
10593 if (tevent_req_nomem(state->reqs[i], req)) {
10594 return tevent_req_post(req, ev);
10596 name = talloc_move(state->reqs[i], &name);
10597 tevent_req_set_callback(state->reqs[i],
10598 torture_createdels_done, req);
10604 static void torture_createdels_done(struct tevent_req *subreq)
10606 struct tevent_req *req = tevent_req_callback_data(
10607 subreq, struct tevent_req);
10608 struct torture_createdels_state *state = tevent_req_data(
10609 req, struct torture_createdels_state);
10610 size_t num_parallel = talloc_array_length(state->reqs);
10615 status = torture_createdel_recv(subreq);
10616 if (!NT_STATUS_IS_OK(status)){
10617 DEBUG(10, ("torture_createdel_recv returned %s\n",
10618 nt_errstr(status)));
10619 TALLOC_FREE(subreq);
10620 tevent_req_nterror(req, status);
10624 for (i=0; i<num_parallel; i++) {
10625 if (subreq == state->reqs[i]) {
10629 if (i == num_parallel) {
10630 DEBUG(10, ("received something we did not send\n"));
10631 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
10634 TALLOC_FREE(state->reqs[i]);
10636 if (state->sent >= state->num_files) {
10637 tevent_req_done(req);
10641 name = talloc_asprintf(state, "%s%8.8d", state->base_name,
10643 if (tevent_req_nomem(name, req)) {
10646 state->reqs[i] = torture_createdel_send(state->reqs, state->ev,
10648 if (tevent_req_nomem(state->reqs[i], req)) {
10651 name = talloc_move(state->reqs[i], &name);
10652 tevent_req_set_callback(state->reqs[i], torture_createdels_done, req);
10656 static NTSTATUS torture_createdels_recv(struct tevent_req *req)
10658 return tevent_req_simple_recv_ntstatus(req);
10661 struct swallow_notify_state {
10662 struct tevent_context *ev;
10663 struct cli_state *cli;
10665 uint32_t completion_filter;
10667 bool (*fn)(uint32_t action, const char *name, void *priv);
10671 static void swallow_notify_done(struct tevent_req *subreq);
10673 static struct tevent_req *swallow_notify_send(TALLOC_CTX *mem_ctx,
10674 struct tevent_context *ev,
10675 struct cli_state *cli,
10677 uint32_t completion_filter,
10679 bool (*fn)(uint32_t action,
10684 struct tevent_req *req, *subreq;
10685 struct swallow_notify_state *state;
10687 req = tevent_req_create(mem_ctx, &state,
10688 struct swallow_notify_state);
10694 state->fnum = fnum;
10695 state->completion_filter = completion_filter;
10696 state->recursive = recursive;
10698 state->priv = priv;
10700 subreq = cli_notify_send(state, state->ev, state->cli, state->fnum,
10701 0xffff, state->completion_filter,
10703 if (tevent_req_nomem(subreq, req)) {
10704 return tevent_req_post(req, ev);
10706 tevent_req_set_callback(subreq, swallow_notify_done, req);
10710 static void swallow_notify_done(struct tevent_req *subreq)
10712 struct tevent_req *req = tevent_req_callback_data(
10713 subreq, struct tevent_req);
10714 struct swallow_notify_state *state = tevent_req_data(
10715 req, struct swallow_notify_state);
10717 uint32_t i, num_changes;
10718 struct notify_change *changes;
10720 status = cli_notify_recv(subreq, state, &num_changes, &changes);
10721 TALLOC_FREE(subreq);
10722 if (!NT_STATUS_IS_OK(status)) {
10723 DEBUG(10, ("cli_notify_recv returned %s\n",
10724 nt_errstr(status)));
10725 tevent_req_nterror(req, status);
10729 for (i=0; i<num_changes; i++) {
10730 state->fn(changes[i].action, changes[i].name, state->priv);
10732 TALLOC_FREE(changes);
10734 subreq = cli_notify_send(state, state->ev, state->cli, state->fnum,
10735 0xffff, state->completion_filter,
10737 if (tevent_req_nomem(subreq, req)) {
10740 tevent_req_set_callback(subreq, swallow_notify_done, req);
10743 static bool print_notifies(uint32_t action, const char *name, void *priv)
10745 if (DEBUGLEVEL > 5) {
10746 d_printf("%d %s\n", (int)action, name);
10751 static void notify_bench_done(struct tevent_req *req)
10753 int *num_finished = (int *)tevent_req_callback_data_void(req);
10754 *num_finished += 1;
10757 static bool run_notify_bench(int dummy)
10759 const char *dname = "\\notify-bench";
10760 struct tevent_context *ev;
10763 struct tevent_req *req1;
10764 struct tevent_req *req2 = NULL;
10765 int i, num_unc_names;
10766 int num_finished = 0;
10768 printf("starting notify-bench test\n");
10770 if (use_multishare_conn) {
10772 unc_list = file_lines_load(multishare_conn_fname,
10773 &num_unc_names, 0, NULL);
10774 if (!unc_list || num_unc_names <= 0) {
10775 d_printf("Failed to load unc names list from '%s'\n",
10776 multishare_conn_fname);
10779 TALLOC_FREE(unc_list);
10784 ev = samba_tevent_context_init(talloc_tos());
10786 d_printf("tevent_context_init failed\n");
10790 for (i=0; i<num_unc_names; i++) {
10791 struct cli_state *cli;
10794 base_fname = talloc_asprintf(talloc_tos(), "%s\\file%3.3d.",
10796 if (base_fname == NULL) {
10800 if (!torture_open_connection(&cli, i)) {
10804 status = cli_ntcreate(cli, dname, 0,
10805 MAXIMUM_ALLOWED_ACCESS,
10806 0, FILE_SHARE_READ|FILE_SHARE_WRITE|
10808 FILE_OPEN_IF, FILE_DIRECTORY_FILE, 0,
10811 if (!NT_STATUS_IS_OK(status)) {
10812 d_printf("Could not create %s: %s\n", dname,
10813 nt_errstr(status));
10817 req1 = swallow_notify_send(talloc_tos(), ev, cli, dnum,
10818 FILE_NOTIFY_CHANGE_FILE_NAME |
10819 FILE_NOTIFY_CHANGE_DIR_NAME |
10820 FILE_NOTIFY_CHANGE_ATTRIBUTES |
10821 FILE_NOTIFY_CHANGE_LAST_WRITE,
10822 false, print_notifies, NULL);
10823 if (req1 == NULL) {
10824 d_printf("Could not create notify request\n");
10828 req2 = torture_createdels_send(talloc_tos(), ev, cli,
10829 base_fname, 10, torture_numops);
10830 if (req2 == NULL) {
10831 d_printf("Could not create createdels request\n");
10834 TALLOC_FREE(base_fname);
10836 tevent_req_set_callback(req2, notify_bench_done,
10840 while (num_finished < num_unc_names) {
10842 ret = tevent_loop_once(ev);
10844 d_printf("tevent_loop_once failed\n");
10849 if (!tevent_req_poll(req2, ev)) {
10850 d_printf("tevent_req_poll failed\n");
10853 status = torture_createdels_recv(req2);
10854 d_printf("torture_createdels_recv returned %s\n", nt_errstr(status));
10859 static bool run_mangle1(int dummy)
10861 struct cli_state *cli;
10862 const char *fname = "this_is_a_long_fname_to_be_mangled.txt";
10866 time_t change_time, access_time, write_time;
10870 printf("starting mangle1 test\n");
10871 if (!torture_open_connection(&cli, 0)) {
10875 smbXcli_conn_set_sockopt(cli->conn, sockops);
10877 status = cli_ntcreate(cli, fname, 0, GENERIC_ALL_ACCESS|DELETE_ACCESS,
10878 FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
10879 0, 0, &fnum, NULL);
10880 if (!NT_STATUS_IS_OK(status)) {
10881 d_printf("open %s failed: %s\n", fname, nt_errstr(status));
10884 cli_close(cli, fnum);
10886 status = cli_qpathinfo_alt_name(cli, fname, alt_name);
10887 if (!NT_STATUS_IS_OK(status)) {
10888 d_printf("cli_qpathinfo_alt_name failed: %s\n",
10889 nt_errstr(status));
10892 d_printf("alt_name: %s\n", alt_name);
10894 status = cli_openx(cli, alt_name, O_RDONLY, DENY_NONE, &fnum);
10895 if (!NT_STATUS_IS_OK(status)) {
10896 d_printf("cli_openx(%s) failed: %s\n", alt_name,
10897 nt_errstr(status));
10900 cli_close(cli, fnum);
10902 status = cli_qpathinfo1(cli, alt_name, &change_time, &access_time,
10903 &write_time, &size, &attr);
10904 if (!NT_STATUS_IS_OK(status)) {
10905 d_printf("cli_qpathinfo1(%s) failed: %s\n", alt_name,
10906 nt_errstr(status));
10913 static NTSTATUS mangle_illegal_list_shortname_fn(const char *mntpoint,
10914 struct file_info *f,
10918 if (f->short_name == NULL) {
10919 return NT_STATUS_OK;
10922 if (strlen(f->short_name) == 0) {
10923 return NT_STATUS_OK;
10926 printf("unexpected shortname: %s\n", f->short_name);
10928 return NT_STATUS_OBJECT_NAME_INVALID;
10931 static NTSTATUS mangle_illegal_list_name_fn(const char *mntpoint,
10932 struct file_info *f,
10936 char *name = state;
10938 printf("name: %s\n", f->name);
10939 fstrcpy(name, f->name);
10940 return NT_STATUS_OK;
10943 static bool run_mangle_illegal(int dummy)
10945 struct cli_state *cli = NULL;
10946 struct cli_state *cli_posix = NULL;
10947 const char *fname = "\\MANGLE_ILLEGAL\\this_is_a_long_fname_to_be_mangled.txt";
10948 const char *illegal_fname = "MANGLE_ILLEGAL/foo:bar";
10949 char *mangled_path = NULL;
10955 printf("starting mangle-illegal test\n");
10957 if (!torture_open_connection(&cli, 0)) {
10961 smbXcli_conn_set_sockopt(cli->conn, sockops);
10963 if (!torture_open_connection(&cli_posix, 0)) {
10967 smbXcli_conn_set_sockopt(cli_posix->conn, sockops);
10969 status = torture_setup_unix_extensions(cli_posix);
10970 if (!NT_STATUS_IS_OK(status)) {
10974 cli_rmdir(cli, "\\MANGLE_ILLEGAL");
10975 status = cli_mkdir(cli, "\\MANGLE_ILLEGAL");
10976 if (!NT_STATUS_IS_OK(status)) {
10977 printf("mkdir1 failed : %s\n", nt_errstr(status));
10982 * Create a file with illegal NTFS characters and test that we
10983 * get a usable mangled name
10986 cli_setatr(cli_posix, illegal_fname, 0, 0);
10987 cli_posix_unlink(cli_posix, illegal_fname);
10989 status = cli_posix_open(cli_posix, illegal_fname, O_RDWR|O_CREAT|O_EXCL,
10991 if (!NT_STATUS_IS_OK(status)) {
10992 printf("POSIX create of %s failed (%s)\n",
10993 illegal_fname, nt_errstr(status));
10997 status = cli_close(cli_posix, fnum);
10998 if (!NT_STATUS_IS_OK(status)) {
10999 printf("close failed (%s)\n", nt_errstr(status));
11003 status = cli_list(cli, "\\MANGLE_ILLEGAL\\*", 0, mangle_illegal_list_name_fn, &name);
11004 if (!NT_STATUS_IS_OK(status)) {
11005 d_printf("cli_list failed: %s\n", nt_errstr(status));
11009 mangled_path = talloc_asprintf(talloc_tos(), "\\MANGLE_ILLEGAL\\%s", name);
11010 if (mangled_path == NULL) {
11014 status = cli_openx(cli, mangled_path, O_RDONLY, DENY_NONE, &fnum);
11015 if (!NT_STATUS_IS_OK(status)) {
11016 d_printf("cli_openx(%s) failed: %s\n", mangled_path, nt_errstr(status));
11017 TALLOC_FREE(mangled_path);
11020 TALLOC_FREE(mangled_path);
11021 cli_close(cli, fnum);
11023 cli_setatr(cli_posix, illegal_fname, 0, 0);
11024 cli_posix_unlink(cli_posix, illegal_fname);
11027 * Create a file with a long name and check that we got *no* short name.
11030 status = cli_ntcreate(cli, fname, 0, GENERIC_ALL_ACCESS|DELETE_ACCESS,
11031 FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
11032 0, 0, &fnum, NULL);
11033 if (!NT_STATUS_IS_OK(status)) {
11034 d_printf("open %s failed: %s\n", fname, nt_errstr(status));
11037 cli_close(cli, fnum);
11039 status = cli_list(cli, fname, 0, mangle_illegal_list_shortname_fn, &alt_name);
11040 if (!NT_STATUS_IS_OK(status)) {
11041 d_printf("cli_list failed\n");
11045 cli_unlink(cli, fname, 0);
11046 cli_rmdir(cli, "\\MANGLE_ILLEGAL");
11048 if (!torture_close_connection(cli_posix)) {
11052 if (!torture_close_connection(cli)) {
11059 static size_t null_source(uint8_t *buf, size_t n, void *priv)
11061 size_t *to_pull = (size_t *)priv;
11062 size_t thistime = *to_pull;
11064 thistime = MIN(thistime, n);
11065 if (thistime == 0) {
11069 memset(buf, 0, thistime);
11070 *to_pull -= thistime;
11074 static bool run_windows_write(int dummy)
11076 struct cli_state *cli1;
11080 const char *fname = "\\writetest.txt";
11081 struct timeval start_time;
11086 printf("starting windows_write test\n");
11087 if (!torture_open_connection(&cli1, 0)) {
11091 status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
11092 if (!NT_STATUS_IS_OK(status)) {
11093 printf("open failed (%s)\n", nt_errstr(status));
11097 smbXcli_conn_set_sockopt(cli1->conn, sockops);
11099 start_time = timeval_current();
11101 for (i=0; i<torture_numops; i++) {
11103 off_t start = i * torture_blocksize;
11104 size_t to_pull = torture_blocksize - 1;
11106 status = cli_writeall(cli1, fnum, 0, &c,
11107 start + torture_blocksize - 1, 1, NULL);
11108 if (!NT_STATUS_IS_OK(status)) {
11109 printf("cli_write failed: %s\n", nt_errstr(status));
11113 status = cli_push(cli1, fnum, 0, i * torture_blocksize, torture_blocksize,
11114 null_source, &to_pull);
11115 if (!NT_STATUS_IS_OK(status)) {
11116 printf("cli_push returned: %s\n", nt_errstr(status));
11121 seconds = timeval_elapsed(&start_time);
11122 kbytes = (double)torture_blocksize * torture_numops;
11125 printf("Wrote %d kbytes in %.2f seconds: %d kb/sec\n", (int)kbytes,
11126 (double)seconds, (int)(kbytes/seconds));
11130 cli_close(cli1, fnum);
11131 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
11132 torture_close_connection(cli1);
11136 static size_t calc_expected_return(struct cli_state *cli, size_t len_requested)
11138 size_t max_pdu = 0x1FFFF;
11140 if (cli->server_posix_capabilities & CIFS_UNIX_LARGE_READ_CAP) {
11141 max_pdu = 0xFFFFFF;
11144 if (smb1cli_conn_signing_is_active(cli->conn)) {
11148 if (smb1cli_conn_encryption_on(cli->conn)) {
11149 max_pdu = CLI_BUFFER_SIZE;
11152 if ((len_requested & 0xFFFF0000) == 0xFFFF0000) {
11153 len_requested &= 0xFFFF;
11156 return MIN(len_requested,
11157 max_pdu - (MIN_SMB_SIZE + VWV(12) + 1 /* padding byte */));
11160 static bool check_read_call(struct cli_state *cli,
11163 size_t len_requested)
11166 struct tevent_req *subreq = NULL;
11167 ssize_t len_read = 0;
11168 size_t len_expected = 0;
11169 struct tevent_context *ev = NULL;
11171 ev = samba_tevent_context_init(talloc_tos());
11176 subreq = cli_read_andx_send(talloc_tos(),
11183 if (!tevent_req_poll_ntstatus(subreq, ev, &status)) {
11187 status = cli_read_andx_recv(subreq, &len_read, &buf);
11188 if (!NT_STATUS_IS_OK(status)) {
11189 d_printf("cli_read_andx_recv failed: %s\n", nt_errstr(status));
11193 TALLOC_FREE(subreq);
11196 len_expected = calc_expected_return(cli, len_requested);
11198 if (len_expected > 0x10000 && len_read == 0x10000) {
11199 /* Windows servers only return a max of 0x10000,
11200 doesn't matter if you set CAP_LARGE_READX in
11201 the client sessionsetupX call or not. */
11202 d_printf("Windows server - returned 0x10000 on a read of 0x%x\n",
11203 (unsigned int)len_requested);
11204 } else if (len_read != len_expected) {
11205 d_printf("read of 0x%x failed: got 0x%x, expected 0x%x\n",
11206 (unsigned int)len_requested,
11207 (unsigned int)len_read,
11208 (unsigned int)len_expected);
11211 d_printf("Correct read reply.\n");
11217 /* Test large readX variants. */
11218 static bool large_readx_tests(struct cli_state *cli,
11222 /* A read of 0xFFFF0001 should *always* return 1 byte. */
11223 if (check_read_call(cli, fnum, buf, 0xFFFF0001) == false) {
11226 /* A read of 0x10000 should return 0x10000 bytes. */
11227 if (check_read_call(cli, fnum, buf, 0x10000) == false) {
11230 /* A read of 0x10000 should return 0x10001 bytes. */
11231 if (check_read_call(cli, fnum, buf, 0x10001) == false) {
11234 /* A read of 0x1FFFF - (MIN_SMB_SIZE + VWV(12) should return
11235 the requested number of bytes. */
11236 if (check_read_call(cli, fnum, buf, 0x1FFFF - (MIN_SMB_SIZE + VWV(12))) == false) {
11239 /* A read of 1MB should return 1MB bytes (on Samba). */
11240 if (check_read_call(cli, fnum, buf, 0x100000) == false) {
11244 if (check_read_call(cli, fnum, buf, 0x20001) == false) {
11247 if (check_read_call(cli, fnum, buf, 0x22000001) == false) {
11250 if (check_read_call(cli, fnum, buf, 0xFFFE0001) == false) {
11256 static bool run_large_readx(int dummy)
11258 uint8_t *buf = NULL;
11259 struct cli_state *cli1 = NULL;
11260 struct cli_state *cli2 = NULL;
11261 bool correct = false;
11262 const char *fname = "\\large_readx.dat";
11264 uint16_t fnum1 = UINT16_MAX;
11265 uint32_t normal_caps = 0;
11266 size_t file_size = 20*1024*1024;
11267 TALLOC_CTX *frame = talloc_stackframe();
11271 enum smb_signing_setting signing_setting;
11272 enum protocol_types protocol;
11276 .signing_setting = SMB_SIGNING_IF_REQUIRED,
11277 .protocol = PROTOCOL_NT1,
11279 .name = "NT1 - SIGNING_REQUIRED",
11280 .signing_setting = SMB_SIGNING_REQUIRED,
11281 .protocol = PROTOCOL_NT1,
11285 printf("starting large_readx test\n");
11287 if (!torture_open_connection(&cli1, 0)) {
11291 normal_caps = smb1cli_conn_capabilities(cli1->conn);
11293 if (!(normal_caps & CAP_LARGE_READX)) {
11294 d_printf("Server doesn't have CAP_LARGE_READX 0x%x\n",
11295 (unsigned int)normal_caps);
11299 /* Create a file of size 4MB. */
11300 status = cli_ntcreate(cli1, fname, 0, GENERIC_ALL_ACCESS,
11301 FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
11302 0, 0, &fnum1, NULL);
11304 if (!NT_STATUS_IS_OK(status)) {
11305 d_printf("open %s failed: %s\n", fname, nt_errstr(status));
11309 /* Write file_size bytes. */
11310 buf = talloc_zero_array(frame, uint8_t, file_size);
11315 status = cli_writeall(cli1,
11322 if (!NT_STATUS_IS_OK(status)) {
11323 d_printf("cli_writeall failed: %s\n", nt_errstr(status));
11327 status = cli_close(cli1, fnum1);
11328 if (!NT_STATUS_IS_OK(status)) {
11329 d_printf("cli_close failed: %s\n", nt_errstr(status));
11333 fnum1 = UINT16_MAX;
11335 for (i=0; i < ARRAY_SIZE(runs); i++) {
11336 enum smb_signing_setting saved_signing_setting = signing_state;
11337 uint16_t fnum2 = -1;
11340 (runs[i].signing_setting == SMB_SIGNING_REQUIRED))
11342 d_printf("skip[%u] - %s\n", (unsigned)i, runs[i].name);
11346 d_printf("run[%u] - %s\n", (unsigned)i, runs[i].name);
11348 signing_state = runs[i].signing_setting;
11349 cli2 = open_nbt_connection();
11350 signing_state = saved_signing_setting;
11351 if (cli2 == NULL) {
11355 status = smbXcli_negprot(cli2->conn,
11359 if (!NT_STATUS_IS_OK(status)) {
11363 status = cli_session_setup_creds(cli2, torture_creds);
11364 if (!NT_STATUS_IS_OK(status)) {
11368 status = cli_tree_connect(cli2,
11372 if (!NT_STATUS_IS_OK(status)) {
11376 cli_set_timeout(cli2, 120000); /* set a really long timeout (2 minutes) */
11378 normal_caps = smb1cli_conn_capabilities(cli2->conn);
11380 if (!(normal_caps & CAP_LARGE_READX)) {
11381 d_printf("Server doesn't have CAP_LARGE_READX 0x%x\n",
11382 (unsigned int)normal_caps);
11387 if (force_cli_encryption(cli2, share) == false) {
11390 } else if (SERVER_HAS_UNIX_CIFS(cli2)) {
11391 uint16_t major, minor;
11392 uint32_t caplow, caphigh;
11394 status = cli_unix_extensions_version(cli2,
11396 &caplow, &caphigh);
11397 if (!NT_STATUS_IS_OK(status)) {
11402 status = cli_ntcreate(cli2, fname, 0, FILE_READ_DATA,
11403 FILE_ATTRIBUTE_NORMAL, 0, FILE_OPEN,
11404 0, 0, &fnum2, NULL);
11405 if (!NT_STATUS_IS_OK(status)) {
11406 d_printf("Second open %s failed: %s\n", fname, nt_errstr(status));
11410 /* All reads must return less than file_size bytes. */
11411 if (!large_readx_tests(cli2, fnum2, buf)) {
11415 status = cli_close(cli2, fnum2);
11416 if (!NT_STATUS_IS_OK(status)) {
11417 d_printf("cli_close failed: %s\n", nt_errstr(status));
11422 if (!torture_close_connection(cli2)) {
11429 printf("Success on large_readx test\n");
11434 if (!torture_close_connection(cli2)) {
11440 if (fnum1 != UINT16_MAX) {
11441 status = cli_close(cli1, fnum1);
11442 if (!NT_STATUS_IS_OK(status)) {
11443 d_printf("cli_close failed: %s\n", nt_errstr(status));
11445 fnum1 = UINT16_MAX;
11448 status = cli_unlink(cli1, fname,
11449 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
11450 if (!NT_STATUS_IS_OK(status)) {
11451 printf("unlink failed (%s)\n", nt_errstr(status));
11454 if (!torture_close_connection(cli1)) {
11459 TALLOC_FREE(frame);
11461 printf("finished large_readx test\n");
11465 static NTSTATUS msdfs_attribute_list_fn(const char *mnt,
11466 struct file_info *finfo,
11468 void *private_data)
11470 uint32_t *p_attr = (uint32_t *)private_data;
11472 if (strequal(finfo->name, test_filename)) {
11473 *p_attr = finfo->attr;
11476 return NT_STATUS_OK;
11479 static bool run_msdfs_attribute(int dummy)
11481 static struct cli_state *cli;
11482 bool correct = false;
11486 printf("Starting MSDFS-ATTRIBUTE test\n");
11488 if (test_filename == NULL || test_filename[0] == '\0') {
11489 printf("MSDFS-ATTRIBUTE test "
11490 "needs -f filename-of-msdfs-link\n");
11495 * NB. We use torture_open_connection_flags() not
11496 * torture_open_connection() as the latter forces
11499 if (!torture_open_connection_flags(&cli, 0, 0)) {
11503 smbXcli_conn_set_sockopt(cli->conn, sockops);
11505 status = cli_list(cli,
11507 FILE_ATTRIBUTE_DIRECTORY,
11508 msdfs_attribute_list_fn,
11511 if (!NT_STATUS_IS_OK(status)) {
11512 printf("cli_list failed with %s\n",
11513 nt_errstr(status));
11516 if ((attr & FILE_ATTRIBUTE_REPARSE_POINT) == 0) {
11517 printf("file %s should have "
11518 "FILE_ATTRIBUTE_REPARSE_POINT set. attr = 0x%x\n",
11520 (unsigned int)attr);
11524 if ((attr & FILE_ATTRIBUTE_DIRECTORY) == 0) {
11525 printf("file %s should have "
11526 "FILE_ATTRIBUTE_DIRECTORY set. attr = 0x%x\n",
11528 (unsigned int)attr);
11536 torture_close_connection(cli);
11540 static bool run_cli_echo(int dummy)
11542 struct cli_state *cli;
11545 printf("starting cli_echo test\n");
11546 if (!torture_open_connection(&cli, 0)) {
11549 smbXcli_conn_set_sockopt(cli->conn, sockops);
11551 status = cli_echo(cli, 5, data_blob_const("hello", 5));
11553 d_printf("cli_echo returned %s\n", nt_errstr(status));
11555 torture_close_connection(cli);
11556 return NT_STATUS_IS_OK(status);
11559 static int splice_status(off_t written, void *priv)
11564 static bool run_cli_splice(int dummy)
11566 uint8_t *buf = NULL;
11567 struct cli_state *cli1 = NULL;
11568 bool correct = false;
11569 const char *fname_src = "\\splice_src.dat";
11570 const char *fname_dst = "\\splice_dst.dat";
11572 uint16_t fnum1 = UINT16_MAX;
11573 uint16_t fnum2 = UINT16_MAX;
11574 size_t file_size = 2*1024*1024;
11575 size_t splice_size = 1*1024*1024 + 713;
11576 uint8_t digest1[16], digest2[16];
11579 TALLOC_CTX *frame = talloc_stackframe();
11581 printf("starting cli_splice test\n");
11583 if (!torture_open_connection(&cli1, 0)) {
11587 cli_unlink(cli1, fname_src,
11588 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
11589 cli_unlink(cli1, fname_dst,
11590 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
11592 /* Create a file */
11593 status = cli_ntcreate(cli1, fname_src, 0, GENERIC_ALL_ACCESS,
11594 FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
11595 0, 0, &fnum1, NULL);
11597 if (!NT_STATUS_IS_OK(status)) {
11598 d_printf("open %s failed: %s\n", fname_src, nt_errstr(status));
11602 /* Write file_size bytes - must be bigger than splice_size. */
11603 buf = talloc_zero_array(frame, uint8_t, file_size);
11605 d_printf("talloc_fail\n");
11609 /* Fill it with random numbers. */
11610 generate_random_buffer(buf, file_size);
11612 /* MD5 the first 1MB + 713 bytes. */
11613 gnutls_hash_fast(GNUTLS_DIG_MD5,
11618 status = cli_writeall(cli1,
11625 if (!NT_STATUS_IS_OK(status)) {
11626 d_printf("cli_writeall failed: %s\n", nt_errstr(status));
11630 status = cli_ntcreate(cli1, fname_dst, 0, GENERIC_ALL_ACCESS,
11631 FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
11632 0, 0, &fnum2, NULL);
11634 if (!NT_STATUS_IS_OK(status)) {
11635 d_printf("open %s failed: %s\n", fname_dst, nt_errstr(status));
11639 /* Now splice 1MB + 713 bytes. */
11640 status = cli_splice(cli1,
11651 if (!NT_STATUS_IS_OK(status)) {
11652 d_printf("cli_splice failed: %s\n", nt_errstr(status));
11656 /* Clear the old buffer. */
11657 memset(buf, '\0', file_size);
11659 /* Read the new file. */
11660 status = cli_read(cli1, fnum2, (char *)buf, 0, splice_size, &nread);
11661 if (!NT_STATUS_IS_OK(status)) {
11662 d_printf("cli_read failed: %s\n", nt_errstr(status));
11665 if (nread != splice_size) {
11666 d_printf("bad read of 0x%x, should be 0x%x\n",
11667 (unsigned int)nread,
11668 (unsigned int)splice_size);
11672 /* MD5 the first 1MB + 713 bytes. */
11673 gnutls_hash_fast(GNUTLS_DIG_MD5,
11678 /* Must be the same. */
11679 if (memcmp(digest1, digest2, 16) != 0) {
11680 d_printf("bad MD5 compare\n");
11685 printf("Success on cli_splice test\n");
11690 if (fnum1 != UINT16_MAX) {
11691 cli_close(cli1, fnum1);
11693 if (fnum2 != UINT16_MAX) {
11694 cli_close(cli1, fnum2);
11697 cli_unlink(cli1, fname_src,
11698 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
11699 cli_unlink(cli1, fname_dst,
11700 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
11702 if (!torture_close_connection(cli1)) {
11707 TALLOC_FREE(frame);
11711 static bool run_uid_regression_test(int dummy)
11713 static struct cli_state *cli;
11716 bool correct = True;
11717 struct smbXcli_tcon *orig_tcon = NULL;
11720 printf("starting uid regression test\n");
11722 if (!torture_open_connection(&cli, 0)) {
11726 smbXcli_conn_set_sockopt(cli->conn, sockops);
11728 /* Ok - now save then logoff our current user. */
11729 old_vuid = cli_state_get_uid(cli);
11731 status = cli_ulogoff(cli);
11732 if (!NT_STATUS_IS_OK(status)) {
11733 d_printf("(%s) cli_ulogoff failed: %s\n",
11734 __location__, nt_errstr(status));
11739 cli_state_set_uid(cli, old_vuid);
11741 /* Try an operation. */
11742 status = cli_mkdir(cli, "\\uid_reg_test");
11743 if (NT_STATUS_IS_OK(status)) {
11744 d_printf("(%s) cli_mkdir succeeded\n",
11749 /* Should be bad uid. */
11750 if (!check_error(__LINE__, status, ERRSRV, ERRbaduid,
11751 NT_STATUS_USER_SESSION_DELETED)) {
11757 old_cnum = cli_state_get_tid(cli);
11758 orig_tcon = cli_state_save_tcon(cli);
11759 if (orig_tcon == NULL) {
11764 /* Now try a SMBtdis with the invalid vuid set to zero. */
11765 cli_state_set_uid(cli, 0);
11767 /* This should succeed. */
11768 status = cli_tdis(cli);
11770 if (NT_STATUS_IS_OK(status)) {
11771 d_printf("First tdis with invalid vuid should succeed.\n");
11773 d_printf("First tdis failed (%s)\n", nt_errstr(status));
11775 cli_state_restore_tcon(cli, orig_tcon);
11779 cli_state_restore_tcon(cli, orig_tcon);
11780 cli_state_set_uid(cli, old_vuid);
11781 cli_state_set_tid(cli, old_cnum);
11783 /* This should fail. */
11784 status = cli_tdis(cli);
11785 if (NT_STATUS_IS_OK(status)) {
11786 d_printf("Second tdis with invalid vuid should fail - succeeded instead !.\n");
11790 /* Should be bad tid. */
11791 if (!check_error(__LINE__, status, ERRSRV, ERRinvnid,
11792 NT_STATUS_NETWORK_NAME_DELETED)) {
11798 cli_rmdir(cli, "\\uid_reg_test");
11807 static const char *illegal_chars = "*\\/?<>|\":";
11808 static char force_shortname_chars[] = " +,.[];=\177";
11810 static NTSTATUS shortname_del_fn(const char *mnt, struct file_info *finfo,
11811 const char *mask, void *state)
11813 struct cli_state *pcli = (struct cli_state *)state;
11815 NTSTATUS status = NT_STATUS_OK;
11817 slprintf(fname, sizeof(fname), "\\shortname\\%s", finfo->name);
11819 if (strcmp(finfo->name, ".") == 0 || strcmp(finfo->name, "..") == 0)
11820 return NT_STATUS_OK;
11822 if (finfo->attr & FILE_ATTRIBUTE_DIRECTORY) {
11823 status = cli_rmdir(pcli, fname);
11824 if (!NT_STATUS_IS_OK(status)) {
11825 printf("del_fn: failed to rmdir %s\n,", fname );
11828 status = cli_unlink(pcli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
11829 if (!NT_STATUS_IS_OK(status)) {
11830 printf("del_fn: failed to unlink %s\n,", fname );
11842 static NTSTATUS shortname_list_fn(const char *mnt, struct file_info *finfo,
11843 const char *name, void *state)
11845 struct sn_state *s = (struct sn_state *)state;
11849 printf("shortname list: i = %d, name = |%s|, shortname = |%s|\n",
11850 i, finfo->name, finfo->short_name);
11853 if (strchr(force_shortname_chars, i)) {
11854 if (!finfo->short_name) {
11855 /* Shortname not created when it should be. */
11856 d_printf("(%s) ERROR: Shortname was not created for file %s containing %d\n",
11857 __location__, finfo->name, i);
11860 } else if (finfo->short_name){
11861 /* Shortname created when it should not be. */
11862 d_printf("(%s) ERROR: Shortname %s was created for file %s\n",
11863 __location__, finfo->short_name, finfo->name);
11867 return NT_STATUS_OK;
11870 static bool run_shortname_test(int dummy)
11872 static struct cli_state *cli;
11873 bool correct = True;
11879 printf("starting shortname test\n");
11881 if (!torture_open_connection(&cli, 0)) {
11885 smbXcli_conn_set_sockopt(cli->conn, sockops);
11887 cli_list(cli, "\\shortname\\*", 0, shortname_del_fn, cli);
11888 cli_list(cli, "\\shortname\\*", FILE_ATTRIBUTE_DIRECTORY, shortname_del_fn, cli);
11889 cli_rmdir(cli, "\\shortname");
11891 status = cli_mkdir(cli, "\\shortname");
11892 if (!NT_STATUS_IS_OK(status)) {
11893 d_printf("(%s) cli_mkdir of \\shortname failed: %s\n",
11894 __location__, nt_errstr(status));
11899 if (strlcpy(fname, "\\shortname\\", sizeof(fname)) >= sizeof(fname)) {
11903 if (strlcat(fname, "test .txt", sizeof(fname)) >= sizeof(fname)) {
11910 for (i = 32; i < 128; i++) {
11911 uint16_t fnum = (uint16_t)-1;
11915 if (strchr(illegal_chars, i)) {
11920 status = cli_ntcreate(cli, fname, 0, GENERIC_ALL_ACCESS, FILE_ATTRIBUTE_NORMAL,
11921 FILE_SHARE_READ|FILE_SHARE_WRITE,
11922 FILE_OVERWRITE_IF, 0, 0, &fnum, NULL);
11923 if (!NT_STATUS_IS_OK(status)) {
11924 d_printf("(%s) cli_nt_create of %s failed: %s\n",
11925 __location__, fname, nt_errstr(status));
11929 cli_close(cli, fnum);
11932 status = cli_list(cli, "\\shortname\\test*.*", 0,
11933 shortname_list_fn, &s);
11934 if (s.matched != 1) {
11935 d_printf("(%s) failed to list %s: %s\n",
11936 __location__, fname, nt_errstr(status));
11941 status = cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
11942 if (!NT_STATUS_IS_OK(status)) {
11943 d_printf("(%s) failed to delete %s: %s\n",
11944 __location__, fname, nt_errstr(status));
11957 cli_list(cli, "\\shortname\\*", 0, shortname_del_fn, cli);
11958 cli_list(cli, "\\shortname\\*", FILE_ATTRIBUTE_DIRECTORY, shortname_del_fn, cli);
11959 cli_rmdir(cli, "\\shortname");
11960 torture_close_connection(cli);
11964 TLDAPRC callback_code;
11966 static void pagedsearch_cb(struct tevent_req *req)
11969 struct tldap_message *msg;
11972 rc = tldap_search_paged_recv(req, talloc_tos(), &msg);
11973 if (!TLDAP_RC_IS_SUCCESS(rc)) {
11974 d_printf("tldap_search_paged_recv failed: %s\n",
11975 tldap_rc2string(rc));
11976 callback_code = rc;
11979 if (tldap_msg_type(msg) != TLDAP_RES_SEARCH_ENTRY) {
11983 if (!tldap_entry_dn(msg, &dn)) {
11984 d_printf("tldap_entry_dn failed\n");
11987 d_printf("%s\n", dn);
11991 enum tldap_extended_val {
11998 * Construct an extended dn control with either no value, 0 or 1
12000 * No value and 0 are equivalent (non-hyphenated GUID)
12001 * 1 has the hyphenated GUID
12003 static struct tldap_control *
12004 tldap_build_extended_control(enum tldap_extended_val val)
12006 struct tldap_control empty_control;
12007 struct asn1_data *data;
12009 ZERO_STRUCT(empty_control);
12011 if (val != EXTENDED_NONE) {
12012 data = asn1_init(talloc_tos(), ASN1_MAX_TREE_DEPTH);
12018 if (!asn1_push_tag(data, ASN1_SEQUENCE(0))) {
12022 if (!asn1_write_Integer(data, (int)val)) {
12026 if (!asn1_pop_tag(data)) {
12030 if (!asn1_blob(data, &empty_control.value)) {
12035 empty_control.oid = "1.2.840.113556.1.4.529";
12036 empty_control.critical = true;
12038 return tldap_add_control(talloc_tos(), NULL, 0, &empty_control);
12042 static bool tldap_test_dn_guid_format(struct tldap_context *ld, const char *basedn,
12043 enum tldap_extended_val control_val)
12045 struct tldap_control *control = tldap_build_extended_control(control_val);
12047 struct tldap_message **msg;
12050 rc = tldap_search(ld, basedn, TLDAP_SCOPE_BASE,
12051 "(objectClass=*)", NULL, 0, 0,
12053 0, 0, 0, 0, talloc_tos(), &msg);
12054 if (!TLDAP_RC_IS_SUCCESS(rc)) {
12055 d_printf("tldap_search for domain DN failed: %s\n",
12056 tldap_errstr(talloc_tos(), ld, rc));
12060 if (!tldap_entry_dn(msg[0], &dn)) {
12061 d_printf("tldap_search domain DN fetch failed: %s\n",
12062 tldap_errstr(talloc_tos(), ld, rc));
12066 d_printf("%s\n", dn);
12069 uint32_t time_mid, time_hi_and_version;
12070 uint32_t clock_seq[2];
12074 switch (control_val) {
12075 case EXTENDED_NONE:
12076 case EXTENDED_ZERO:
12078 * When reading GUIDs with hyphens, scanf will treat
12079 * hyphen as a hex character (and counts as part of the
12080 * width). This creates leftover GUID string which we
12081 * check will for with 'next' and closing '>'.
12083 if (12 == sscanf(dn, "<GUID=%08x%04x%04x%02x%02x%02x%02x%02x%02x%02x%02x>%c",
12084 &time_low, &time_mid,
12085 &time_hi_and_version, &clock_seq[0],
12086 &clock_seq[1], &node[0], &node[1],
12087 &node[2], &node[3], &node[4],
12088 &node[5], &next)) {
12089 /* This GUID is good */
12091 d_printf("GUID format in control (no hyphens) doesn't match output\n");
12097 if (12 == sscanf(dn,
12098 "<GUID=%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x>%c",
12099 &time_low, &time_mid,
12100 &time_hi_and_version, &clock_seq[0],
12101 &clock_seq[1], &node[0], &node[1],
12102 &node[2], &node[3], &node[4],
12103 &node[5], &next)) {
12104 /* This GUID is good */
12106 d_printf("GUID format in control (with hyphens) doesn't match output\n");
12119 static bool run_tldap(int dummy)
12121 struct tldap_context *ld;
12125 struct sockaddr_storage addr;
12126 struct tevent_context *ev;
12127 struct tevent_req *req;
12129 const char *filter;
12131 if (!resolve_name(host, &addr, 0, false)) {
12132 d_printf("could not find host %s\n", host);
12135 status = open_socket_out(&addr, 389, 9999, &fd);
12136 if (!NT_STATUS_IS_OK(status)) {
12137 d_printf("open_socket_out failed: %s\n", nt_errstr(status));
12141 ld = tldap_context_create(talloc_tos(), fd);
12144 d_printf("tldap_context_create failed\n");
12148 rc = tldap_fetch_rootdse(ld);
12149 if (!TLDAP_RC_IS_SUCCESS(rc)) {
12150 d_printf("tldap_fetch_rootdse failed: %s\n",
12151 tldap_errstr(talloc_tos(), ld, rc));
12155 basedn = tldap_talloc_single_attribute(
12156 tldap_rootdse(ld), "defaultNamingContext", talloc_tos());
12157 if (basedn == NULL) {
12158 d_printf("no defaultNamingContext\n");
12161 d_printf("defaultNamingContext: %s\n", basedn);
12163 ev = samba_tevent_context_init(talloc_tos());
12165 d_printf("tevent_context_init failed\n");
12169 rc = tldap_gensec_bind(ld, torture_creds, "ldap", host, NULL,
12170 loadparm_init_s3(talloc_tos(),
12171 loadparm_s3_helpers()),
12172 GENSEC_FEATURE_SIGN | GENSEC_FEATURE_SEAL);
12174 if (!TLDAP_RC_IS_SUCCESS(rc)) {
12175 d_printf("tldap_gensec_bind failed\n");
12179 callback_code = TLDAP_SUCCESS;
12181 req = tldap_search_paged_send(talloc_tos(), ev, ld, basedn,
12182 TLDAP_SCOPE_SUB, "(objectclass=*)",
12184 NULL, 0, NULL, 0, 0, 0, 0, 5);
12186 d_printf("tldap_search_paged_send failed\n");
12189 tevent_req_set_callback(req, pagedsearch_cb, NULL);
12191 tevent_req_poll(req, ev);
12195 rc = callback_code;
12197 if (!TLDAP_RC_IS_SUCCESS(rc)) {
12198 d_printf("tldap_search with paging failed: %s\n",
12199 tldap_errstr(talloc_tos(), ld, rc));
12203 /* test search filters against rootDSE */
12204 filter = "(&(|(name=samba)(nextRid<=10000000)(usnChanged>=10)(samba~=ambas)(!(name=s*m*a)))"
12205 "(|(name:=samba)(name:dn:2.5.13.5:=samba)(:dn:2.5.13.5:=samba)(!(name=*samba))))";
12207 rc = tldap_search(ld, "", TLDAP_SCOPE_BASE, filter,
12208 NULL, 0, 0, NULL, 0, NULL, 0, 0, 0, 0,
12209 talloc_tos(), NULL);
12210 if (!TLDAP_RC_IS_SUCCESS(rc)) {
12211 d_printf("tldap_search with complex filter failed: %s\n",
12212 tldap_errstr(talloc_tos(), ld, rc));
12217 * Tests to check for regression of:
12219 * https://bugzilla.samba.org/show_bug.cgi?id=14029
12221 * TLDAP used here to pick apart the original string DN (with GUID)
12223 if (!tldap_test_dn_guid_format(ld, basedn, EXTENDED_NONE)) {
12224 d_printf("tldap_search with extended dn (no val) failed: %s\n",
12225 tldap_errstr(talloc_tos(), ld, rc));
12228 if (!tldap_test_dn_guid_format(ld, basedn, EXTENDED_ZERO)) {
12229 d_printf("tldap_search with extended dn (0) failed: %s\n",
12230 tldap_errstr(talloc_tos(), ld, rc));
12233 if (!tldap_test_dn_guid_format(ld, basedn, EXTENDED_ONE)) {
12234 d_printf("tldap_search with extended dn (1) failed: %s\n",
12235 tldap_errstr(talloc_tos(), ld, rc));
12243 /* Torture test to ensure no regression of :
12244 https://bugzilla.samba.org/show_bug.cgi?id=7084
12247 static bool run_dir_createtime(int dummy)
12249 struct cli_state *cli;
12250 const char *dname = "\\testdir_createtime";
12251 const char *fname = "\\testdir_createtime\\testfile";
12253 struct timespec create_time;
12254 struct timespec create_time1;
12259 if (!torture_open_connection(&cli, 0)) {
12263 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
12264 /* Ensure ino is zero, SMB2 gets a real one. */
12267 /* Ensure ino is -1, SMB1 never gets a real one. */
12268 ino = (uint64_t)-1;
12271 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
12272 cli_rmdir(cli, dname);
12274 status = cli_mkdir(cli, dname);
12275 if (!NT_STATUS_IS_OK(status)) {
12276 printf("mkdir failed: %s\n", nt_errstr(status));
12280 status = cli_qpathinfo2(cli, dname, &create_time, NULL, NULL, NULL,
12282 if (!NT_STATUS_IS_OK(status)) {
12283 printf("cli_qpathinfo2 returned %s\n",
12284 nt_errstr(status));
12288 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
12289 /* SMB2 should always return an inode. */
12291 printf("SMB2 bad inode (0)\n");
12295 /* SMB1 must always return zero here. */
12297 printf("SMB1 bad inode (!0)\n");
12302 /* Sleep 3 seconds, then create a file. */
12305 status = cli_openx(cli, fname, O_RDWR | O_CREAT | O_EXCL,
12307 if (!NT_STATUS_IS_OK(status)) {
12308 printf("cli_openx failed: %s\n", nt_errstr(status));
12312 status = cli_qpathinfo2(cli, dname, &create_time1, NULL, NULL, NULL,
12314 if (!NT_STATUS_IS_OK(status)) {
12315 printf("cli_qpathinfo2 (2) returned %s\n",
12316 nt_errstr(status));
12320 if (timespec_compare(&create_time1, &create_time)) {
12321 printf("run_dir_createtime: create time was updated (error)\n");
12323 printf("run_dir_createtime: create time was not updated (correct)\n");
12329 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
12330 cli_rmdir(cli, dname);
12331 if (!torture_close_connection(cli)) {
12338 static bool run_streamerror(int dummy)
12340 struct cli_state *cli;
12341 const char *dname = "\\testdir_streamerror";
12342 const char *streamname =
12343 "testdir_streamerror:{4c8cc155-6c1e-11d1-8e41-00c04fb9386d}:$DATA";
12345 time_t change_time, access_time, write_time;
12351 if (!torture_open_connection(&cli, 0)) {
12355 cli_unlink(cli, "\\testdir_streamerror\\*", FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
12356 cli_rmdir(cli, dname);
12358 status = cli_mkdir(cli, dname);
12359 if (!NT_STATUS_IS_OK(status)) {
12360 printf("mkdir failed: %s\n", nt_errstr(status));
12364 status = cli_qpathinfo1(cli, streamname, &change_time, &access_time,
12365 &write_time, &size, &attr);
12366 if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
12367 printf("pathinfo returned %s, expected "
12368 "NT_STATUS_OBJECT_NAME_NOT_FOUND\n",
12369 nt_errstr(status));
12373 status = cli_ntcreate(cli, streamname, 0x16,
12374 FILE_READ_DATA|FILE_READ_EA|
12375 FILE_READ_ATTRIBUTES|READ_CONTROL_ACCESS,
12376 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ,
12377 FILE_OPEN, 0, 0, &fnum, NULL);
12379 if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
12380 printf("ntcreate returned %s, expected "
12381 "NT_STATUS_OBJECT_NAME_NOT_FOUND\n",
12382 nt_errstr(status));
12387 cli_rmdir(cli, dname);
12391 struct pidtest_state {
12397 static void pid_echo_done(struct tevent_req *subreq);
12399 static struct tevent_req *pid_echo_send(TALLOC_CTX *mem_ctx,
12400 struct tevent_context *ev,
12401 struct cli_state *cli)
12403 struct tevent_req *req, *subreq;
12404 struct pidtest_state *state;
12406 req = tevent_req_create(mem_ctx, &state, struct pidtest_state);
12411 SSVAL(state->vwv, 0, 1);
12412 state->data = data_blob_const("hello", 5);
12414 subreq = smb1cli_req_send(state,
12418 0, 0, /* *_flags */
12419 0, 0, /* *_flags2 */
12421 0xDEADBEEF, /* pid */
12423 NULL, /* session */
12424 ARRAY_SIZE(state->vwv), state->vwv,
12425 state->data.length, state->data.data);
12427 if (tevent_req_nomem(subreq, req)) {
12428 return tevent_req_post(req, ev);
12430 tevent_req_set_callback(subreq, pid_echo_done, req);
12434 static void pid_echo_done(struct tevent_req *subreq)
12436 struct tevent_req *req = tevent_req_callback_data(
12437 subreq, struct tevent_req);
12438 struct pidtest_state *state = tevent_req_data(
12439 req, struct pidtest_state);
12441 uint32_t num_bytes;
12442 uint8_t *bytes = NULL;
12443 struct iovec *recv_iov = NULL;
12444 uint8_t *phdr = NULL;
12445 uint16_t pidlow = 0;
12446 uint16_t pidhigh = 0;
12447 struct smb1cli_req_expected_response expected[] = {
12449 .status = NT_STATUS_OK,
12454 status = smb1cli_req_recv(subreq, state,
12459 NULL, /* pvwv_offset */
12462 NULL, /* pbytes_offset */
12464 expected, ARRAY_SIZE(expected));
12466 TALLOC_FREE(subreq);
12468 if (!NT_STATUS_IS_OK(status)) {
12469 tevent_req_nterror(req, status);
12473 if (num_bytes != state->data.length) {
12474 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
12478 if (memcmp(bytes, state->data.data, num_bytes) != 0) {
12479 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
12483 /* Check pid low/high == DEADBEEF */
12484 pidlow = SVAL(phdr, HDR_PID);
12485 if (pidlow != 0xBEEF){
12486 printf("Incorrect pidlow 0x%x, should be 0xBEEF\n",
12487 (unsigned int)pidlow);
12488 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
12491 pidhigh = SVAL(phdr, HDR_PIDHIGH);
12492 if (pidhigh != 0xDEAD){
12493 printf("Incorrect pidhigh 0x%x, should be 0xDEAD\n",
12494 (unsigned int)pidhigh);
12495 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
12499 tevent_req_done(req);
12502 static NTSTATUS pid_echo_recv(struct tevent_req *req)
12504 return tevent_req_simple_recv_ntstatus(req);
12507 static bool run_pidhigh(int dummy)
12509 bool success = false;
12510 struct cli_state *cli = NULL;
12512 struct tevent_context *ev = NULL;
12513 struct tevent_req *req = NULL;
12514 TALLOC_CTX *frame = talloc_stackframe();
12516 printf("starting pid high test\n");
12517 if (!torture_open_connection(&cli, 0)) {
12520 smbXcli_conn_set_sockopt(cli->conn, sockops);
12522 ev = samba_tevent_context_init(frame);
12527 req = pid_echo_send(frame, ev, cli);
12532 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
12536 status = pid_echo_recv(req);
12537 if (NT_STATUS_IS_OK(status)) {
12538 printf("pid high test ok\n");
12544 TALLOC_FREE(frame);
12545 torture_close_connection(cli);
12550 Test Windows open on a bad POSIX symlink.
12552 static bool run_symlink_open_test(int dummy)
12554 static struct cli_state *cli;
12555 const char *fname = "non_existant_file";
12556 const char *sname = "dangling_symlink";
12557 uint16_t fnum = (uint16_t)-1;
12558 bool correct = false;
12560 TALLOC_CTX *frame = NULL;
12562 frame = talloc_stackframe();
12564 printf("Starting Windows bad symlink open test\n");
12566 if (!torture_open_connection(&cli, 0)) {
12567 TALLOC_FREE(frame);
12571 smbXcli_conn_set_sockopt(cli->conn, sockops);
12573 status = torture_setup_unix_extensions(cli);
12574 if (!NT_STATUS_IS_OK(status)) {
12575 TALLOC_FREE(frame);
12579 /* Ensure nothing exists. */
12580 cli_setatr(cli, fname, 0, 0);
12581 cli_posix_unlink(cli, fname);
12582 cli_setatr(cli, sname, 0, 0);
12583 cli_posix_unlink(cli, sname);
12585 /* Create a symlink pointing nowhere. */
12586 status = cli_posix_symlink(cli, fname, sname);
12587 if (!NT_STATUS_IS_OK(status)) {
12588 printf("cli_posix_symlink of %s -> %s failed (%s)\n",
12591 nt_errstr(status));
12595 /* Now ensure that a Windows open doesn't hang. */
12596 status = cli_ntcreate(cli,
12599 FILE_READ_DATA|FILE_WRITE_DATA,
12601 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
12609 * We get either NT_STATUS_OBJECT_NAME_NOT_FOUND or
12610 * NT_STATUS_OBJECT_PATH_NOT_FOUND depending on if
12611 * we use O_NOFOLLOW on the server or not.
12613 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND) ||
12614 NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_PATH_NOT_FOUND))
12618 printf("cli_ntcreate of %s returned %s - should return"
12619 " either (%s) or (%s)\n",
12622 nt_errstr(NT_STATUS_OBJECT_NAME_NOT_FOUND),
12623 nt_errstr(NT_STATUS_OBJECT_PATH_NOT_FOUND));
12631 if (fnum != (uint16_t)-1) {
12632 cli_close(cli, fnum);
12633 fnum = (uint16_t)-1;
12636 cli_setatr(cli, sname, 0, 0);
12637 cli_posix_unlink(cli, sname);
12638 cli_setatr(cli, fname, 0, 0);
12639 cli_posix_unlink(cli, fname);
12641 if (!torture_close_connection(cli)) {
12645 TALLOC_FREE(frame);
12650 * Only testing minimal time strings, as the others
12651 * need (locale-dependent) guessing at what strftime does and
12652 * even may differ in builds.
12654 static bool timesubst_test(void)
12656 TALLOC_CTX *ctx = NULL;
12657 /* Sa 23. Dez 04:33:20 CET 2017 */
12658 const struct timeval tv = { 1514000000, 123 };
12659 const char* expect_minimal = "20171223_033320";
12660 const char* expect_minus = "20171223_033320_000123";
12662 char *env_tz, *orig_tz = NULL;
12663 bool result = true;
12665 ctx = talloc_new(NULL);
12667 env_tz = getenv("TZ");
12669 orig_tz = talloc_strdup(ctx, env_tz);
12671 setenv("TZ", "UTC", 1);
12673 s = minimal_timeval_string(ctx, &tv, false);
12675 if(!s || strcmp(s, expect_minimal)) {
12676 printf("minimal_timeval_string(ctx, tv, false) returned [%s], expected "
12677 "[%s]\n", s ? s : "<nil>", expect_minimal);
12681 s = minimal_timeval_string(ctx, &tv, true);
12682 if(!s || strcmp(s, expect_minus)) {
12683 printf("minimal_timeval_string(ctx, tv, true) returned [%s], expected "
12684 "[%s]\n", s ? s : "<nil>", expect_minus);
12690 setenv("TZ", orig_tz, 1);
12697 static bool run_local_substitute(int dummy)
12701 ok &= subst_test("%U", "bla", "", -1, -1, "bla");
12702 ok &= subst_test("%u%U", "bla", "", -1, -1, "blabla");
12703 ok &= subst_test("%g", "", "", -1, -1, "NO_GROUP");
12704 ok &= subst_test("%G", "", "", -1, -1, "NO_GROUP");
12705 ok &= subst_test("%g", "", "", -1, 0, gidtoname(0));
12706 ok &= subst_test("%G", "", "", -1, 0, gidtoname(0));
12707 ok &= subst_test("%D%u", "u", "dom", -1, 0, "domu");
12708 ok &= subst_test("%i %I", "", "", -1, -1, "0.0.0.0 0.0.0.0");
12709 ok &= subst_test("%j %J", "", "", -1, -1, "0_0_0_0 0_0_0_0");
12710 /* Substitution depends on current time, so better test the underlying
12711 formatting function. At least covers %t. */
12712 ok &= timesubst_test();
12714 /* Different captialization rules in sub_basic... */
12716 ok &= (strcmp(talloc_sub_basic(talloc_tos(), "BLA", "dom", "%U%D"),
12722 static bool run_local_base64(int dummy)
12727 for (i=1; i<2000; i++) {
12728 DATA_BLOB blob1, blob2;
12731 blob1.data = talloc_array(talloc_tos(), uint8_t, i);
12733 generate_random_buffer(blob1.data, blob1.length);
12735 b64 = base64_encode_data_blob(talloc_tos(), blob1);
12737 d_fprintf(stderr, "base64_encode_data_blob failed "
12738 "for %d bytes\n", i);
12741 blob2 = base64_decode_data_blob(b64);
12744 if (data_blob_cmp(&blob1, &blob2)) {
12745 d_fprintf(stderr, "data_blob_cmp failed for %d "
12749 TALLOC_FREE(blob1.data);
12750 data_blob_free(&blob2);
12755 static void parse_fn(const struct gencache_timeout *t,
12757 void *private_data)
12762 static bool run_local_gencache(int dummy)
12768 struct memcache *mem;
12771 mem = memcache_init(NULL, 0);
12773 d_printf("%s: memcache_init failed\n", __location__);
12776 memcache_set_global(mem);
12778 if (!gencache_set("foo", "bar", time(NULL) + 1000)) {
12779 d_printf("%s: gencache_set() failed\n", __location__);
12783 if (!gencache_get("foo", NULL, NULL, NULL)) {
12784 d_printf("%s: gencache_get() failed\n", __location__);
12788 for (i=0; i<1000000; i++) {
12789 gencache_parse("foo", parse_fn, NULL);
12792 if (!gencache_get("foo", talloc_tos(), &val, &tm)) {
12793 d_printf("%s: gencache_get() failed\n", __location__);
12798 if (!gencache_get("foo", talloc_tos(), &val, &tm)) {
12799 d_printf("%s: gencache_get() failed\n", __location__);
12803 if (strcmp(val, "bar") != 0) {
12804 d_printf("%s: gencache_get() returned %s, expected %s\n",
12805 __location__, val, "bar");
12812 if (!gencache_del("foo")) {
12813 d_printf("%s: gencache_del() failed\n", __location__);
12816 if (gencache_del("foo")) {
12817 d_printf("%s: second gencache_del() succeeded\n",
12822 if (gencache_get("foo", talloc_tos(), &val, &tm)) {
12823 d_printf("%s: gencache_get() on deleted entry "
12824 "succeeded\n", __location__);
12828 blob = data_blob_string_const_null("bar");
12829 tm = time(NULL) + 60;
12831 if (!gencache_set_data_blob("foo", blob, tm)) {
12832 d_printf("%s: gencache_set_data_blob() failed\n", __location__);
12836 if (!gencache_get_data_blob("foo", talloc_tos(), &blob, NULL, NULL)) {
12837 d_printf("%s: gencache_get_data_blob() failed\n", __location__);
12841 if (strcmp((const char *)blob.data, "bar") != 0) {
12842 d_printf("%s: gencache_get_data_blob() returned %s, expected %s\n",
12843 __location__, (const char *)blob.data, "bar");
12844 data_blob_free(&blob);
12848 data_blob_free(&blob);
12850 if (!gencache_del("foo")) {
12851 d_printf("%s: gencache_del() failed\n", __location__);
12854 if (gencache_del("foo")) {
12855 d_printf("%s: second gencache_del() succeeded\n",
12860 if (gencache_get_data_blob("foo", talloc_tos(), &blob, NULL, NULL)) {
12861 d_printf("%s: gencache_get_data_blob() on deleted entry "
12862 "succeeded\n", __location__);
12867 blob.data = (uint8_t *)&v;
12868 blob.length = sizeof(v);
12870 if (!gencache_set_data_blob("blob", blob, tm)) {
12871 d_printf("%s: gencache_set_data_blob() failed\n",
12875 if (gencache_get("blob", talloc_tos(), &val, &tm)) {
12876 d_printf("%s: gencache_get succeeded\n", __location__);
12883 static bool rbt_testval(struct db_context *db, const char *key,
12886 struct db_record *rec;
12887 TDB_DATA data = string_tdb_data(value);
12892 rec = dbwrap_fetch_locked(db, db, string_tdb_data(key));
12894 d_fprintf(stderr, "fetch_locked failed\n");
12897 status = dbwrap_record_store(rec, data, 0);
12898 if (!NT_STATUS_IS_OK(status)) {
12899 d_fprintf(stderr, "store failed: %s\n", nt_errstr(status));
12904 rec = dbwrap_fetch_locked(db, db, string_tdb_data(key));
12906 d_fprintf(stderr, "second fetch_locked failed\n");
12910 dbvalue = dbwrap_record_get_value(rec);
12911 if ((dbvalue.dsize != data.dsize)
12912 || (memcmp(dbvalue.dptr, data.dptr, data.dsize) != 0)) {
12913 d_fprintf(stderr, "Got wrong data back\n");
12923 static int local_rbtree_traverse_read(struct db_record *rec, void *private_data)
12925 int *count2 = (int *)private_data;
12930 static int local_rbtree_traverse_delete(struct db_record *rec, void *private_data)
12932 int *count2 = (int *)private_data;
12934 dbwrap_record_delete(rec);
12938 static bool run_local_rbtree(int dummy)
12940 struct db_context *db;
12947 db = db_open_rbt(NULL);
12950 d_fprintf(stderr, "db_open_rbt failed\n");
12954 for (i=0; i<1000; i++) {
12957 if (asprintf(&key, "key%ld", random()) == -1) {
12960 if (asprintf(&value, "value%ld", random()) == -1) {
12965 if (!rbt_testval(db, key, value)) {
12972 if (asprintf(&value, "value%ld", random()) == -1) {
12977 if (!rbt_testval(db, key, value)) {
12988 count = 0; count2 = 0;
12989 status = dbwrap_traverse_read(db, local_rbtree_traverse_read,
12991 printf("%s: read1: %d %d, %s\n", __func__, count, count2, nt_errstr(status));
12992 if ((count != count2) || (count != 1000)) {
12995 count = 0; count2 = 0;
12996 status = dbwrap_traverse(db, local_rbtree_traverse_delete,
12998 printf("%s: delete: %d %d, %s\n", __func__, count, count2, nt_errstr(status));
12999 if ((count != count2) || (count != 1000)) {
13002 count = 0; count2 = 0;
13003 status = dbwrap_traverse_read(db, local_rbtree_traverse_read,
13005 printf("%s: read2: %d %d, %s\n", __func__, count, count2, nt_errstr(status));
13006 if ((count != count2) || (count != 0)) {
13017 local test for character set functions
13019 This is a very simple test for the functionality in convert_string_error()
13021 static bool run_local_convert_string(int dummy)
13023 TALLOC_CTX *tmp_ctx = talloc_new(NULL);
13024 const char *test_strings[2] = { "March", "M\303\244rz" };
13028 for (i=0; i<2; i++) {
13029 const char *str = test_strings[i];
13030 int len = strlen(str);
13031 size_t converted_size;
13034 memset(dst, 'X', sizeof(dst));
13036 /* first try with real source length */
13037 ret = convert_string_error(CH_UNIX, CH_UTF8,
13042 d_fprintf(stderr, "Failed to convert '%s' to CH_DISPLAY\n", str);
13046 if (converted_size != len) {
13047 d_fprintf(stderr, "Converted size of '%s' should be %d - got %d\n",
13048 str, len, (int)converted_size);
13052 if (strncmp(str, dst, converted_size) != 0) {
13053 d_fprintf(stderr, "Expected '%s' to match '%s'\n", str, dst);
13057 if (strlen(str) != converted_size) {
13058 d_fprintf(stderr, "Expected '%s' length %d - got %d\n", str,
13059 (int)strlen(str), (int)converted_size);
13063 if (dst[converted_size] != 'X') {
13064 d_fprintf(stderr, "Expected no termination of '%s'\n", dst);
13068 /* now with srclen==-1, this causes the nul to be
13070 ret = convert_string_error(CH_UNIX, CH_UTF8,
13075 d_fprintf(stderr, "Failed to convert '%s' to CH_DISPLAY\n", str);
13079 if (converted_size != len+1) {
13080 d_fprintf(stderr, "Converted size of '%s' should be %d - got %d\n",
13081 str, len, (int)converted_size);
13085 if (strncmp(str, dst, converted_size) != 0) {
13086 d_fprintf(stderr, "Expected '%s' to match '%s'\n", str, dst);
13090 if (len+1 != converted_size) {
13091 d_fprintf(stderr, "Expected '%s' length %d - got %d\n", str,
13092 len+1, (int)converted_size);
13096 if (dst[converted_size] != 'X') {
13097 d_fprintf(stderr, "Expected no termination of '%s'\n", dst);
13104 TALLOC_FREE(tmp_ctx);
13107 TALLOC_FREE(tmp_ctx);
13111 static bool run_local_string_to_sid(int dummy) {
13112 struct dom_sid sid;
13114 if (string_to_sid(&sid, "S--1-5-32-545")) {
13115 printf("allowing S--1-5-32-545\n");
13118 if (string_to_sid(&sid, "S-1-5-32-+545")) {
13119 printf("allowing S-1-5-32-+545\n");
13122 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")) {
13123 printf("allowing S-1-2-3-4-5-6-7-8-9-0-1-2-3-4-5-6-7-8-9-0\n");
13126 if (string_to_sid(&sid, "S-1-5-32-545-abc")) {
13127 printf("allowing S-1-5-32-545-abc\n");
13130 if (string_to_sid(&sid, "S-300-5-32-545")) {
13131 printf("allowing S-300-5-32-545\n");
13134 if (string_to_sid(&sid, "S-1-0xfffffffffffffe-32-545")) {
13135 printf("allowing S-1-0xfffffffffffffe-32-545\n");
13138 if (string_to_sid(&sid, "S-1-0xffffffffffff-5294967297-545")) {
13139 printf("allowing S-1-0xffffffffffff-5294967297-545\n");
13142 if (!string_to_sid(&sid, "S-1-0xfffffffffffe-32-545")) {
13143 printf("could not parse S-1-0xfffffffffffe-32-545\n");
13146 if (!string_to_sid(&sid, "S-1-5-32-545")) {
13147 printf("could not parse S-1-5-32-545\n");
13150 if (!dom_sid_equal(&sid, &global_sid_Builtin_Users)) {
13151 struct dom_sid_buf buf;
13152 printf("mis-parsed S-1-5-32-545 as %s\n",
13153 dom_sid_str_buf(&sid, &buf));
13159 static bool sid_to_string_test(const char *expected) {
13162 struct dom_sid sid;
13164 if (!string_to_sid(&sid, expected)) {
13165 printf("could not parse %s\n", expected);
13169 str = dom_sid_string(NULL, &sid);
13170 if (strcmp(str, expected)) {
13171 printf("Comparison failed (%s != %s)\n", str, expected);
13178 static bool run_local_sid_to_string(int dummy) {
13179 if (!sid_to_string_test("S-1-0xffffffffffff-1-1-1-1-1-1-1-1-1-1-1-1"))
13181 if (!sid_to_string_test("S-1-545"))
13183 if (!sid_to_string_test("S-255-3840-1-1-1-1"))
13188 static bool run_local_binary_to_sid(int dummy) {
13190 struct dom_sid *sid = talloc(NULL, struct dom_sid);
13191 static const uint8_t good_binary_sid[] = {
13192 0x1, /* revision number */
13193 15, /* num auths */
13194 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, /* id_auth */
13195 0x1, 0x1, 0x1, 0x1, /* auth[0] */
13196 0x1, 0x1, 0x1, 0x1, /* auth[1] */
13197 0x1, 0x1, 0x1, 0x1, /* auth[2] */
13198 0x1, 0x1, 0x1, 0x1, /* auth[3] */
13199 0x1, 0x1, 0x1, 0x1, /* auth[4] */
13200 0x1, 0x1, 0x1, 0x1, /* auth[5] */
13201 0x1, 0x1, 0x1, 0x1, /* auth[6] */
13202 0x1, 0x1, 0x1, 0x1, /* auth[7] */
13203 0x1, 0x1, 0x1, 0x1, /* auth[8] */
13204 0x1, 0x1, 0x1, 0x1, /* auth[9] */
13205 0x1, 0x1, 0x1, 0x1, /* auth[10] */
13206 0x1, 0x1, 0x1, 0x1, /* auth[11] */
13207 0x1, 0x1, 0x1, 0x1, /* auth[12] */
13208 0x1, 0x1, 0x1, 0x1, /* auth[13] */
13209 0x1, 0x1, 0x1, 0x1, /* auth[14] */
13212 static const uint8_t long_binary_sid[] = {
13213 0x1, /* revision number */
13214 15, /* num auths */
13215 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, /* id_auth */
13216 0x1, 0x1, 0x1, 0x1, /* auth[0] */
13217 0x1, 0x1, 0x1, 0x1, /* auth[1] */
13218 0x1, 0x1, 0x1, 0x1, /* auth[2] */
13219 0x1, 0x1, 0x1, 0x1, /* auth[3] */
13220 0x1, 0x1, 0x1, 0x1, /* auth[4] */
13221 0x1, 0x1, 0x1, 0x1, /* auth[5] */
13222 0x1, 0x1, 0x1, 0x1, /* auth[6] */
13223 0x1, 0x1, 0x1, 0x1, /* auth[7] */
13224 0x1, 0x1, 0x1, 0x1, /* auth[8] */
13225 0x1, 0x1, 0x1, 0x1, /* auth[9] */
13226 0x1, 0x1, 0x1, 0x1, /* auth[10] */
13227 0x1, 0x1, 0x1, 0x1, /* auth[11] */
13228 0x1, 0x1, 0x1, 0x1, /* auth[12] */
13229 0x1, 0x1, 0x1, 0x1, /* auth[13] */
13230 0x1, 0x1, 0x1, 0x1, /* auth[14] */
13231 0x1, 0x1, 0x1, 0x1, /* auth[15] */
13232 0x1, 0x1, 0x1, 0x1, /* auth[16] */
13233 0x1, 0x1, 0x1, 0x1, /* auth[17] */
13236 static const uint8_t long_binary_sid2[] = {
13237 0x1, /* revision number */
13238 32, /* num auths */
13239 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, /* id_auth */
13240 0x1, 0x1, 0x1, 0x1, /* auth[0] */
13241 0x1, 0x1, 0x1, 0x1, /* auth[1] */
13242 0x1, 0x1, 0x1, 0x1, /* auth[2] */
13243 0x1, 0x1, 0x1, 0x1, /* auth[3] */
13244 0x1, 0x1, 0x1, 0x1, /* auth[4] */
13245 0x1, 0x1, 0x1, 0x1, /* auth[5] */
13246 0x1, 0x1, 0x1, 0x1, /* auth[6] */
13247 0x1, 0x1, 0x1, 0x1, /* auth[7] */
13248 0x1, 0x1, 0x1, 0x1, /* auth[8] */
13249 0x1, 0x1, 0x1, 0x1, /* auth[9] */
13250 0x1, 0x1, 0x1, 0x1, /* auth[10] */
13251 0x1, 0x1, 0x1, 0x1, /* auth[11] */
13252 0x1, 0x1, 0x1, 0x1, /* auth[12] */
13253 0x1, 0x1, 0x1, 0x1, /* auth[13] */
13254 0x1, 0x1, 0x1, 0x1, /* auth[14] */
13255 0x1, 0x1, 0x1, 0x1, /* auth[15] */
13256 0x1, 0x1, 0x1, 0x1, /* auth[16] */
13257 0x1, 0x1, 0x1, 0x1, /* auth[17] */
13258 0x1, 0x1, 0x1, 0x1, /* auth[18] */
13259 0x1, 0x1, 0x1, 0x1, /* auth[19] */
13260 0x1, 0x1, 0x1, 0x1, /* auth[20] */
13261 0x1, 0x1, 0x1, 0x1, /* auth[21] */
13262 0x1, 0x1, 0x1, 0x1, /* auth[22] */
13263 0x1, 0x1, 0x1, 0x1, /* auth[23] */
13264 0x1, 0x1, 0x1, 0x1, /* auth[24] */
13265 0x1, 0x1, 0x1, 0x1, /* auth[25] */
13266 0x1, 0x1, 0x1, 0x1, /* auth[26] */
13267 0x1, 0x1, 0x1, 0x1, /* auth[27] */
13268 0x1, 0x1, 0x1, 0x1, /* auth[28] */
13269 0x1, 0x1, 0x1, 0x1, /* auth[29] */
13270 0x1, 0x1, 0x1, 0x1, /* auth[30] */
13271 0x1, 0x1, 0x1, 0x1, /* auth[31] */
13274 ret = sid_parse(good_binary_sid, sizeof(good_binary_sid), sid);
13278 ret = sid_parse(long_binary_sid2, sizeof(long_binary_sid2), sid);
13282 ret = sid_parse(long_binary_sid, sizeof(long_binary_sid), sid);
13289 /* Split a path name into filename and stream name components. Canonicalise
13290 * such that an implicit $DATA token is always explicit.
13292 * The "specification" of this function can be found in the
13293 * run_local_stream_name() function in torture.c, I've tried those
13294 * combinations against a W2k3 server.
13297 static NTSTATUS split_ntfs_stream_name(TALLOC_CTX *mem_ctx, const char *fname,
13298 char **pbase, char **pstream)
13301 char *stream = NULL;
13302 char *sname; /* stream name */
13303 const char *stype; /* stream type */
13305 DEBUG(10, ("split_ntfs_stream_name called for [%s]\n", fname));
13307 sname = strchr_m(fname, ':');
13309 if (sname == NULL) {
13310 if (pbase != NULL) {
13311 base = talloc_strdup(mem_ctx, fname);
13312 NT_STATUS_HAVE_NO_MEMORY(base);
13317 if (pbase != NULL) {
13318 base = talloc_strndup(mem_ctx, fname, PTR_DIFF(sname, fname));
13319 NT_STATUS_HAVE_NO_MEMORY(base);
13324 stype = strchr_m(sname, ':');
13326 if (stype == NULL) {
13327 sname = talloc_strdup(mem_ctx, sname);
13331 if (strcasecmp_m(stype, ":$DATA") != 0) {
13333 * If there is an explicit stream type, so far we only
13334 * allow $DATA. Is there anything else allowed? -- vl
13336 DEBUG(10, ("[%s] is an invalid stream type\n", stype));
13338 return NT_STATUS_OBJECT_NAME_INVALID;
13340 sname = talloc_strndup(mem_ctx, sname, PTR_DIFF(stype, sname));
13344 if (sname == NULL) {
13346 return NT_STATUS_NO_MEMORY;
13349 if (sname[0] == '\0') {
13351 * no stream name, so no stream
13356 if (pstream != NULL) {
13357 stream = talloc_asprintf(mem_ctx, "%s:%s", sname, stype);
13358 if (stream == NULL) {
13359 TALLOC_FREE(sname);
13361 return NT_STATUS_NO_MEMORY;
13364 * upper-case the type field
13366 (void)strupper_m(strchr_m(stream, ':')+1);
13370 if (pbase != NULL) {
13373 if (pstream != NULL) {
13376 return NT_STATUS_OK;
13379 static bool test_stream_name(const char *fname, const char *expected_base,
13380 const char *expected_stream,
13381 NTSTATUS expected_status)
13385 char *stream = NULL;
13387 status = split_ntfs_stream_name(talloc_tos(), fname, &base, &stream);
13388 if (!NT_STATUS_EQUAL(status, expected_status)) {
13392 if (!NT_STATUS_IS_OK(status)) {
13396 if (base == NULL) goto error;
13398 if (strcmp(expected_base, base) != 0) goto error;
13400 if ((expected_stream != NULL) && (stream == NULL)) goto error;
13401 if ((expected_stream == NULL) && (stream != NULL)) goto error;
13403 if ((stream != NULL) && (strcmp(expected_stream, stream) != 0))
13407 TALLOC_FREE(stream);
13411 d_fprintf(stderr, "Do test_stream(%s, %s, %s, %s)\n",
13412 fname, expected_base ? expected_base : "<NULL>",
13413 expected_stream ? expected_stream : "<NULL>",
13414 nt_errstr(expected_status));
13415 d_fprintf(stderr, "-> base=%s, stream=%s, status=%s\n",
13416 base ? base : "<NULL>", stream ? stream : "<NULL>",
13417 nt_errstr(status));
13419 TALLOC_FREE(stream);
13423 static bool run_local_stream_name(int dummy)
13427 ret &= test_stream_name(
13428 "bla", "bla", NULL, NT_STATUS_OK);
13429 ret &= test_stream_name(
13430 "bla::$DATA", "bla", NULL, NT_STATUS_OK);
13431 ret &= test_stream_name(
13432 "bla:blub:", "bla", NULL, NT_STATUS_OBJECT_NAME_INVALID);
13433 ret &= test_stream_name(
13434 "bla::", NULL, NULL, NT_STATUS_OBJECT_NAME_INVALID);
13435 ret &= test_stream_name(
13436 "bla::123", "bla", NULL, NT_STATUS_OBJECT_NAME_INVALID);
13437 ret &= test_stream_name(
13438 "bla:$DATA", "bla", "$DATA:$DATA", NT_STATUS_OK);
13439 ret &= test_stream_name(
13440 "bla:x:$DATA", "bla", "x:$DATA", NT_STATUS_OK);
13441 ret &= test_stream_name(
13442 "bla:x", "bla", "x:$DATA", NT_STATUS_OK);
13447 static bool data_blob_equal(DATA_BLOB a, DATA_BLOB b)
13449 if (a.length != b.length) {
13450 printf("a.length=%d != b.length=%d\n",
13451 (int)a.length, (int)b.length);
13454 if (memcmp(a.data, b.data, a.length) != 0) {
13455 printf("a.data and b.data differ\n");
13461 static bool run_local_memcache(int dummy)
13463 struct memcache *cache;
13464 DATA_BLOB k1, k2, k3, k4, k5;
13468 TALLOC_CTX *mem_ctx;
13474 size_t size1, size2;
13477 mem_ctx = talloc_init("foo");
13478 if (mem_ctx == NULL) {
13482 /* STAT_CACHE TESTS */
13484 cache = memcache_init(NULL, sizeof(void *) == 8 ? 200 : 100);
13486 if (cache == NULL) {
13487 printf("memcache_init failed\n");
13491 d1 = data_blob_const("d1", 2);
13492 d3 = data_blob_const("d3", 2);
13494 k1 = data_blob_const("d1", 2);
13495 k2 = data_blob_const("d2", 2);
13496 k3 = data_blob_const("d3", 2);
13497 k4 = data_blob_const("d4", 2);
13498 k5 = data_blob_const("d5", 2);
13500 memcache_add(cache, STAT_CACHE, k1, d1);
13502 if (!memcache_lookup(cache, STAT_CACHE, k1, &v1)) {
13503 printf("could not find k1\n");
13506 if (!data_blob_equal(d1, v1)) {
13510 memcache_add(cache, STAT_CACHE, k1, d3);
13512 if (!memcache_lookup(cache, STAT_CACHE, k1, &v3)) {
13513 printf("could not find replaced k1\n");
13516 if (!data_blob_equal(d3, v3)) {
13520 TALLOC_FREE(cache);
13522 /* GETWD_CACHE TESTS */
13523 str1 = talloc_strdup(mem_ctx, "string1");
13524 if (str1 == NULL) {
13527 ptr2 = str1; /* Keep an alias for comparison. */
13529 str2 = talloc_strdup(mem_ctx, "string2");
13530 if (str2 == NULL) {
13534 cache = memcache_init(NULL, sizeof(void *) == 8 ? 200 : 100);
13535 if (cache == NULL) {
13536 printf("memcache_init failed\n");
13540 memcache_add_talloc(cache, GETWD_CACHE, k2, &str1);
13541 /* str1 == NULL now. */
13542 ptr1 = memcache_lookup_talloc(cache, GETWD_CACHE, k2);
13543 if (ptr1 == NULL) {
13544 printf("could not find k2\n");
13547 if (ptr1 != ptr2) {
13548 printf("fetch of k2 got wrong string\n");
13552 /* Add a blob to ensure k2 gets purged. */
13553 d3 = data_blob_talloc_zero(mem_ctx, 180);
13554 memcache_add(cache, STAT_CACHE, k3, d3);
13556 ptr2 = memcache_lookup_talloc(cache, GETWD_CACHE, k2);
13557 if (ptr2 != NULL) {
13558 printf("Did find k2, should have been purged\n");
13563 * Test that talloc size also is accounted in memcache and
13564 * causes purge of other object.
13567 str1 = talloc_zero_size(mem_ctx, 100);
13568 str2 = talloc_zero_size(mem_ctx, 100);
13570 memcache_add_talloc(cache, GETWD_CACHE, k4, &str1);
13571 memcache_add_talloc(cache, GETWD_CACHE, k5, &str1);
13573 ptr3 = memcache_lookup_talloc(cache, GETWD_CACHE, k4);
13574 if (ptr3 != NULL) {
13575 printf("Did find k4, should have been purged\n");
13580 * Test that adding a duplicate non-talloced
13581 * key/value on top of a talloced key/value takes account
13582 * of the talloc_freed value size.
13584 TALLOC_FREE(cache);
13585 TALLOC_FREE(mem_ctx);
13587 mem_ctx = talloc_init("key_replace");
13588 if (mem_ctx == NULL) {
13592 cache = memcache_init(NULL, sizeof(void *) == 8 ? 200 : 100);
13593 if (cache == NULL) {
13598 * Add a 100 byte talloced string. This will
13599 * store a (4 or 8 byte) pointer and record the
13600 * total talloced size.
13602 str1 = talloc_zero_size(mem_ctx, 100);
13603 memcache_add_talloc(cache, GETWD_CACHE, k4, &str1);
13605 * Now overwrite with a small talloced
13606 * value. This should fit in the existing size
13607 * and the total talloced size should be removed
13608 * from the cache size.
13610 str1 = talloc_zero_size(mem_ctx, 2);
13611 memcache_add_talloc(cache, GETWD_CACHE, k4, &str1);
13613 * Now store a 20 byte string. If the
13614 * total talloced size wasn't accounted for
13615 * and removed in the overwrite, then this
13618 str2 = talloc_zero_size(mem_ctx, 20);
13619 memcache_add_talloc(cache, GETWD_CACHE, k5, &str2);
13621 ptr3 = memcache_lookup_talloc(cache, GETWD_CACHE, k4);
13622 if (ptr3 == NULL) {
13623 printf("Did not find k4, should not have been purged\n");
13627 TALLOC_FREE(cache);
13628 TALLOC_FREE(mem_ctx);
13630 mem_ctx = talloc_init("foo");
13631 if (mem_ctx == NULL) {
13635 cache = memcache_init(NULL, 0);
13636 if (cache == NULL) {
13640 str1 = talloc_strdup(mem_ctx, "string1");
13641 if (str1 == NULL) {
13644 str2 = talloc_strdup(mem_ctx, "string2");
13645 if (str2 == NULL) {
13648 memcache_add_talloc(cache, SINGLETON_CACHE_TALLOC,
13649 data_blob_string_const("torture"), &str1);
13650 size1 = talloc_total_size(cache);
13652 memcache_add_talloc(cache, SINGLETON_CACHE_TALLOC,
13653 data_blob_string_const("torture"), &str2);
13654 size2 = talloc_total_size(cache);
13656 printf("size1=%d, size2=%d\n", (int)size1, (int)size2);
13658 if (size2 > size1) {
13659 printf("memcache leaks memory!\n");
13665 TALLOC_FREE(cache);
13669 static void wbclient_done(struct tevent_req *req)
13672 struct winbindd_response *wb_resp;
13673 int *i = (int *)tevent_req_callback_data_void(req);
13675 wbc_err = wb_trans_recv(req, req, &wb_resp);
13678 d_printf("wb_trans_recv %d returned %s\n", *i, wbcErrorString(wbc_err));
13681 static bool run_wbclient_multi_ping(int dummy)
13683 struct tevent_context *ev;
13684 struct wb_context **wb_ctx;
13685 struct winbindd_request wb_req;
13686 bool result = false;
13689 BlockSignals(True, SIGPIPE);
13691 ev = tevent_context_init(talloc_tos());
13696 wb_ctx = talloc_array(ev, struct wb_context *, torture_nprocs);
13697 if (wb_ctx == NULL) {
13701 ZERO_STRUCT(wb_req);
13702 wb_req.cmd = WINBINDD_PING;
13704 d_printf("torture_nprocs=%d, numops=%d\n", (int)torture_nprocs, (int)torture_numops);
13706 for (i=0; i<torture_nprocs; i++) {
13707 wb_ctx[i] = wb_context_init(ev, NULL);
13708 if (wb_ctx[i] == NULL) {
13711 for (j=0; j<torture_numops; j++) {
13712 struct tevent_req *req;
13713 req = wb_trans_send(ev, ev, wb_ctx[i],
13714 (j % 2) == 0, &wb_req);
13718 tevent_req_set_callback(req, wbclient_done, &i);
13724 while (i < torture_nprocs * torture_numops) {
13725 tevent_loop_once(ev);
13734 static bool dbtrans_inc(struct db_context *db)
13736 struct db_record *rec;
13742 rec = dbwrap_fetch_locked(db, db, string_term_tdb_data("transtest"));
13744 printf(__location__ "fetch_lock failed\n");
13748 value = dbwrap_record_get_value(rec);
13750 if (value.dsize != sizeof(uint32_t)) {
13751 printf(__location__ "value.dsize = %d\n",
13756 memcpy(&val, value.dptr, sizeof(val));
13759 status = dbwrap_record_store(
13760 rec, make_tdb_data((uint8_t *)&val, sizeof(val)), 0);
13761 if (!NT_STATUS_IS_OK(status)) {
13762 printf(__location__ "store failed: %s\n",
13763 nt_errstr(status));
13773 static bool run_local_dbtrans(int dummy)
13775 struct db_context *db;
13776 struct db_record *rec;
13782 db = db_open(talloc_tos(), "transtest.tdb", 0, TDB_DEFAULT,
13783 O_RDWR|O_CREAT, 0600, DBWRAP_LOCK_ORDER_1,
13786 printf("Could not open transtest.db\n");
13790 res = dbwrap_transaction_start(db);
13792 printf(__location__ "transaction_start failed\n");
13796 rec = dbwrap_fetch_locked(db, db, string_term_tdb_data("transtest"));
13798 printf(__location__ "fetch_lock failed\n");
13802 value = dbwrap_record_get_value(rec);
13804 if (value.dptr == NULL) {
13806 status = dbwrap_record_store(
13807 rec, make_tdb_data((uint8_t *)&initial,
13810 if (!NT_STATUS_IS_OK(status)) {
13811 printf(__location__ "store returned %s\n",
13812 nt_errstr(status));
13819 res = dbwrap_transaction_commit(db);
13821 printf(__location__ "transaction_commit failed\n");
13826 uint32_t val, val2;
13829 res = dbwrap_transaction_start(db);
13831 printf(__location__ "transaction_start failed\n");
13835 status = dbwrap_fetch_uint32_bystring(db, "transtest", &val);
13836 if (!NT_STATUS_IS_OK(status)) {
13837 printf(__location__ "dbwrap_fetch_uint32 failed: %s\n",
13838 nt_errstr(status));
13842 for (i=0; i<10; i++) {
13843 if (!dbtrans_inc(db)) {
13848 status = dbwrap_fetch_uint32_bystring(db, "transtest", &val2);
13849 if (!NT_STATUS_IS_OK(status)) {
13850 printf(__location__ "dbwrap_fetch_uint32 failed: %s\n",
13851 nt_errstr(status));
13855 if (val2 != val + 10) {
13856 printf(__location__ "val=%d, val2=%d\n",
13857 (int)val, (int)val2);
13861 printf("val2=%d\r", val2);
13863 res = dbwrap_transaction_commit(db);
13865 printf(__location__ "transaction_commit failed\n");
13875 * Just a dummy test to be run under a debugger. There's no real way
13876 * to inspect the tevent_poll specific function from outside of
13880 static bool run_local_tevent_poll(int dummy)
13882 struct tevent_context *ev;
13883 struct tevent_fd *fd1, *fd2;
13884 bool result = false;
13886 ev = tevent_context_init_byname(NULL, "poll");
13888 d_fprintf(stderr, "tevent_context_init_byname failed\n");
13892 fd1 = tevent_add_fd(ev, ev, 2, 0, NULL, NULL);
13894 d_fprintf(stderr, "tevent_add_fd failed\n");
13897 fd2 = tevent_add_fd(ev, ev, 3, 0, NULL, NULL);
13899 d_fprintf(stderr, "tevent_add_fd failed\n");
13904 fd2 = tevent_add_fd(ev, ev, 1, 0, NULL, NULL);
13906 d_fprintf(stderr, "tevent_add_fd failed\n");
13916 static bool run_local_hex_encode_buf(int dummy)
13922 for (i=0; i<sizeof(src); i++) {
13925 hex_encode_buf(buf, src, sizeof(src));
13926 if (strcmp(buf, "0001020304050607") != 0) {
13929 hex_encode_buf(buf, NULL, 0);
13930 if (buf[0] != '\0') {
13936 static const char *remove_duplicate_addrs2_test_strings_vector[] = {
13958 "1001:1111:1111:1000:0:1111:1111:1111",
13967 static const char *remove_duplicate_addrs2_test_strings_result[] = {
13981 "1001:1111:1111:1000:0:1111:1111:1111"
13984 static bool run_local_remove_duplicate_addrs2(int dummy)
13986 struct ip_service test_vector[28];
13989 /* Construct the sockaddr_storage test vector. */
13990 for (i = 0; i < 28; i++) {
13991 struct addrinfo hints;
13992 struct addrinfo *res = NULL;
13995 memset(&hints, '\0', sizeof(hints));
13996 hints.ai_flags = AI_NUMERICHOST;
13997 ret = getaddrinfo(remove_duplicate_addrs2_test_strings_vector[i],
14002 fprintf(stderr, "getaddrinfo failed on [%s]\n",
14003 remove_duplicate_addrs2_test_strings_vector[i]);
14006 memset(&test_vector[i], '\0', sizeof(test_vector[i]));
14007 memcpy(&test_vector[i].ss,
14013 count = remove_duplicate_addrs2(test_vector, i);
14016 fprintf(stderr, "count wrong (%d) should be 14\n",
14021 for (i = 0; i < count; i++) {
14022 char addr[INET6_ADDRSTRLEN];
14024 print_sockaddr(addr, sizeof(addr), &test_vector[i].ss);
14026 if (strcmp(addr, remove_duplicate_addrs2_test_strings_result[i]) != 0) {
14027 fprintf(stderr, "mismatch on [%d] [%s] [%s]\n",
14030 remove_duplicate_addrs2_test_strings_result[i]);
14035 printf("run_local_remove_duplicate_addrs2: success\n");
14039 static bool run_local_tdb_opener(int dummy)
14045 t = tdb_open("test.tdb", 1000, TDB_CLEAR_IF_FIRST,
14046 O_RDWR|O_CREAT, 0755);
14048 perror("tdb_open failed");
14059 static bool run_local_tdb_writer(int dummy)
14065 t = tdb_open("test.tdb", 1000, 0, O_RDWR|O_CREAT, 0755);
14067 perror("tdb_open failed");
14071 val.dptr = (uint8_t *)&v;
14072 val.dsize = sizeof(v);
14078 ret = tdb_store(t, val, val, 0);
14080 printf("%s\n", tdb_errorstr(t));
14085 data = tdb_fetch(t, val);
14086 if (data.dptr != NULL) {
14087 SAFE_FREE(data.dptr);
14093 static bool run_local_canonicalize_path(int dummy)
14095 const char *src[] = {
14102 ".././././../../../boo",
14114 "/foo/bar/../baz/",
14115 "////////////////",
14116 "/////////./././././.",
14117 "/./.././../.boo/../baz",
14118 "/a/component/path",
14119 "/a/component/path/",
14120 "/a/component/path/..",
14121 "/a/component/../path/",
14122 "///a/./././///component/../////path/",
14125 const char *dst[] = {
14148 "/a/component/path",
14149 "/a/component/path",
14157 for (i = 0; src[i] != NULL; i++) {
14158 char *d = canonicalize_absolute_path(talloc_tos(), src[i]);
14160 perror("talloc fail\n");
14163 if (strcmp(d, dst[i]) != 0) {
14165 "canonicalize mismatch %s -> %s != %s",
14166 src[i], d, dst[i]);
14174 static bool run_ign_bad_negprot(int dummy)
14176 struct tevent_context *ev;
14177 struct tevent_req *req;
14178 struct smbXcli_conn *conn;
14179 struct sockaddr_storage ss;
14184 printf("starting ignore bad negprot\n");
14186 ok = resolve_name(host, &ss, 0x20, true);
14188 d_fprintf(stderr, "Could not resolve name %s\n", host);
14192 status = open_socket_out(&ss, 445, 10000, &fd);
14193 if (!NT_STATUS_IS_OK(status)) {
14194 d_fprintf(stderr, "open_socket_out failed: %s\n",
14195 nt_errstr(status));
14199 conn = smbXcli_conn_create(talloc_tos(), fd, host, SMB_SIGNING_OFF, 0,
14201 if (conn == NULL) {
14202 d_fprintf(stderr, "smbXcli_conn_create failed\n");
14206 status = smbXcli_negprot(conn, 0, PROTOCOL_CORE, PROTOCOL_CORE);
14207 if (NT_STATUS_IS_OK(status)) {
14208 d_fprintf(stderr, "smbXcli_negprot succeeded!\n");
14212 ev = samba_tevent_context_init(talloc_tos());
14214 d_fprintf(stderr, "samba_tevent_context_init failed\n");
14218 req = smb1cli_session_setup_nt1_send(
14219 ev, ev, conn, 0, getpid(), NULL, 65503, 2, 1, 0, "", "",
14220 data_blob_null, data_blob_null, 0x40,
14221 "Windows 2000 2195", "Windows 2000 5.0");
14223 d_fprintf(stderr, "smb1cli_session_setup_nt1_send failed\n");
14227 ok = tevent_req_poll_ntstatus(req, ev, &status);
14229 d_fprintf(stderr, "tevent_req_poll failed\n");
14233 status = smb1cli_session_setup_nt1_recv(req, NULL, NULL, NULL, NULL,
14235 if (!NT_STATUS_EQUAL(status, NT_STATUS_CONNECTION_RESET)) {
14236 d_fprintf(stderr, "smb1cli_session_setup_nt1_recv returned "
14237 "%s, expected NT_STATUS_CONNECTION_RESET\n",
14238 nt_errstr(status));
14244 printf("starting ignore bad negprot\n");
14249 static double create_procs(bool (*fn)(int), bool *result)
14252 volatile pid_t *child_status;
14253 volatile bool *child_status_out;
14256 struct timeval start;
14260 child_status = (volatile pid_t *)anonymous_shared_allocate(sizeof(pid_t)*torture_nprocs);
14261 if (!child_status) {
14262 printf("Failed to setup shared memory\n");
14266 child_status_out = (volatile bool *)anonymous_shared_allocate(sizeof(bool)*torture_nprocs);
14267 if (!child_status_out) {
14268 printf("Failed to setup result status shared memory\n");
14272 for (i = 0; i < torture_nprocs; i++) {
14273 child_status[i] = 0;
14274 child_status_out[i] = True;
14277 start = timeval_current();
14279 for (i=0;i<torture_nprocs;i++) {
14282 pid_t mypid = getpid();
14283 sys_srandom(((int)mypid) ^ ((int)time(NULL)));
14285 slprintf(myname,sizeof(myname),"CLIENT%d", i);
14288 if (torture_open_connection(¤t_cli, i)) break;
14289 if (tries-- == 0) {
14290 printf("pid %d failed to start\n", (int)getpid());
14296 child_status[i] = getpid();
14298 while (child_status[i] && timeval_elapsed(&start) < 5) smb_msleep(2);
14300 child_status_out[i] = fn(i);
14307 for (i=0;i<torture_nprocs;i++) {
14308 if (child_status[i]) synccount++;
14310 if (synccount == torture_nprocs) break;
14312 } while (timeval_elapsed(&start) < 30);
14314 if (synccount != torture_nprocs) {
14315 printf("FAILED TO START %d CLIENTS (started %d)\n", torture_nprocs, synccount);
14317 return timeval_elapsed(&start);
14320 /* start the client load */
14321 start = timeval_current();
14323 for (i=0;i<torture_nprocs;i++) {
14324 child_status[i] = 0;
14327 printf("%d clients started\n", torture_nprocs);
14329 for (i=0;i<torture_nprocs;i++) {
14330 while (waitpid(0, &status, 0) == -1 && errno == EINTR) /* noop */ ;
14335 for (i=0;i<torture_nprocs;i++) {
14336 if (!child_status_out[i]) {
14340 return timeval_elapsed(&start);
14343 #define FLAG_MULTIPROC 1
14349 } torture_ops[] = {
14352 .fn = run_fdpasstest,
14356 .fn = run_locktest1,
14360 .fn = run_locktest2,
14364 .fn = run_locktest3,
14368 .fn = run_locktest4,
14372 .fn = run_locktest5,
14376 .fn = run_locktest6,
14380 .fn = run_locktest7,
14384 .fn = run_locktest8,
14388 .fn = run_locktest9a,
14392 .fn = run_locktest9b,
14396 .fn = run_locktest10,
14400 .fn = run_locktest11,
14404 .fn = run_locktest12,
14408 .fn = run_locktest13,
14412 .fn = run_unlinktest,
14416 .fn = run_browsetest,
14420 .fn = run_attrtest,
14424 .fn = run_trans2test,
14428 .fn = run_maxfidtest,
14429 .flags = FLAG_MULTIPROC,
14434 .flags = FLAG_MULTIPROC,
14437 .name = "RANDOMIPC",
14438 .fn = run_randomipc,
14441 .name = "NEGNOWAIT",
14442 .fn = run_negprot_nowait,
14464 #ifdef HAVE_KERNEL_OPLOCKS_LINUX
14476 .fn = run_dirtest1,
14479 .name = "DIR-CREATETIME",
14480 .fn = run_dir_createtime,
14484 .fn = torture_denytest1,
14488 .fn = torture_denytest2,
14492 .fn = run_tcon_test,
14496 .fn = run_tcon_devtype_test,
14500 .fn = run_readwritetest,
14504 .fn = run_readwritemulti,
14505 .flags = FLAG_MULTIPROC
14509 .fn = run_readwritelarge,
14512 .name = "RW-SIGNING",
14513 .fn = run_readwritelarge_signtest,
14517 .fn = run_opentest,
14521 .fn = run_simple_posix_open_test,
14524 .name = "POSIX-APPEND",
14525 .fn = run_posix_append,
14528 .name = "POSIX-SYMLINK-ACL",
14529 .fn = run_acl_symlink_test,
14532 .name = "POSIX-SYMLINK-EA",
14533 .fn = run_ea_symlink_test,
14536 .name = "POSIX-STREAM-DELETE",
14537 .fn = run_posix_stream_delete,
14540 .name = "POSIX-OFD-LOCK",
14541 .fn = run_posix_ofd_lock_test,
14544 .name = "POSIX-BLOCKING-LOCK",
14545 .fn = run_posix_blocking_lock,
14548 .name = "POSIX-MKDIR",
14549 .fn = run_posix_mkdir_test,
14552 .name = "POSIX-ACL-OPLOCK",
14553 .fn = run_posix_acl_oplock_test,
14556 .name = "POSIX-ACL-SHAREROOT",
14557 .fn = run_posix_acl_shareroot_test,
14560 .name = "WINDOWS-BAD-SYMLINK",
14561 .fn = run_symlink_open_test,
14564 .name = "CASE-INSENSITIVE-CREATE",
14565 .fn = run_case_insensitive_create,
14568 .name = "ASYNC-ECHO",
14569 .fn = run_async_echo,
14572 .name = "UID-REGRESSION-TEST",
14573 .fn = run_uid_regression_test,
14576 .name = "SHORTNAME-TEST",
14577 .fn = run_shortname_test,
14580 .name = "ADDRCHANGE",
14581 .fn = run_addrchange,
14585 .name = "OPENATTR",
14586 .fn = run_openattrtest,
14598 .name = "RENAME-ACCESS",
14599 .fn = run_rename_access,
14602 .name = "OWNER-RIGHTS",
14603 .fn = run_owner_rights,
14607 .fn = run_deletetest,
14610 .name = "DELETE-STREAM",
14611 .fn = run_delete_stream,
14614 .name = "DELETE-PRINT",
14615 .fn = run_delete_print_test,
14618 .name = "WILDDELETE",
14619 .fn = run_wild_deletetest,
14622 .name = "DELETE-LN",
14623 .fn = run_deletetest_ln,
14626 .name = "PROPERTIES",
14627 .fn = run_properties,
14631 .fn = torture_mangle,
14638 .name = "MANGLE-ILLEGAL",
14639 .fn = run_mangle_illegal,
14646 .name = "TRANS2SCAN",
14647 .fn = torture_trans2_scan,
14650 .name = "NTTRANSSCAN",
14651 .fn = torture_nttrans_scan,
14655 .fn = torture_utable,
14658 .name = "CASETABLE",
14659 .fn = torture_casetable,
14662 .name = "ERRMAPEXTRACT",
14663 .fn = run_error_map_extract,
14666 .name = "PIPE_NUMBER",
14667 .fn = run_pipe_number,
14671 .fn = run_tcon2_test,
14675 .fn = torture_ioctl_test,
14679 .fn = torture_chkpath_test,
14683 .fn = run_fdsesstest,
14690 .name = "SESSSETUP_BENCH",
14691 .fn = run_sesssetup_bench,
14706 .name = "WINDOWS-WRITE",
14707 .fn = run_windows_write,
14710 .name = "LARGE_READX",
14711 .fn = run_large_readx,
14714 .name = "MSDFS-ATTRIBUTE",
14715 .fn = run_msdfs_attribute,
14718 .name = "NTTRANS-CREATE",
14719 .fn = run_nttrans_create,
14722 .name = "NTTRANS-FSCTL",
14723 .fn = run_nttrans_fsctl,
14726 .name = "CLI_ECHO",
14727 .fn = run_cli_echo,
14730 .name = "CLI_SPLICE",
14731 .fn = run_cli_splice,
14738 .name = "STREAMERROR",
14739 .fn = run_streamerror,
14742 .name = "NOTIFY-BENCH",
14743 .fn = run_notify_bench,
14746 .name = "NOTIFY-BENCH2",
14747 .fn = run_notify_bench2,
14750 .name = "NOTIFY-BENCH3",
14751 .fn = run_notify_bench3,
14754 .name = "BAD-NBT-SESSION",
14755 .fn = run_bad_nbt_session,
14758 .name = "IGN-BAD-NEGPROT",
14759 .fn = run_ign_bad_negprot,
14762 .name = "SMB-ANY-CONNECT",
14763 .fn = run_smb_any_connect,
14766 .name = "NOTIFY-ONLINE",
14767 .fn = run_notify_online,
14770 .name = "SMB2-BASIC",
14771 .fn = run_smb2_basic,
14774 .name = "SMB2-NEGPROT",
14775 .fn = run_smb2_negprot,
14778 .name = "SMB2-ANONYMOUS",
14779 .fn = run_smb2_anonymous,
14782 .name = "SMB2-SESSION-RECONNECT",
14783 .fn = run_smb2_session_reconnect,
14786 .name = "SMB2-TCON-DEPENDENCE",
14787 .fn = run_smb2_tcon_dependence,
14790 .name = "SMB2-MULTI-CHANNEL",
14791 .fn = run_smb2_multi_channel,
14794 .name = "SMB2-SESSION-REAUTH",
14795 .fn = run_smb2_session_reauth,
14798 .name = "SMB2-FTRUNCATE",
14799 .fn = run_smb2_ftruncate,
14802 .name = "SMB2-DIR-FSYNC",
14803 .fn = run_smb2_dir_fsync,
14806 .name = "SMB2-PATH-SLASH",
14807 .fn = run_smb2_path_slash,
14810 .name = "SMB1-SYSTEM-SECURITY",
14811 .fn = run_smb1_system_security,
14814 .name = "SMB2-SACL",
14815 .fn = run_smb2_sacl,
14818 .name = "SMB2-QUOTA1",
14819 .fn = run_smb2_quota1,
14822 .name = "CLEANUP1",
14823 .fn = run_cleanup1,
14826 .name = "CLEANUP2",
14827 .fn = run_cleanup2,
14830 .name = "CLEANUP4",
14831 .fn = run_cleanup4,
14834 .name = "OPLOCK-CANCEL",
14835 .fn = run_oplock_cancel,
14842 .name = "LOCAL-SUBSTITUTE",
14843 .fn = run_local_substitute,
14846 .name = "LOCAL-GENCACHE",
14847 .fn = run_local_gencache,
14850 .name = "LOCAL-DBWRAP-WATCH1",
14851 .fn = run_dbwrap_watch1,
14854 .name = "LOCAL-DBWRAP-WATCH2",
14855 .fn = run_dbwrap_watch2,
14858 .name = "LOCAL-DBWRAP-WATCH3",
14859 .fn = run_dbwrap_watch3,
14862 .name = "LOCAL-DBWRAP-WATCH4",
14863 .fn = run_dbwrap_watch4,
14866 .name = "LOCAL-DBWRAP-DO-LOCKED1",
14867 .fn = run_dbwrap_do_locked1,
14870 .name = "LOCAL-MESSAGING-READ1",
14871 .fn = run_messaging_read1,
14874 .name = "LOCAL-MESSAGING-READ2",
14875 .fn = run_messaging_read2,
14878 .name = "LOCAL-MESSAGING-READ3",
14879 .fn = run_messaging_read3,
14882 .name = "LOCAL-MESSAGING-READ4",
14883 .fn = run_messaging_read4,
14886 .name = "LOCAL-MESSAGING-FDPASS1",
14887 .fn = run_messaging_fdpass1,
14890 .name = "LOCAL-MESSAGING-FDPASS2",
14891 .fn = run_messaging_fdpass2,
14894 .name = "LOCAL-MESSAGING-FDPASS2a",
14895 .fn = run_messaging_fdpass2a,
14898 .name = "LOCAL-MESSAGING-FDPASS2b",
14899 .fn = run_messaging_fdpass2b,
14902 .name = "LOCAL-MESSAGING-SEND-ALL",
14903 .fn = run_messaging_send_all,
14906 .name = "LOCAL-BASE64",
14907 .fn = run_local_base64,
14910 .name = "LOCAL-RBTREE",
14911 .fn = run_local_rbtree,
14914 .name = "LOCAL-MEMCACHE",
14915 .fn = run_local_memcache,
14918 .name = "LOCAL-STREAM-NAME",
14919 .fn = run_local_stream_name,
14922 .name = "WBCLIENT-MULTI-PING",
14923 .fn = run_wbclient_multi_ping,
14926 .name = "LOCAL-string_to_sid",
14927 .fn = run_local_string_to_sid,
14930 .name = "LOCAL-sid_to_string",
14931 .fn = run_local_sid_to_string,
14934 .name = "LOCAL-binary_to_sid",
14935 .fn = run_local_binary_to_sid,
14938 .name = "LOCAL-DBTRANS",
14939 .fn = run_local_dbtrans,
14942 .name = "LOCAL-TEVENT-POLL",
14943 .fn = run_local_tevent_poll,
14946 .name = "LOCAL-CONVERT-STRING",
14947 .fn = run_local_convert_string,
14950 .name = "LOCAL-CONV-AUTH-INFO",
14951 .fn = run_local_conv_auth_info,
14954 .name = "LOCAL-hex_encode_buf",
14955 .fn = run_local_hex_encode_buf,
14958 .name = "LOCAL-IDMAP-TDB-COMMON",
14959 .fn = run_idmap_tdb_common_test,
14962 .name = "LOCAL-remove_duplicate_addrs2",
14963 .fn = run_local_remove_duplicate_addrs2,
14966 .name = "local-tdb-opener",
14967 .fn = run_local_tdb_opener,
14970 .name = "local-tdb-writer",
14971 .fn = run_local_tdb_writer,
14974 .name = "LOCAL-DBWRAP-CTDB1",
14975 .fn = run_local_dbwrap_ctdb1,
14978 .name = "LOCAL-BENCH-PTHREADPOOL",
14979 .fn = run_bench_pthreadpool,
14982 .name = "LOCAL-PTHREADPOOL-TEVENT",
14983 .fn = run_pthreadpool_tevent,
14986 .name = "LOCAL-G-LOCK1",
14990 .name = "LOCAL-G-LOCK2",
14994 .name = "LOCAL-G-LOCK3",
14998 .name = "LOCAL-G-LOCK4",
15002 .name = "LOCAL-G-LOCK4A",
15003 .fn = run_g_lock4a,
15006 .name = "LOCAL-G-LOCK5",
15010 .name = "LOCAL-G-LOCK6",
15014 .name = "LOCAL-G-LOCK7",
15018 .name = "LOCAL-G-LOCK8",
15022 .name = "LOCAL-G-LOCK-PING-PONG",
15023 .fn = run_g_lock_ping_pong,
15026 .name = "LOCAL-CANONICALIZE-PATH",
15027 .fn = run_local_canonicalize_path,
15030 .name = "LOCAL-NAMEMAP-CACHE1",
15031 .fn = run_local_namemap_cache1,
15034 .name = "LOCAL-IDMAP-CACHE1",
15035 .fn = run_local_idmap_cache1,
15038 .name = "qpathinfo-bufsize",
15039 .fn = run_qpathinfo_bufsize,
15042 .name = "hide-new-files-timeout",
15043 .fn = run_hidenewfiles,
15045 #ifdef CLUSTER_SUPPORT
15047 .name = "ctdbd-conn1",
15048 .fn = run_ctdbd_conn1,
15052 .name = "readdir-timestamp",
15053 .fn = run_readdir_timestamp,
15060 /****************************************************************************
15061 run a specified test or "ALL"
15062 ****************************************************************************/
15063 static bool run_test(const char *name)
15066 bool result = True;
15067 bool found = False;
15070 if (strequal(name,"ALL")) {
15071 for (i=0;torture_ops[i].name;i++) {
15072 run_test(torture_ops[i].name);
15077 for (i=0;torture_ops[i].name;i++) {
15078 fstr_sprintf(randomfname, "\\XX%x",
15079 (unsigned)random());
15081 if (strequal(name, torture_ops[i].name)) {
15083 printf("Running %s\n", name);
15084 if (torture_ops[i].flags & FLAG_MULTIPROC) {
15085 t = create_procs(torture_ops[i].fn, &result);
15088 printf("TEST %s FAILED!\n", name);
15091 struct timeval start;
15092 start = timeval_current();
15093 if (!torture_ops[i].fn(0)) {
15095 printf("TEST %s FAILED!\n", name);
15097 t = timeval_elapsed(&start);
15099 printf("%s took %g secs\n\n", name, t);
15104 printf("Did not find a test named %s\n", name);
15112 static void usage(void)
15116 printf("WARNING samba4 test suite is much more complete nowadays.\n");
15117 printf("Please use samba4 torture.\n\n");
15119 printf("Usage: smbtorture //server/share <options> TEST1 TEST2 ...\n");
15121 printf("\t-d debuglevel\n");
15122 printf("\t-U user%%pass\n");
15123 printf("\t-k use kerberos\n");
15124 printf("\t-N numprocs\n");
15125 printf("\t-n my_netbios_name\n");
15126 printf("\t-W workgroup\n");
15127 printf("\t-o num_operations\n");
15128 printf("\t-O socket_options\n");
15129 printf("\t-m maximum protocol\n");
15130 printf("\t-L use oplocks\n");
15131 printf("\t-c CLIENT.TXT specify client load file for NBENCH\n");
15132 printf("\t-A showall\n");
15133 printf("\t-p port\n");
15134 printf("\t-s seed\n");
15135 printf("\t-b unclist_filename specify multiple shares for multiple connections\n");
15136 printf("\t-f filename filename to test\n");
15137 printf("\t-e encrypt\n");
15140 printf("tests are:");
15141 for (i=0;torture_ops[i].name;i++) {
15142 printf(" %s", torture_ops[i].name);
15146 printf("default test is ALL\n");
15151 /****************************************************************************
15153 ****************************************************************************/
15154 int main(int argc,char *argv[])
15160 bool correct = True;
15161 TALLOC_CTX *frame = talloc_stackframe();
15162 int seed = time(NULL);
15164 #ifdef HAVE_SETBUFFER
15165 setbuffer(stdout, NULL, 0);
15168 setup_logging("smbtorture", DEBUG_STDOUT);
15173 if (is_default_dyn_CONFIGFILE()) {
15174 if(getenv("SMB_CONF_PATH")) {
15175 set_dyn_CONFIGFILE(getenv("SMB_CONF_PATH"));
15178 lp_load_global(get_dyn_CONFIGFILE());
15185 for(p = argv[1]; *p; p++)
15189 if (strncmp(argv[1], "//", 2)) {
15193 fstrcpy(host, &argv[1][2]);
15194 p = strchr_m(&host[2],'/');
15199 fstrcpy(share, p+1);
15201 fstrcpy(myname, get_myname(talloc_tos()));
15203 fprintf(stderr, "Failed to get my hostname.\n");
15207 if (*username == 0 && getenv("LOGNAME")) {
15208 fstrcpy(username,getenv("LOGNAME"));
15214 fstrcpy(workgroup, lp_workgroup());
15216 while ((opt = getopt(argc, argv, "p:hW:U:n:N:O:o:m:Ll:d:Aec:ks:b:B:f:"))
15220 port_to_use = atoi(optarg);
15223 seed = atoi(optarg);
15226 fstrcpy(workgroup,optarg);
15229 lp_set_cmdline("client max protocol", optarg);
15232 torture_nprocs = atoi(optarg);
15235 torture_numops = atoi(optarg);
15238 lp_set_cmdline("log level", optarg);
15244 use_oplocks = True;
15247 local_path = optarg;
15250 torture_showall = True;
15253 fstrcpy(myname, optarg);
15256 client_txt = optarg;
15263 use_kerberos = True;
15265 d_printf("No kerberos support compiled in\n");
15271 fstrcpy(username,optarg);
15272 p = strchr_m(username,'%');
15275 fstrcpy(password, p+1);
15280 fstrcpy(multishare_conn_fname, optarg);
15281 use_multishare_conn = True;
15284 torture_blocksize = atoi(optarg);
15287 test_filename = SMB_STRDUP(optarg);
15290 printf("Unknown option %c (%d)\n", (char)opt, opt);
15295 d_printf("using seed %d\n", seed);
15299 if(use_kerberos && !gotuser) gotpass = True;
15302 char pwd[256] = {0};
15305 rc = samba_getpass("Password:", pwd, sizeof(pwd), false, false);
15307 fstrcpy(password, pwd);
15312 printf("host=%s share=%s user=%s myname=%s\n",
15313 host, share, username, myname);
15315 torture_creds = cli_session_creds_init(frame,
15321 false, /* fallback_after_kerberos */
15322 false, /* use_ccache */
15323 false); /* password_is_nt_hash */
15324 if (torture_creds == NULL) {
15325 d_printf("cli_session_creds_init() failed.\n");
15329 if (argc == optind) {
15330 correct = run_test("ALL");
15332 for (i=optind;i<argc;i++) {
15333 if (!run_test(argv[i])) {
15339 TALLOC_FREE(frame);