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 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4019 cli_openx(cli, fname,
4020 O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum);
4021 cli_close(cli, fnum);
4023 status = cli_getatr(cli, fname, NULL, NULL, &t);
4024 if (!NT_STATUS_IS_OK(status)) {
4025 printf("getatr failed (%s)\n", nt_errstr(status));
4029 if (labs(t - time(NULL)) > 60*60*24*10) {
4030 printf("ERROR: SMBgetatr bug. time is %s",
4036 t2 = t-60*60*24; /* 1 day ago */
4038 status = cli_setatr(cli, fname, 0, t2);
4039 if (!NT_STATUS_IS_OK(status)) {
4040 printf("setatr failed (%s)\n", nt_errstr(status));
4044 status = cli_getatr(cli, fname, NULL, NULL, &t);
4045 if (!NT_STATUS_IS_OK(status)) {
4046 printf("getatr failed (%s)\n", nt_errstr(status));
4051 printf("ERROR: getatr/setatr bug. times are\n%s",
4053 printf("%s", ctime(&t2));
4057 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4059 /* Check cli_setpathinfo_ext() */
4060 /* Re-create the file. */
4061 status = cli_openx(cli, fname,
4062 O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum);
4063 if (!NT_STATUS_IS_OK(status)) {
4064 printf("Failed to recreate %s (%s)\n",
4065 fname, nt_errstr(status));
4068 cli_close(cli, fnum);
4070 status = cli_setpathinfo_ext(
4073 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* create */
4074 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* access */
4075 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* write */
4076 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* change */
4077 FILE_ATTRIBUTE_SYSTEM |
4078 FILE_ATTRIBUTE_HIDDEN |
4079 FILE_ATTRIBUTE_READONLY);
4080 if (!NT_STATUS_IS_OK(status)) {
4081 printf("cli_setpathinfo_ext failed with %s\n",
4086 /* Check attributes are correct. */
4087 correct = check_attributes(cli,
4089 FILE_ATTRIBUTE_SYSTEM |
4090 FILE_ATTRIBUTE_HIDDEN |
4091 FILE_ATTRIBUTE_READONLY);
4092 if (correct == false) {
4096 /* Setting to FILE_ATTRIBUTE_NORMAL should be ignored. */
4097 status = cli_setpathinfo_ext(
4100 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* create */
4101 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* access */
4102 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* write */
4103 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* change */
4104 FILE_ATTRIBUTE_NORMAL);
4105 if (!NT_STATUS_IS_OK(status)) {
4106 printf("cli_setpathinfo_ext failed with %s\n",
4111 /* Check attributes are correct. */
4112 correct = check_attributes(cli,
4114 FILE_ATTRIBUTE_SYSTEM |
4115 FILE_ATTRIBUTE_HIDDEN |
4116 FILE_ATTRIBUTE_READONLY);
4117 if (correct == false) {
4121 /* Setting to (uint16_t)-1 should also be ignored. */
4122 status = cli_setpathinfo_ext(
4125 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* create */
4126 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* access */
4127 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* write */
4128 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* change */
4130 if (!NT_STATUS_IS_OK(status)) {
4131 printf("cli_setpathinfo_ext failed with %s\n",
4136 /* Check attributes are correct. */
4137 correct = check_attributes(cli,
4139 FILE_ATTRIBUTE_SYSTEM |
4140 FILE_ATTRIBUTE_HIDDEN |
4141 FILE_ATTRIBUTE_READONLY);
4142 if (correct == false) {
4146 /* Setting to 0 should clear them all. */
4147 status = cli_setpathinfo_ext(
4150 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* create */
4151 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* access */
4152 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* write */
4153 (struct timespec) { .tv_nsec = SAMBA_UTIME_OMIT }, /* change */
4155 if (!NT_STATUS_IS_OK(status)) {
4156 printf("cli_setpathinfo_ext failed with %s\n",
4161 /* Check attributes are correct. */
4162 correct = check_attributes(cli,
4164 FILE_ATTRIBUTE_NORMAL);
4165 if (correct == false) {
4173 FILE_ATTRIBUTE_SYSTEM |
4174 FILE_ATTRIBUTE_HIDDEN|
4175 FILE_ATTRIBUTE_READONLY);
4177 if (!torture_close_connection(cli)) {
4181 printf("attrib test finished\n");
4188 This checks a couple of trans2 calls
4190 static bool run_trans2test(int dummy)
4192 struct cli_state *cli;
4195 time_t c_time, a_time, m_time;
4196 struct timespec c_time_ts, a_time_ts, m_time_ts, w_time_ts, m_time2_ts;
4197 const char *fname = "\\trans2.tst";
4198 const char *dname = "\\trans2";
4199 const char *fname2 = "\\trans2\\trans2.tst";
4201 bool correct = True;
4206 printf("starting trans2 test\n");
4208 if (!torture_open_connection(&cli, 0)) {
4212 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
4213 /* Ensure ino is zero, SMB2 gets a real one. */
4216 /* Ensure ino is -1, SMB1 never gets a real one. */
4220 status = cli_get_fs_attr_info(cli, &fs_attr);
4221 if (!NT_STATUS_IS_OK(status)) {
4222 printf("ERROR: cli_get_fs_attr_info returned %s\n",
4227 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4228 cli_openx(cli, fname, O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum);
4229 status = cli_qfileinfo_basic(cli, fnum, NULL, &size, &c_time_ts,
4230 &a_time_ts, &w_time_ts, &m_time_ts, NULL);
4231 if (!NT_STATUS_IS_OK(status)) {
4232 printf("ERROR: qfileinfo failed (%s)\n", nt_errstr(status));
4236 status = cli_qfilename(cli, fnum, talloc_tos(), &pname);
4237 if (!NT_STATUS_IS_OK(status)) {
4238 printf("ERROR: qfilename failed (%s)\n", nt_errstr(status));
4241 else if (strcmp(pname, fname)) {
4242 printf("qfilename gave different name? [%s] [%s]\n",
4247 cli_close(cli, fnum);
4251 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4252 status = cli_openx(cli, fname, O_RDWR | O_CREAT | O_TRUNC, DENY_NONE,
4254 if (!NT_STATUS_IS_OK(status)) {
4255 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
4258 cli_close(cli, fnum);
4260 status = cli_qpathinfo1(cli, fname, &c_time, &a_time, &m_time, &size,
4262 if (!NT_STATUS_IS_OK(status)) {
4263 printf("ERROR: qpathinfo failed (%s)\n", nt_errstr(status));
4266 time_t t = time(NULL);
4268 if (c_time != m_time) {
4269 printf("create time=%s", ctime(&c_time));
4270 printf("modify time=%s", ctime(&m_time));
4271 printf("This system appears to have sticky create times\n");
4273 if ((labs(a_time - t) > 60) && (a_time % (60*60) == 0)) {
4274 printf("access time=%s", ctime(&a_time));
4275 printf("This system appears to set a midnight access time\n");
4279 if (labs(m_time - t) > 60*60*24*7) {
4280 printf("ERROR: totally incorrect times - maybe word reversed? mtime=%s", ctime(&m_time));
4286 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4287 cli_openx(cli, fname,
4288 O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum);
4289 cli_close(cli, fnum);
4290 status = cli_qpathinfo2(cli, fname, &c_time_ts, &a_time_ts, &w_time_ts,
4291 &m_time_ts, &size, NULL, &ino);
4292 if (!NT_STATUS_IS_OK(status)) {
4293 printf("ERROR: qpathinfo2 failed (%s)\n", nt_errstr(status));
4296 if (w_time_ts.tv_sec < 60*60*24*2) {
4297 printf("write time=%s", ctime(&w_time_ts.tv_sec));
4298 printf("This system appears to set a initial 0 write time\n");
4301 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
4302 /* SMB2 should always return an inode. */
4304 printf("SMB2 bad inode (0)\n");
4308 /* SMB1 must always return zero here. */
4310 printf("SMB1 bad inode (!0)\n");
4316 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4319 /* check if the server updates the directory modification time
4320 when creating a new file */
4321 status = cli_mkdir(cli, dname);
4322 if (!NT_STATUS_IS_OK(status)) {
4323 printf("ERROR: mkdir failed (%s)\n", nt_errstr(status));
4327 status = cli_qpathinfo2(cli, "\\trans2\\", &c_time_ts, &a_time_ts,
4328 &w_time_ts, &m_time_ts, &size, NULL, NULL);
4329 if (!NT_STATUS_IS_OK(status)) {
4330 printf("ERROR: qpathinfo2 failed (%s)\n", nt_errstr(status));
4334 cli_openx(cli, fname2,
4335 O_RDWR | O_CREAT | O_TRUNC, DENY_NONE, &fnum);
4336 cli_writeall(cli, fnum, 0, (uint8_t *)&fnum, 0, sizeof(fnum), NULL);
4337 cli_close(cli, fnum);
4338 status = cli_qpathinfo2(cli, "\\trans2\\", &c_time_ts, &a_time_ts,
4339 &w_time_ts, &m_time2_ts, &size, NULL, NULL);
4340 if (!NT_STATUS_IS_OK(status)) {
4341 printf("ERROR: qpathinfo2 failed (%s)\n", nt_errstr(status));
4344 if (memcmp(&m_time_ts, &m_time2_ts, sizeof(struct timespec))
4346 printf("This system does not update directory modification times\n");
4350 cli_unlink(cli, fname2, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4351 cli_rmdir(cli, dname);
4353 if (!torture_close_connection(cli)) {
4357 printf("trans2 test finished\n");
4363 This checks new W2K calls.
4366 static NTSTATUS new_trans(struct cli_state *pcli, int fnum, int level)
4368 uint8_t *buf = NULL;
4372 status = cli_qfileinfo(talloc_tos(), pcli, fnum, level, 0,
4373 CLI_BUFFER_SIZE, NULL, &buf, &len);
4374 if (!NT_STATUS_IS_OK(status)) {
4375 printf("ERROR: qfileinfo (%d) failed (%s)\n", level,
4378 printf("qfileinfo: level %d, len = %u\n", level, len);
4379 dump_data(0, (uint8_t *)buf, len);
4386 static bool run_w2ktest(int dummy)
4388 struct cli_state *cli;
4390 const char *fname = "\\w2ktest\\w2k.tst";
4392 bool correct = True;
4394 printf("starting w2k test\n");
4396 if (!torture_open_connection(&cli, 0)) {
4400 cli_openx(cli, fname,
4401 O_RDWR | O_CREAT , DENY_NONE, &fnum);
4403 for (level = 1004; level < 1040; level++) {
4404 new_trans(cli, fnum, level);
4407 cli_close(cli, fnum);
4409 if (!torture_close_connection(cli)) {
4413 printf("w2k test finished\n");
4420 this is a harness for some oplock tests
4422 static bool run_oplock1(int dummy)
4424 struct cli_state *cli1;
4425 const char *fname = "\\lockt1.lck";
4427 bool correct = True;
4430 printf("starting oplock test 1\n");
4432 if (!torture_open_connection(&cli1, 0)) {
4436 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4438 smbXcli_conn_set_sockopt(cli1->conn, sockops);
4440 cli1->use_oplocks = True;
4442 status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
4444 if (!NT_STATUS_IS_OK(status)) {
4445 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
4449 cli1->use_oplocks = False;
4451 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4452 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4454 status = cli_close(cli1, fnum1);
4455 if (!NT_STATUS_IS_OK(status)) {
4456 printf("close2 failed (%s)\n", nt_errstr(status));
4460 status = cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4461 if (!NT_STATUS_IS_OK(status)) {
4462 printf("unlink failed (%s)\n", nt_errstr(status));
4466 if (!torture_close_connection(cli1)) {
4470 printf("finished oplock test 1\n");
4475 static bool run_oplock2(int dummy)
4477 struct cli_state *cli1, *cli2;
4478 const char *fname = "\\lockt2.lck";
4479 uint16_t fnum1, fnum2;
4480 int saved_use_oplocks = use_oplocks;
4482 bool correct = True;
4483 volatile bool *shared_correct;
4487 shared_correct = (volatile bool *)anonymous_shared_allocate(sizeof(bool));
4488 *shared_correct = True;
4490 use_level_II_oplocks = True;
4493 printf("starting oplock test 2\n");
4495 if (!torture_open_connection(&cli1, 0)) {
4496 use_level_II_oplocks = False;
4497 use_oplocks = saved_use_oplocks;
4501 if (!torture_open_connection(&cli2, 1)) {
4502 use_level_II_oplocks = False;
4503 use_oplocks = saved_use_oplocks;
4507 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4509 smbXcli_conn_set_sockopt(cli1->conn, sockops);
4510 smbXcli_conn_set_sockopt(cli2->conn, sockops);
4512 status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
4514 if (!NT_STATUS_IS_OK(status)) {
4515 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
4519 /* Don't need the globals any more. */
4520 use_level_II_oplocks = False;
4521 use_oplocks = saved_use_oplocks;
4525 status = cli_openx(cli2, fname, O_RDWR, DENY_NONE, &fnum2);
4526 if (!NT_STATUS_IS_OK(status)) {
4527 printf("second open of %s failed (%s)\n", fname, nt_errstr(status));
4528 *shared_correct = False;
4534 status = cli_close(cli2, fnum2);
4535 if (!NT_STATUS_IS_OK(status)) {
4536 printf("close2 failed (%s)\n", nt_errstr(status));
4537 *shared_correct = False;
4545 /* Ensure cli1 processes the break. Empty file should always return 0
4547 status = cli_read(cli1, fnum1, buf, 0, 4, &nread);
4548 if (!NT_STATUS_IS_OK(status)) {
4549 printf("read on fnum1 failed (%s)\n", nt_errstr(status));
4551 } else if (nread != 0) {
4552 printf("read on empty fnum1 failed. recv %ld expected %d\n",
4553 (unsigned long)nread, 0);
4557 /* Should now be at level II. */
4558 /* Test if sending a write locks causes a break to none. */
4559 status = cli_lock32(cli1, fnum1, 0, 4, 0, READ_LOCK);
4560 if (!NT_STATUS_IS_OK(status)) {
4561 printf("lock failed (%s)\n", nt_errstr(status));
4565 cli_unlock(cli1, fnum1, 0, 4);
4569 status = cli_lock32(cli1, fnum1, 0, 4, 0, WRITE_LOCK);
4570 if (!NT_STATUS_IS_OK(status)) {
4571 printf("lock failed (%s)\n", nt_errstr(status));
4575 cli_unlock(cli1, fnum1, 0, 4);
4579 cli_read(cli1, fnum1, buf, 0, 4, NULL);
4581 status = cli_close(cli1, fnum1);
4582 if (!NT_STATUS_IS_OK(status)) {
4583 printf("close1 failed (%s)\n", nt_errstr(status));
4589 status = cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4590 if (!NT_STATUS_IS_OK(status)) {
4591 printf("unlink failed (%s)\n", nt_errstr(status));
4595 if (!torture_close_connection(cli1)) {
4599 if (!*shared_correct) {
4603 printf("finished oplock test 2\n");
4608 struct oplock4_state {
4609 struct tevent_context *ev;
4610 struct cli_state *cli;
4615 static void oplock4_got_break(struct tevent_req *req);
4616 static void oplock4_got_open(struct tevent_req *req);
4618 static bool run_oplock4(int dummy)
4620 struct tevent_context *ev;
4621 struct cli_state *cli1, *cli2;
4622 struct tevent_req *oplock_req, *open_req;
4623 const char *fname = "\\lockt4.lck";
4624 const char *fname_ln = "\\lockt4_ln.lck";
4625 uint16_t fnum1, fnum2;
4626 int saved_use_oplocks = use_oplocks;
4628 bool correct = true;
4632 struct oplock4_state *state;
4634 printf("starting oplock test 4\n");
4636 if (!torture_open_connection(&cli1, 0)) {
4637 use_level_II_oplocks = false;
4638 use_oplocks = saved_use_oplocks;
4642 if (!torture_open_connection(&cli2, 1)) {
4643 use_level_II_oplocks = false;
4644 use_oplocks = saved_use_oplocks;
4648 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4649 cli_unlink(cli1, fname_ln, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4651 smbXcli_conn_set_sockopt(cli1->conn, sockops);
4652 smbXcli_conn_set_sockopt(cli2->conn, sockops);
4654 /* Create the file. */
4655 status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
4657 if (!NT_STATUS_IS_OK(status)) {
4658 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
4662 status = cli_close(cli1, fnum1);
4663 if (!NT_STATUS_IS_OK(status)) {
4664 printf("close1 failed (%s)\n", nt_errstr(status));
4668 /* Now create a hardlink. */
4669 status = cli_hardlink(cli1, fname, fname_ln);
4670 if (!NT_STATUS_IS_OK(status)) {
4671 printf("nt hardlink failed (%s)\n", nt_errstr(status));
4675 /* Prove that opening hardlinks cause deny modes to conflict. */
4676 status = cli_openx(cli1, fname, O_RDWR, DENY_ALL, &fnum1);
4677 if (!NT_STATUS_IS_OK(status)) {
4678 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
4682 status = cli_openx(cli1, fname_ln, O_RDWR, DENY_NONE, &fnum2);
4683 if (NT_STATUS_IS_OK(status)) {
4684 printf("open of %s succeeded - should fail with sharing violation.\n",
4689 if (!NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
4690 printf("open of %s should fail with sharing violation. Got %s\n",
4691 fname_ln, nt_errstr(status));
4695 status = cli_close(cli1, fnum1);
4696 if (!NT_STATUS_IS_OK(status)) {
4697 printf("close1 failed (%s)\n", nt_errstr(status));
4701 cli1->use_oplocks = true;
4702 cli2->use_oplocks = true;
4704 status = cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
4705 if (!NT_STATUS_IS_OK(status)) {
4706 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
4710 ev = samba_tevent_context_init(talloc_tos());
4712 printf("tevent_context_init failed\n");
4716 state = talloc(ev, struct oplock4_state);
4717 if (state == NULL) {
4718 printf("talloc failed\n");
4723 state->got_break = &got_break;
4724 state->fnum2 = &fnum2;
4726 oplock_req = cli_smb_oplock_break_waiter_send(
4727 talloc_tos(), ev, cli1);
4728 if (oplock_req == NULL) {
4729 printf("cli_smb_oplock_break_waiter_send failed\n");
4732 tevent_req_set_callback(oplock_req, oplock4_got_break, state);
4734 open_req = cli_openx_send(
4735 talloc_tos(), ev, cli2, fname_ln, O_RDWR, DENY_NONE);
4736 if (open_req == NULL) {
4737 printf("cli_openx_send failed\n");
4740 tevent_req_set_callback(open_req, oplock4_got_open, state);
4745 while (!got_break || fnum2 == 0xffff) {
4747 ret = tevent_loop_once(ev);
4749 printf("tevent_loop_once failed: %s\n",
4755 status = cli_close(cli2, fnum2);
4756 if (!NT_STATUS_IS_OK(status)) {
4757 printf("close2 failed (%s)\n", nt_errstr(status));
4761 status = cli_close(cli1, fnum1);
4762 if (!NT_STATUS_IS_OK(status)) {
4763 printf("close1 failed (%s)\n", nt_errstr(status));
4767 status = cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4768 if (!NT_STATUS_IS_OK(status)) {
4769 printf("unlink failed (%s)\n", nt_errstr(status));
4773 status = cli_unlink(cli1, fname_ln, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
4774 if (!NT_STATUS_IS_OK(status)) {
4775 printf("unlink failed (%s)\n", nt_errstr(status));
4779 if (!torture_close_connection(cli1)) {
4787 printf("finished oplock test 4\n");
4792 static void oplock4_got_break(struct tevent_req *req)
4794 struct oplock4_state *state = tevent_req_callback_data(
4795 req, struct oplock4_state);
4800 status = cli_smb_oplock_break_waiter_recv(req, &fnum, &level);
4802 if (!NT_STATUS_IS_OK(status)) {
4803 printf("cli_smb_oplock_break_waiter_recv returned %s\n",
4807 *state->got_break = true;
4809 req = cli_oplock_ack_send(state, state->ev, state->cli, fnum,
4812 printf("cli_oplock_ack_send failed\n");
4817 static void oplock4_got_open(struct tevent_req *req)
4819 struct oplock4_state *state = tevent_req_callback_data(
4820 req, struct oplock4_state);
4823 status = cli_openx_recv(req, state->fnum2);
4824 if (!NT_STATUS_IS_OK(status)) {
4825 printf("cli_openx_recv returned %s\n", nt_errstr(status));
4826 *state->fnum2 = 0xffff;
4830 #ifdef HAVE_KERNEL_OPLOCKS_LINUX
4832 struct oplock5_state {
4837 * Async open the file that has a kernel oplock, do an echo to get
4838 * that 100% across, close the file to signal to the child fd that the
4839 * oplock can be dropped, wait for the open reply.
4842 static void oplock5_opened(struct tevent_req *subreq);
4843 static void oplock5_pong(struct tevent_req *subreq);
4844 static void oplock5_timedout(struct tevent_req *subreq);
4846 static struct tevent_req *oplock5_send(
4847 TALLOC_CTX *mem_ctx,
4848 struct tevent_context *ev,
4849 struct cli_state *cli,
4853 struct tevent_req *req = NULL, *subreq = NULL;
4854 struct oplock5_state *state = NULL;
4855 static uint8_t data = 0;
4857 req = tevent_req_create(mem_ctx, &state, struct oplock5_state);
4861 state->pipe_down_fd = pipe_down_fd;
4863 subreq = cli_ntcreate_send(
4869 SEC_FILE_READ_DATA, /* DesiredAccess */
4870 FILE_ATTRIBUTE_NORMAL, /* FileAttributes */
4871 FILE_SHARE_WRITE|FILE_SHARE_READ, /* ShareAccess */
4872 FILE_OPEN, /* CreateDisposition */
4873 FILE_NON_DIRECTORY_FILE, /* CreateOptions */
4874 0, /* Impersonation */
4875 0); /* SecurityFlags */
4876 if (tevent_req_nomem(subreq, req)) {
4877 return tevent_req_post(req, ev);
4879 tevent_req_set_callback(subreq, oplock5_opened, req);
4881 subreq = cli_echo_send(
4886 (DATA_BLOB) { .data = &data, .length = sizeof(data) });
4887 if (tevent_req_nomem(subreq, req)) {
4888 return tevent_req_post(req, ev);
4890 tevent_req_set_callback(subreq, oplock5_pong, req);
4892 subreq = tevent_wakeup_send(state, ev, timeval_current_ofs(20, 0));
4893 if (tevent_req_nomem(subreq, req)) {
4894 return tevent_req_post(req, ev);
4896 tevent_req_set_callback(subreq, oplock5_timedout, req);
4901 static void oplock5_opened(struct tevent_req *subreq)
4903 struct tevent_req *req = tevent_req_callback_data(
4904 subreq, struct tevent_req);
4908 status = cli_ntcreate_recv(subreq, &fnum, NULL);
4909 TALLOC_FREE(subreq);
4910 if (tevent_req_nterror(req, status)) {
4913 tevent_req_done(req);
4916 static void oplock5_pong(struct tevent_req *subreq)
4918 struct tevent_req *req = tevent_req_callback_data(
4919 subreq, struct tevent_req);
4920 struct oplock5_state *state = tevent_req_data(
4921 req, struct oplock5_state);
4924 status = cli_echo_recv(subreq);
4925 TALLOC_FREE(subreq);
4926 if (tevent_req_nterror(req, status)) {
4930 close(state->pipe_down_fd);
4933 static void oplock5_timedout(struct tevent_req *subreq)
4935 struct tevent_req *req = tevent_req_callback_data(
4936 subreq, struct tevent_req);
4939 ok = tevent_wakeup_recv(subreq);
4940 TALLOC_FREE(subreq);
4942 tevent_req_oom(req);
4945 tevent_req_nterror(req, NT_STATUS_TIMEOUT);
4948 static NTSTATUS oplock5_recv(struct tevent_req *req)
4950 return tevent_req_simple_recv_ntstatus(req);
4953 static bool run_oplock5(int dummy)
4955 struct tevent_context *ev = NULL;
4956 struct tevent_req *req = NULL;
4957 struct cli_state *cli = NULL;
4958 const char *fname = "oplock5.txt";
4959 int pipe_down[2], pipe_up[2];
4966 printf("starting oplock5\n");
4968 if (local_path == NULL) {
4969 d_fprintf(stderr, "oplock5 must be given a local path via "
4970 "-l <localpath>\n");
4974 ret = pipe(pipe_down);
4976 d_fprintf(stderr, "pipe() failed: %s\n", strerror(errno));
4979 ret = pipe(pipe_up);
4981 d_fprintf(stderr, "pipe() failed: %s\n", strerror(errno));
4986 if (child_pid == -1) {
4987 d_fprintf(stderr, "fork() failed: %s\n", strerror(errno));
4991 if (child_pid == 0) {
4992 char *local_file = NULL;
4995 close(pipe_down[1]);
4998 local_file = talloc_asprintf(
4999 talloc_tos(), "%s/%s", local_path, fname);
5000 if (local_file == 0) {
5004 fd = open(local_file, O_RDWR|O_CREAT, 0644);
5007 "open(%s) in child failed: %s\n",
5014 signal(SIGIO, SIG_IGN);
5016 ret = fcntl(fd, F_SETLEASE, F_WRLCK);
5019 "SETLEASE in child failed: %s\n",
5026 ret = sys_write(pipe_up[1], &c, sizeof(c));
5029 "sys_write failed: %s\n",
5033 ret = sys_read(pipe_down[0], &c, sizeof(c));
5036 "sys_read failed: %s\n",
5044 close(pipe_down[0]);
5046 ret = sys_read(pipe_up[0], &c, sizeof(c));
5049 "sys_read failed: %s\n",
5054 d_fprintf(stderr, "got error code %"PRIu8"\n", c);
5058 ok = torture_open_connection(&cli, 0);
5060 d_fprintf(stderr, "torture_open_connection failed\n");
5064 ev = samba_tevent_context_init(talloc_tos());
5066 d_fprintf(stderr, "samba_tevent_context_init failed\n");
5070 req = oplock5_send(ev, ev, cli, fname, pipe_down[1]);
5072 d_fprintf(stderr, "oplock5_send failed\n");
5076 ok = tevent_req_poll_ntstatus(req, ev, &status);
5079 "tevent_req_poll_ntstatus failed: %s\n",
5084 status = oplock5_recv(req);
5086 if (!NT_STATUS_IS_OK(status)) {
5088 "oplock5 failed: %s\n",
5096 #endif /* HAVE_KERNEL_OPLOCKS_LINUX */
5099 Test delete on close semantics.
5101 static bool run_deletetest(int dummy)
5103 struct cli_state *cli1 = NULL;
5104 struct cli_state *cli2 = NULL;
5105 const char *fname = "\\delete.file";
5106 uint16_t fnum1 = (uint16_t)-1;
5107 uint16_t fnum2 = (uint16_t)-1;
5108 bool correct = false;
5111 printf("starting delete test\n");
5113 if (!torture_open_connection(&cli1, 0)) {
5117 smbXcli_conn_set_sockopt(cli1->conn, sockops);
5119 /* Test 1 - this should delete the file on close. */
5121 cli_setatr(cli1, fname, 0, 0);
5122 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5124 status = cli_ntcreate(cli1, fname, 0, GENERIC_ALL_ACCESS|DELETE_ACCESS,
5125 FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
5126 FILE_DELETE_ON_CLOSE, 0, &fnum1, NULL);
5127 if (!NT_STATUS_IS_OK(status)) {
5128 printf("[1] open of %s failed (%s)\n", fname, nt_errstr(status));
5132 status = cli_close(cli1, fnum1);
5133 if (!NT_STATUS_IS_OK(status)) {
5134 printf("[1] close failed (%s)\n", nt_errstr(status));
5138 status = cli_openx(cli1, fname, O_RDWR, DENY_NONE, &fnum1);
5139 if (NT_STATUS_IS_OK(status)) {
5140 printf("[1] open of %s succeeded (should fail)\n", fname);
5144 printf("first delete on close test succeeded.\n");
5146 /* Test 2 - this should delete the file on close. */
5148 cli_setatr(cli1, fname, 0, 0);
5149 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5151 status = cli_ntcreate(cli1, fname, 0, GENERIC_ALL_ACCESS,
5152 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
5153 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
5154 if (!NT_STATUS_IS_OK(status)) {
5155 printf("[2] open of %s failed (%s)\n", fname, nt_errstr(status));
5159 status = cli_nt_delete_on_close(cli1, fnum1, true);
5160 if (!NT_STATUS_IS_OK(status)) {
5161 printf("[2] setting delete_on_close failed (%s)\n", nt_errstr(status));
5165 status = cli_close(cli1, fnum1);
5166 if (!NT_STATUS_IS_OK(status)) {
5167 printf("[2] close failed (%s)\n", nt_errstr(status));
5171 status = cli_openx(cli1, fname, O_RDONLY, DENY_NONE, &fnum1);
5172 if (NT_STATUS_IS_OK(status)) {
5173 printf("[2] open of %s succeeded should have been deleted on close !\n", fname);
5174 status = cli_close(cli1, fnum1);
5175 if (!NT_STATUS_IS_OK(status)) {
5176 printf("[2] close failed (%s)\n", nt_errstr(status));
5178 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5182 printf("second delete on close test succeeded.\n");
5185 cli_setatr(cli1, fname, 0, 0);
5186 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5188 status = cli_ntcreate(cli1, fname, 0, GENERIC_ALL_ACCESS,
5189 FILE_ATTRIBUTE_NORMAL,
5190 FILE_SHARE_READ|FILE_SHARE_WRITE,
5191 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
5192 if (!NT_STATUS_IS_OK(status)) {
5193 printf("[3] open - 1 of %s failed (%s)\n", fname, nt_errstr(status));
5197 /* This should fail with a sharing violation - open for delete is only compatible
5198 with SHARE_DELETE. */
5200 status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
5201 FILE_ATTRIBUTE_NORMAL,
5202 FILE_SHARE_READ|FILE_SHARE_WRITE,
5203 FILE_OPEN, 0, 0, &fnum2, NULL);
5204 if (NT_STATUS_IS_OK(status)) {
5205 printf("[3] open - 2 of %s succeeded - should have failed.\n", fname);
5209 /* This should succeed. */
5210 status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
5211 FILE_ATTRIBUTE_NORMAL,
5212 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5213 FILE_OPEN, 0, 0, &fnum2, NULL);
5214 if (!NT_STATUS_IS_OK(status)) {
5215 printf("[3] open - 3 of %s failed (%s)\n", fname, nt_errstr(status));
5219 status = cli_nt_delete_on_close(cli1, fnum1, true);
5220 if (!NT_STATUS_IS_OK(status)) {
5221 printf("[3] setting delete_on_close failed (%s)\n", nt_errstr(status));
5225 status = cli_close(cli1, fnum1);
5226 if (!NT_STATUS_IS_OK(status)) {
5227 printf("[3] close 1 failed (%s)\n", nt_errstr(status));
5231 status = cli_close(cli1, fnum2);
5232 if (!NT_STATUS_IS_OK(status)) {
5233 printf("[3] close 2 failed (%s)\n", nt_errstr(status));
5237 /* This should fail - file should no longer be there. */
5239 status = cli_openx(cli1, fname, O_RDONLY, DENY_NONE, &fnum1);
5240 if (NT_STATUS_IS_OK(status)) {
5241 printf("[3] open of %s succeeded should have been deleted on close !\n", fname);
5242 status = cli_close(cli1, fnum1);
5243 if (!NT_STATUS_IS_OK(status)) {
5244 printf("[3] close failed (%s)\n", nt_errstr(status));
5246 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5250 printf("third delete on close test succeeded.\n");
5253 cli_setatr(cli1, fname, 0, 0);
5254 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5256 status = cli_ntcreate(cli1, fname, 0,
5257 FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
5258 FILE_ATTRIBUTE_NORMAL,
5259 FILE_SHARE_READ|FILE_SHARE_WRITE,
5260 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
5261 if (!NT_STATUS_IS_OK(status)) {
5262 printf("[4] open of %s failed (%s)\n", fname, nt_errstr(status));
5266 /* This should succeed. */
5267 status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
5268 FILE_ATTRIBUTE_NORMAL,
5269 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5270 FILE_OPEN, 0, 0, &fnum2, NULL);
5271 if (!NT_STATUS_IS_OK(status)) {
5272 printf("[4] open - 2 of %s failed (%s)\n", fname, nt_errstr(status));
5276 status = cli_close(cli1, fnum2);
5277 if (!NT_STATUS_IS_OK(status)) {
5278 printf("[4] close - 1 failed (%s)\n", nt_errstr(status));
5282 status = cli_nt_delete_on_close(cli1, fnum1, true);
5283 if (!NT_STATUS_IS_OK(status)) {
5284 printf("[4] setting delete_on_close failed (%s)\n", nt_errstr(status));
5288 /* This should fail - no more opens once delete on close set. */
5289 status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
5290 FILE_ATTRIBUTE_NORMAL,
5291 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5292 FILE_OPEN, 0, 0, &fnum2, NULL);
5293 if (NT_STATUS_IS_OK(status)) {
5294 printf("[4] open - 3 of %s succeeded ! Should have failed.\n", fname );
5298 status = cli_close(cli1, fnum1);
5299 if (!NT_STATUS_IS_OK(status)) {
5300 printf("[4] close - 2 failed (%s)\n", nt_errstr(status));
5304 printf("fourth delete on close test succeeded.\n");
5307 cli_setatr(cli1, fname, 0, 0);
5308 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5310 status = cli_openx(cli1, fname, O_RDWR|O_CREAT, DENY_NONE, &fnum1);
5311 if (!NT_STATUS_IS_OK(status)) {
5312 printf("[5] open of %s failed (%s)\n", fname, nt_errstr(status));
5316 /* This should fail - only allowed on NT opens with DELETE access. */
5318 status = cli_nt_delete_on_close(cli1, fnum1, true);
5319 if (NT_STATUS_IS_OK(status)) {
5320 printf("[5] setting delete_on_close on OpenX file succeeded - should fail !\n");
5324 status = cli_close(cli1, fnum1);
5325 if (!NT_STATUS_IS_OK(status)) {
5326 printf("[5] close failed (%s)\n", nt_errstr(status));
5330 printf("fifth delete on close test succeeded.\n");
5333 cli_setatr(cli1, fname, 0, 0);
5334 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5336 status = cli_ntcreate(cli1, fname, 0, FILE_READ_DATA|FILE_WRITE_DATA,
5337 FILE_ATTRIBUTE_NORMAL,
5338 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5339 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
5340 if (!NT_STATUS_IS_OK(status)) {
5341 printf("[6] open of %s failed (%s)\n", fname,
5346 /* This should fail - only allowed on NT opens with DELETE access. */
5348 status = cli_nt_delete_on_close(cli1, fnum1, true);
5349 if (NT_STATUS_IS_OK(status)) {
5350 printf("[6] setting delete_on_close on file with no delete access succeeded - should fail !\n");
5354 status = cli_close(cli1, fnum1);
5355 if (!NT_STATUS_IS_OK(status)) {
5356 printf("[6] close failed (%s)\n", nt_errstr(status));
5360 printf("sixth delete on close test succeeded.\n");
5363 cli_setatr(cli1, fname, 0, 0);
5364 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5366 status = cli_ntcreate(cli1, fname, 0,
5367 FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
5368 FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
5369 0, 0, &fnum1, NULL);
5370 if (!NT_STATUS_IS_OK(status)) {
5371 printf("[7] open of %s failed (%s)\n", fname, nt_errstr(status));
5375 status = cli_nt_delete_on_close(cli1, fnum1, true);
5376 if (!NT_STATUS_IS_OK(status)) {
5377 printf("[7] setting delete_on_close on file failed !\n");
5381 status = cli_nt_delete_on_close(cli1, fnum1, false);
5382 if (!NT_STATUS_IS_OK(status)) {
5383 printf("[7] unsetting delete_on_close on file failed !\n");
5387 status = cli_close(cli1, fnum1);
5388 if (!NT_STATUS_IS_OK(status)) {
5389 printf("[7] close - 1 failed (%s)\n", nt_errstr(status));
5393 /* This next open should succeed - we reset the flag. */
5394 status = cli_openx(cli1, fname, O_RDONLY, DENY_NONE, &fnum1);
5395 if (!NT_STATUS_IS_OK(status)) {
5396 printf("[7] open of %s failed (%s)\n", fname, nt_errstr(status));
5400 status = cli_close(cli1, fnum1);
5401 if (!NT_STATUS_IS_OK(status)) {
5402 printf("[7] close - 2 failed (%s)\n", nt_errstr(status));
5406 printf("seventh delete on close test succeeded.\n");
5409 cli_setatr(cli1, fname, 0, 0);
5410 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5412 if (!torture_open_connection(&cli2, 1)) {
5413 printf("[8] failed to open second connection.\n");
5417 smbXcli_conn_set_sockopt(cli1->conn, sockops);
5419 status = cli_ntcreate(cli1, fname, 0,
5420 FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
5421 FILE_ATTRIBUTE_NORMAL,
5422 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5423 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
5424 if (!NT_STATUS_IS_OK(status)) {
5425 printf("[8] open 1 of %s failed (%s)\n", fname, nt_errstr(status));
5429 status = cli_ntcreate(cli2, fname, 0,
5430 FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
5431 FILE_ATTRIBUTE_NORMAL,
5432 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5433 FILE_OPEN, 0, 0, &fnum2, NULL);
5434 if (!NT_STATUS_IS_OK(status)) {
5435 printf("[8] open 2 of %s failed (%s)\n", fname, nt_errstr(status));
5439 status = cli_nt_delete_on_close(cli1, fnum1, true);
5440 if (!NT_STATUS_IS_OK(status)) {
5441 printf("[8] setting delete_on_close on file failed !\n");
5445 status = cli_close(cli1, fnum1);
5446 if (!NT_STATUS_IS_OK(status)) {
5447 printf("[8] close - 1 failed (%s)\n", nt_errstr(status));
5451 status = cli_close(cli2, fnum2);
5452 if (!NT_STATUS_IS_OK(status)) {
5453 printf("[8] close - 2 failed (%s)\n", nt_errstr(status));
5457 /* This should fail.. */
5458 status = cli_openx(cli1, fname, O_RDONLY, DENY_NONE, &fnum1);
5459 if (NT_STATUS_IS_OK(status)) {
5460 printf("[8] open of %s succeeded should have been deleted on close !\n", fname);
5464 printf("eighth delete on close test succeeded.\n");
5468 /* This should fail - we need to set DELETE_ACCESS. */
5469 status = cli_ntcreate(cli1, fname, 0, FILE_READ_DATA|FILE_WRITE_DATA,
5470 FILE_ATTRIBUTE_NORMAL,
5473 FILE_DELETE_ON_CLOSE, 0, &fnum1, NULL);
5474 if (NT_STATUS_IS_OK(status)) {
5475 printf("[9] open of %s succeeded should have failed!\n", fname);
5479 printf("ninth delete on close test succeeded.\n");
5483 status = cli_ntcreate(cli1, fname, 0,
5484 FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
5485 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
5486 FILE_OVERWRITE_IF, FILE_DELETE_ON_CLOSE,
5488 if (!NT_STATUS_IS_OK(status)) {
5489 printf("[10] open of %s failed (%s)\n", fname, nt_errstr(status));
5493 /* This should delete the file. */
5494 status = cli_close(cli1, fnum1);
5495 if (!NT_STATUS_IS_OK(status)) {
5496 printf("[10] close failed (%s)\n", nt_errstr(status));
5500 /* This should fail.. */
5501 status = cli_openx(cli1, fname, O_RDONLY, DENY_NONE, &fnum1);
5502 if (NT_STATUS_IS_OK(status)) {
5503 printf("[10] open of %s succeeded should have been deleted on close !\n", fname);
5507 printf("tenth delete on close test succeeded.\n");
5511 cli_setatr(cli1, fname, 0, 0);
5512 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5514 /* Can we open a read-only file with delete access? */
5516 /* Create a readonly file. */
5517 status = cli_ntcreate(cli1, fname, 0, FILE_READ_DATA|FILE_WRITE_DATA,
5518 FILE_ATTRIBUTE_READONLY, FILE_SHARE_NONE,
5519 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
5520 if (!NT_STATUS_IS_OK(status)) {
5521 printf("[11] open of %s failed (%s)\n", fname, nt_errstr(status));
5525 status = cli_close(cli1, fnum1);
5526 if (!NT_STATUS_IS_OK(status)) {
5527 printf("[11] close failed (%s)\n", nt_errstr(status));
5531 /* Now try open for delete access. */
5532 status = cli_ntcreate(cli1, fname, 0,
5533 FILE_READ_ATTRIBUTES|DELETE_ACCESS,
5535 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5536 FILE_OPEN, 0, 0, &fnum1, NULL);
5537 if (!NT_STATUS_IS_OK(status)) {
5538 printf("[11] open of %s failed: %s\n", fname, nt_errstr(status));
5542 cli_close(cli1, fnum1);
5544 printf("eleventh delete on close test succeeded.\n");
5548 * like test 4 but with initial delete on close
5551 cli_setatr(cli1, fname, 0, 0);
5552 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5554 status = cli_ntcreate(cli1, fname, 0,
5555 FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
5556 FILE_ATTRIBUTE_NORMAL,
5557 FILE_SHARE_READ|FILE_SHARE_WRITE,
5559 FILE_DELETE_ON_CLOSE, 0, &fnum1, NULL);
5560 if (!NT_STATUS_IS_OK(status)) {
5561 printf("[12] open 1 of %s failed (%s)\n", fname, nt_errstr(status));
5565 status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
5566 FILE_ATTRIBUTE_NORMAL,
5567 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5568 FILE_OPEN, 0, 0, &fnum2, NULL);
5569 if (!NT_STATUS_IS_OK(status)) {
5570 printf("[12] open 2 of %s failed(%s).\n", fname, nt_errstr(status));
5574 status = cli_close(cli1, fnum2);
5575 if (!NT_STATUS_IS_OK(status)) {
5576 printf("[12] close 1 failed (%s)\n", nt_errstr(status));
5580 status = cli_nt_delete_on_close(cli1, fnum1, true);
5581 if (!NT_STATUS_IS_OK(status)) {
5582 printf("[12] setting delete_on_close failed (%s)\n", nt_errstr(status));
5586 /* This should fail - no more opens once delete on close set. */
5587 status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
5588 FILE_ATTRIBUTE_NORMAL,
5589 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5590 FILE_OPEN, 0, 0, &fnum2, NULL);
5591 if (NT_STATUS_IS_OK(status)) {
5592 printf("[12] open 3 of %s succeeded - should fail).\n", fname);
5596 status = cli_nt_delete_on_close(cli1, fnum1, false);
5597 if (!NT_STATUS_IS_OK(status)) {
5598 printf("[12] unsetting delete_on_close failed (%s)\n", nt_errstr(status));
5602 status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
5603 FILE_ATTRIBUTE_NORMAL,
5604 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5605 FILE_OPEN, 0, 0, &fnum2, NULL);
5606 if (!NT_STATUS_IS_OK(status)) {
5607 printf("[12] open 4 of %s failed (%s)\n", fname, nt_errstr(status));
5611 status = cli_close(cli1, fnum2);
5612 if (!NT_STATUS_IS_OK(status)) {
5613 printf("[12] close 2 failed (%s)\n", nt_errstr(status));
5617 status = cli_close(cli1, fnum1);
5618 if (!NT_STATUS_IS_OK(status)) {
5619 printf("[12] close 3 failed (%s)\n", nt_errstr(status));
5624 * setting delete on close on the handle does
5625 * not unset the initial delete on close...
5627 status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
5628 FILE_ATTRIBUTE_NORMAL,
5629 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5630 FILE_OPEN, 0, 0, &fnum2, NULL);
5631 if (NT_STATUS_IS_OK(status)) {
5632 printf("[12] open 5 of %s succeeded - should fail).\n", fname);
5634 } else if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
5635 printf("ntcreate returned %s, expected "
5636 "NT_STATUS_OBJECT_NAME_NOT_FOUND\n",
5641 printf("twelfth delete on close test succeeded.\n");
5644 printf("finished delete test\n");
5649 /* FIXME: This will crash if we aborted before cli2 got
5650 * intialized, because these functions don't handle
5651 * uninitialized connections. */
5653 if (fnum1 != (uint16_t)-1) cli_close(cli1, fnum1);
5654 if (fnum2 != (uint16_t)-1) cli_close(cli1, fnum2);
5655 cli_setatr(cli1, fname, 0, 0);
5656 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5658 if (cli1 && !torture_close_connection(cli1)) {
5661 if (cli2 && !torture_close_connection(cli2)) {
5667 struct delete_stream_state {
5671 static void delete_stream_unlinked(struct tevent_req *subreq);
5672 static void delete_stream_closed(struct tevent_req *subreq);
5674 static struct tevent_req *delete_stream_send(
5675 TALLOC_CTX *mem_ctx,
5676 struct tevent_context *ev,
5677 struct cli_state *cli,
5678 const char *base_fname,
5679 uint16_t stream_fnum)
5681 struct tevent_req *req = NULL, *subreq = NULL;
5682 struct delete_stream_state *state = NULL;
5684 req = tevent_req_create(
5685 mem_ctx, &state, struct delete_stream_state);
5690 subreq = cli_unlink_send(
5695 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5696 if (tevent_req_nomem(subreq, req)) {
5697 return tevent_req_post(req, ev);
5699 tevent_req_set_callback(subreq, delete_stream_unlinked, req);
5701 subreq = cli_close_send(state, ev, cli, stream_fnum);
5702 if (tevent_req_nomem(subreq, req)) {
5703 return tevent_req_post(req, ev);
5705 tevent_req_set_callback(subreq, delete_stream_closed, req);
5710 static void delete_stream_unlinked(struct tevent_req *subreq)
5712 struct tevent_req *req = tevent_req_callback_data(
5713 subreq, struct tevent_req);
5714 struct delete_stream_state *state = tevent_req_data(
5715 req, struct delete_stream_state);
5718 status = cli_unlink_recv(subreq);
5719 TALLOC_FREE(subreq);
5720 if (!NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
5721 printf("cli_unlink returned %s\n",
5723 tevent_req_nterror(req, NT_STATUS_UNSUCCESSFUL);
5726 if (!state->closed) {
5727 /* close reply should have come in first */
5728 printf("Not closed\n");
5729 tevent_req_nterror(req, NT_STATUS_UNSUCCESSFUL);
5732 tevent_req_done(req);
5735 static void delete_stream_closed(struct tevent_req *subreq)
5737 struct tevent_req *req = tevent_req_callback_data(
5738 subreq, struct tevent_req);
5739 struct delete_stream_state *state = tevent_req_data(
5740 req, struct delete_stream_state);
5743 status = cli_close_recv(subreq);
5744 TALLOC_FREE(subreq);
5745 if (tevent_req_nterror(req, status)) {
5748 /* also waiting for the unlink to come back */
5749 state->closed = true;
5752 static NTSTATUS delete_stream_recv(struct tevent_req *req)
5754 return tevent_req_simple_recv_ntstatus(req);
5757 static bool run_delete_stream(int dummy)
5759 struct tevent_context *ev = NULL;
5760 struct tevent_req *req = NULL;
5761 struct cli_state *cli = NULL;
5762 const char fname[] = "delete_stream";
5763 const char fname_stream[] = "delete_stream:Zone.Identifier:$DATA";
5764 uint16_t fnum1, fnum2;
5768 printf("Starting stream delete test\n");
5770 ok = torture_open_connection(&cli, 0);
5775 cli_setatr(cli, fname, 0, 0);
5776 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5778 /* Create the file. */
5779 status = cli_ntcreate(
5783 READ_CONTROL_ACCESS,
5785 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5791 if (!NT_STATUS_IS_OK(status)) {
5793 "cli_ntcreate of %s failed (%s)\n",
5798 status = cli_close(cli, fnum1);
5799 if (!NT_STATUS_IS_OK(status)) {
5801 "cli_close of %s failed (%s)\n",
5807 /* Now create the stream. */
5808 status = cli_ntcreate(
5814 FILE_SHARE_READ|FILE_SHARE_WRITE,
5821 if (!NT_STATUS_IS_OK(status)) {
5823 "cli_ntcreate of %s failed (%s)\n",
5829 /* open it a second time */
5831 status = cli_ntcreate(
5837 FILE_SHARE_READ|FILE_SHARE_WRITE,
5844 if (!NT_STATUS_IS_OK(status)) {
5846 "2nd cli_ntcreate of %s failed (%s)\n",
5852 ev = samba_tevent_context_init(talloc_tos());
5854 d_fprintf(stderr, "samba_tevent_context_init failed\n");
5858 req = delete_stream_send(ev, ev, cli, fname, fnum1);
5860 d_fprintf(stderr, "delete_stream_send failed\n");
5864 ok = tevent_req_poll_ntstatus(req, ev, &status);
5867 "tevent_req_poll_ntstatus failed: %s\n",
5872 status = delete_stream_recv(req);
5874 if (!NT_STATUS_IS_OK(status)) {
5876 "delete_stream failed: %s\n",
5881 status = cli_close(cli, fnum2);
5882 if (!NT_STATUS_IS_OK(status)) {
5884 "close failed: %s\n",
5889 status = cli_unlink(
5890 cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
5891 if (!NT_STATUS_IS_OK(status)) {
5893 "unlink failed: %s\n",
5902 Exercise delete on close semantics - use on the PRINT1 share in torture
5905 static bool run_delete_print_test(int dummy)
5907 struct cli_state *cli1 = NULL;
5908 const char *fname = "print_delete.file";
5909 uint16_t fnum1 = (uint16_t)-1;
5910 bool correct = false;
5911 const char *buf = "print file data\n";
5914 printf("starting print delete test\n");
5916 if (!torture_open_connection(&cli1, 0)) {
5920 smbXcli_conn_set_sockopt(cli1->conn, sockops);
5922 status = cli_ntcreate(cli1, fname, 0, GENERIC_ALL_ACCESS|DELETE_ACCESS,
5923 FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
5924 0, 0, &fnum1, NULL);
5925 if (!NT_STATUS_IS_OK(status)) {
5926 printf("open of %s failed (%s)\n",
5932 status = cli_writeall(cli1,
5935 (const uint8_t *)buf,
5937 strlen(buf), /* size */
5939 if (!NT_STATUS_IS_OK(status)) {
5940 printf("writing print file data failed (%s)\n",
5945 status = cli_nt_delete_on_close(cli1, fnum1, true);
5946 if (!NT_STATUS_IS_OK(status)) {
5947 printf("setting delete_on_close failed (%s)\n",
5952 status = cli_close(cli1, fnum1);
5953 if (!NT_STATUS_IS_OK(status)) {
5954 printf("close failed (%s)\n", nt_errstr(status));
5958 printf("finished print delete test\n");
5964 if (fnum1 != (uint16_t)-1) {
5965 cli_close(cli1, fnum1);
5968 if (cli1 && !torture_close_connection(cli1)) {
5975 Test wildcard delete.
5977 static bool run_wild_deletetest(int dummy)
5979 struct cli_state *cli = NULL;
5980 const char *dname = "\\WTEST";
5981 const char *fname = "\\WTEST\\A";
5982 const char *wunlink_name = "\\WTEST\\*";
5983 uint16_t fnum1 = (uint16_t)-1;
5984 bool correct = false;
5987 printf("starting wildcard delete test\n");
5989 if (!torture_open_connection(&cli, 0)) {
5993 smbXcli_conn_set_sockopt(cli->conn, sockops);
5995 cli_unlink(cli, fname, 0);
5996 cli_rmdir(cli, dname);
5997 status = cli_mkdir(cli, dname);
5998 if (!NT_STATUS_IS_OK(status)) {
5999 printf("mkdir of %s failed %s!\n", dname, nt_errstr(status));
6002 status = cli_openx(cli, fname, O_CREAT|O_RDONLY, DENY_NONE, &fnum1);
6003 if (!NT_STATUS_IS_OK(status)) {
6004 printf("open of %s failed %s!\n", fname, nt_errstr(status));
6007 status = cli_close(cli, fnum1);
6011 * Note the unlink attribute-type of zero. This should
6012 * map into FILE_ATTRIBUTE_NORMAL at the server even
6013 * on a wildcard delete.
6016 status = cli_unlink(cli, wunlink_name, 0);
6017 if (!NT_STATUS_IS_OK(status)) {
6018 printf("unlink of %s failed %s!\n",
6019 wunlink_name, nt_errstr(status));
6023 printf("finished wildcard delete test\n");
6029 if (fnum1 != (uint16_t)-1) cli_close(cli, fnum1);
6030 cli_unlink(cli, fname, 0);
6031 cli_rmdir(cli, dname);
6033 if (cli && !torture_close_connection(cli)) {
6039 static bool run_deletetest_ln(int dummy)
6041 struct cli_state *cli;
6042 const char *fname = "\\delete1";
6043 const char *fname_ln = "\\delete1_ln";
6047 bool correct = true;
6050 printf("starting deletetest-ln\n");
6052 if (!torture_open_connection(&cli, 0)) {
6056 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6057 cli_unlink(cli, fname_ln, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6059 smbXcli_conn_set_sockopt(cli->conn, sockops);
6061 /* Create the file. */
6062 status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
6063 if (!NT_STATUS_IS_OK(status)) {
6064 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
6068 status = cli_close(cli, fnum);
6069 if (!NT_STATUS_IS_OK(status)) {
6070 printf("close1 failed (%s)\n", nt_errstr(status));
6074 /* Now create a hardlink. */
6075 status = cli_hardlink(cli, fname, fname_ln);
6076 if (!NT_STATUS_IS_OK(status)) {
6077 printf("nt hardlink failed (%s)\n", nt_errstr(status));
6081 /* Open the original file. */
6082 status = cli_ntcreate(cli, fname, 0, FILE_READ_DATA,
6083 FILE_ATTRIBUTE_NORMAL,
6084 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6085 FILE_OPEN_IF, 0, 0, &fnum, NULL);
6086 if (!NT_STATUS_IS_OK(status)) {
6087 printf("ntcreate of %s failed (%s)\n", fname, nt_errstr(status));
6091 /* Unlink the hard link path. */
6092 status = cli_ntcreate(cli, fname_ln, 0, DELETE_ACCESS,
6093 FILE_ATTRIBUTE_NORMAL,
6094 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6095 FILE_OPEN_IF, 0, 0, &fnum1, NULL);
6096 if (!NT_STATUS_IS_OK(status)) {
6097 printf("ntcreate of %s failed (%s)\n", fname_ln, nt_errstr(status));
6100 status = cli_nt_delete_on_close(cli, fnum1, true);
6101 if (!NT_STATUS_IS_OK(status)) {
6102 d_printf("(%s) failed to set delete_on_close %s: %s\n",
6103 __location__, fname_ln, nt_errstr(status));
6107 status = cli_close(cli, fnum1);
6108 if (!NT_STATUS_IS_OK(status)) {
6109 printf("close %s failed (%s)\n",
6110 fname_ln, nt_errstr(status));
6114 status = cli_close(cli, fnum);
6115 if (!NT_STATUS_IS_OK(status)) {
6116 printf("close %s failed (%s)\n",
6117 fname, nt_errstr(status));
6121 /* Ensure the original file is still there. */
6122 status = cli_getatr(cli, fname, NULL, NULL, &t);
6123 if (!NT_STATUS_IS_OK(status)) {
6124 printf("%s getatr on file %s failed (%s)\n",
6131 /* Ensure the link path is gone. */
6132 status = cli_getatr(cli, fname_ln, NULL, NULL, &t);
6133 if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
6134 printf("%s, getatr for file %s returned wrong error code %s "
6135 "- should have been deleted\n",
6137 fname_ln, nt_errstr(status));
6141 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6142 cli_unlink(cli, fname_ln, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6144 if (!torture_close_connection(cli)) {
6148 printf("finished deletetest-ln\n");
6154 print out server properties
6156 static bool run_properties(int dummy)
6158 struct cli_state *cli;
6159 bool correct = True;
6161 printf("starting properties test\n");
6165 if (!torture_open_connection(&cli, 0)) {
6169 smbXcli_conn_set_sockopt(cli->conn, sockops);
6171 d_printf("Capabilities 0x%08x\n", smb1cli_conn_capabilities(cli->conn));
6173 if (!torture_close_connection(cli)) {
6182 /* FIRST_DESIRED_ACCESS 0xf019f */
6183 #define FIRST_DESIRED_ACCESS FILE_READ_DATA|FILE_WRITE_DATA|FILE_APPEND_DATA|\
6184 FILE_READ_EA| /* 0xf */ \
6185 FILE_WRITE_EA|FILE_READ_ATTRIBUTES| /* 0x90 */ \
6186 FILE_WRITE_ATTRIBUTES| /* 0x100 */ \
6187 DELETE_ACCESS|READ_CONTROL_ACCESS|\
6188 WRITE_DAC_ACCESS|WRITE_OWNER_ACCESS /* 0xf0000 */
6189 /* SECOND_DESIRED_ACCESS 0xe0080 */
6190 #define SECOND_DESIRED_ACCESS FILE_READ_ATTRIBUTES| /* 0x80 */ \
6191 READ_CONTROL_ACCESS|WRITE_DAC_ACCESS|\
6192 WRITE_OWNER_ACCESS /* 0xe0000 */
6195 #define THIRD_DESIRED_ACCESS FILE_READ_ATTRIBUTES| /* 0x80 */ \
6196 READ_CONTROL_ACCESS|WRITE_DAC_ACCESS|\
6198 WRITE_OWNER_ACCESS /* */
6202 Test ntcreate calls made by xcopy
6204 static bool run_xcopy(int dummy)
6206 static struct cli_state *cli1;
6207 const char *fname = "\\test.txt";
6208 bool correct = True;
6209 uint16_t fnum1, fnum2;
6212 printf("starting xcopy test\n");
6214 if (!torture_open_connection(&cli1, 0)) {
6218 status = cli_ntcreate(cli1, fname, 0, FIRST_DESIRED_ACCESS,
6219 FILE_ATTRIBUTE_ARCHIVE, FILE_SHARE_NONE,
6220 FILE_OVERWRITE_IF, 0x4044, 0, &fnum1, NULL);
6221 if (!NT_STATUS_IS_OK(status)) {
6222 printf("First open failed - %s\n", nt_errstr(status));
6226 status = cli_ntcreate(cli1, fname, 0, SECOND_DESIRED_ACCESS, 0,
6227 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6228 FILE_OPEN, 0x200000, 0, &fnum2, NULL);
6229 if (!NT_STATUS_IS_OK(status)) {
6230 printf("second open failed - %s\n", nt_errstr(status));
6234 if (!torture_close_connection(cli1)) {
6242 Test rename on files open with share delete and no share delete.
6244 static bool run_rename(int dummy)
6246 static struct cli_state *cli1;
6247 const char *fname = "\\test.txt";
6248 const char *fname1 = "\\test1.txt";
6249 bool correct = True;
6254 printf("starting rename test\n");
6256 if (!torture_open_connection(&cli1, 0)) {
6260 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6261 cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6263 status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
6264 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ,
6265 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
6266 if (!NT_STATUS_IS_OK(status)) {
6267 printf("First open failed - %s\n", nt_errstr(status));
6271 status = cli_rename(cli1, fname, fname1, false);
6272 if (!NT_STATUS_IS_OK(status)) {
6273 printf("First rename failed (SHARE_READ) (this is correct) - %s\n", nt_errstr(status));
6275 printf("First rename succeeded (SHARE_READ) - this should have failed !\n");
6279 status = cli_close(cli1, fnum1);
6280 if (!NT_STATUS_IS_OK(status)) {
6281 printf("close - 1 failed (%s)\n", nt_errstr(status));
6285 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6286 cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6287 status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS, FILE_ATTRIBUTE_NORMAL,
6289 FILE_SHARE_DELETE|FILE_SHARE_NONE,
6291 FILE_SHARE_DELETE|FILE_SHARE_READ,
6293 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
6294 if (!NT_STATUS_IS_OK(status)) {
6295 printf("Second open failed - %s\n", nt_errstr(status));
6299 status = cli_rename(cli1, fname, fname1, false);
6300 if (!NT_STATUS_IS_OK(status)) {
6301 printf("Second rename failed (SHARE_DELETE | SHARE_READ) - this should have succeeded - %s\n", nt_errstr(status));
6304 printf("Second rename succeeded (SHARE_DELETE | SHARE_READ)\n");
6307 status = cli_close(cli1, fnum1);
6308 if (!NT_STATUS_IS_OK(status)) {
6309 printf("close - 2 failed (%s)\n", nt_errstr(status));
6313 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6314 cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6316 status = cli_ntcreate(cli1, fname, 0, READ_CONTROL_ACCESS,
6317 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
6318 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
6319 if (!NT_STATUS_IS_OK(status)) {
6320 printf("Third open failed - %s\n", nt_errstr(status));
6325 status = cli_rename(cli1, fname, fname1, false);
6326 if (!NT_STATUS_IS_OK(status)) {
6327 printf("Third rename failed (SHARE_NONE) - this should have succeeded - %s\n", nt_errstr(status));
6330 printf("Third rename succeeded (SHARE_NONE)\n");
6333 status = cli_close(cli1, fnum1);
6334 if (!NT_STATUS_IS_OK(status)) {
6335 printf("close - 3 failed (%s)\n", nt_errstr(status));
6339 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6340 cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6344 status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
6345 FILE_ATTRIBUTE_NORMAL,
6346 FILE_SHARE_READ | FILE_SHARE_WRITE,
6347 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
6348 if (!NT_STATUS_IS_OK(status)) {
6349 printf("Fourth open failed - %s\n", nt_errstr(status));
6353 status = cli_rename(cli1, fname, fname1, false);
6354 if (!NT_STATUS_IS_OK(status)) {
6355 printf("Fourth rename failed (SHARE_READ | SHARE_WRITE) (this is correct) - %s\n", nt_errstr(status));
6357 printf("Fourth rename succeeded (SHARE_READ | SHARE_WRITE) - this should have failed !\n");
6361 status = cli_close(cli1, fnum1);
6362 if (!NT_STATUS_IS_OK(status)) {
6363 printf("close - 4 failed (%s)\n", nt_errstr(status));
6367 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6368 cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6372 status = cli_ntcreate(cli1, fname, 0, GENERIC_READ_ACCESS,
6373 FILE_ATTRIBUTE_NORMAL,
6374 FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
6375 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
6376 if (!NT_STATUS_IS_OK(status)) {
6377 printf("Fifth open failed - %s\n", nt_errstr(status));
6381 status = cli_rename(cli1, fname, fname1, false);
6382 if (!NT_STATUS_IS_OK(status)) {
6383 printf("Fifth rename failed (SHARE_READ | SHARE_WRITE | SHARE_DELETE) - this should have succeeded - %s ! \n", nt_errstr(status));
6386 printf("Fifth rename succeeded (SHARE_READ | SHARE_WRITE | SHARE_DELETE) (this is correct) - %s\n", nt_errstr(status));
6390 status = cli_close(cli1, fnum1);
6391 if (!NT_STATUS_IS_OK(status)) {
6392 printf("close - 5 failed (%s)\n", nt_errstr(status));
6396 /* Check that the renamed file has FILE_ATTRIBUTE_ARCHIVE. */
6397 status = cli_getatr(cli1, fname1, &attr, NULL, NULL);
6398 if (!NT_STATUS_IS_OK(status)) {
6399 printf("getatr on file %s failed - %s ! \n",
6400 fname1, nt_errstr(status));
6403 if (attr != FILE_ATTRIBUTE_ARCHIVE) {
6404 printf("Renamed file %s has wrong attr 0x%x "
6405 "(should be 0x%x)\n",
6408 (unsigned int)FILE_ATTRIBUTE_ARCHIVE);
6411 printf("Renamed file %s has archive bit set\n", fname1);
6415 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6416 cli_unlink(cli1, fname1, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6418 if (!torture_close_connection(cli1)) {
6426 Test rename into a directory with an ACL denying it.
6428 static bool run_rename_access(int dummy)
6430 static struct cli_state *cli = NULL;
6431 static struct cli_state *posix_cli = NULL;
6432 const char *src = "test.txt";
6433 const char *dname = "dir";
6434 const char *dst = "dir\\test.txt";
6435 const char *dsrc = "test.dir";
6436 const char *ddst = "dir\\test.dir";
6437 uint16_t fnum = (uint16_t)-1;
6438 struct security_descriptor *sd = NULL;
6439 struct security_descriptor *newsd = NULL;
6441 TALLOC_CTX *frame = NULL;
6443 frame = talloc_stackframe();
6444 printf("starting rename access test\n");
6446 /* Windows connection. */
6447 if (!torture_open_connection(&cli, 0)) {
6451 smbXcli_conn_set_sockopt(cli->conn, sockops);
6453 /* Posix connection. */
6454 if (!torture_open_connection(&posix_cli, 0)) {
6458 smbXcli_conn_set_sockopt(posix_cli->conn, sockops);
6460 status = torture_setup_unix_extensions(posix_cli);
6461 if (!NT_STATUS_IS_OK(status)) {
6465 /* Start with a clean slate. */
6466 cli_unlink(cli, src, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6467 cli_unlink(cli, dst, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6468 cli_rmdir(cli, dsrc);
6469 cli_rmdir(cli, ddst);
6470 cli_rmdir(cli, dname);
6473 * Setup the destination directory with a DENY ACE to
6474 * prevent new files within it.
6476 status = cli_ntcreate(cli,
6479 FILE_READ_ATTRIBUTES|READ_CONTROL_ACCESS|
6480 WRITE_DAC_ACCESS|FILE_READ_DATA|
6482 FILE_ATTRIBUTE_DIRECTORY,
6483 FILE_SHARE_READ|FILE_SHARE_WRITE,
6485 FILE_DIRECTORY_FILE,
6489 if (!NT_STATUS_IS_OK(status)) {
6490 printf("Create of %s - %s\n", dname, nt_errstr(status));
6494 status = cli_query_secdesc(cli,
6498 if (!NT_STATUS_IS_OK(status)) {
6499 printf("cli_query_secdesc failed for %s (%s)\n",
6500 dname, nt_errstr(status));
6504 newsd = security_descriptor_dacl_create(frame,
6509 SEC_ACE_TYPE_ACCESS_DENIED,
6510 SEC_DIR_ADD_FILE|SEC_DIR_ADD_SUBDIR,
6513 if (newsd == NULL) {
6516 sd->dacl = security_acl_concatenate(frame,
6519 if (sd->dacl == NULL) {
6522 status = cli_set_secdesc(cli, fnum, sd);
6523 if (!NT_STATUS_IS_OK(status)) {
6524 printf("cli_set_secdesc failed for %s (%s)\n",
6525 dname, nt_errstr(status));
6528 status = cli_close(cli, fnum);
6529 if (!NT_STATUS_IS_OK(status)) {
6530 printf("close failed for %s (%s)\n",
6531 dname, nt_errstr(status));
6534 /* Now go around the back and chmod to 777 via POSIX. */
6535 status = cli_posix_chmod(posix_cli, dname, 0777);
6536 if (!NT_STATUS_IS_OK(status)) {
6537 printf("cli_posix_chmod failed for %s (%s)\n",
6538 dname, nt_errstr(status));
6542 /* Check we can't create a file within dname via Windows. */
6543 status = cli_openx(cli, dst, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
6544 if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
6545 cli_close(posix_cli, fnum);
6546 printf("Create of %s should be ACCESS denied, was %s\n",
6547 dst, nt_errstr(status));
6551 /* Make the sample file/directory. */
6552 status = cli_openx(cli, src, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
6553 if (!NT_STATUS_IS_OK(status)) {
6554 printf("open of %s failed (%s)\n", src, nt_errstr(status));
6557 status = cli_close(cli, fnum);
6558 if (!NT_STATUS_IS_OK(status)) {
6559 printf("cli_close failed (%s)\n", nt_errstr(status));
6563 status = cli_mkdir(cli, dsrc);
6564 if (!NT_STATUS_IS_OK(status)) {
6565 printf("cli_mkdir of %s failed (%s)\n",
6566 dsrc, nt_errstr(status));
6571 * OK - renames of the new file and directory into the
6572 * dst directory should fail.
6575 status = cli_rename(cli, src, dst, false);
6576 if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
6577 printf("rename of %s -> %s should be ACCESS denied, was %s\n",
6578 src, dst, nt_errstr(status));
6581 status = cli_rename(cli, dsrc, ddst, false);
6582 if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
6583 printf("rename of %s -> %s should be ACCESS denied, was %s\n",
6584 src, dst, nt_errstr(status));
6594 torture_close_connection(posix_cli);
6598 if (fnum != (uint16_t)-1) {
6599 cli_close(cli, fnum);
6601 cli_unlink(cli, src,
6602 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6603 cli_unlink(cli, dst,
6604 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6605 cli_rmdir(cli, dsrc);
6606 cli_rmdir(cli, ddst);
6607 cli_rmdir(cli, dname);
6609 torture_close_connection(cli);
6617 Test owner rights ACE.
6619 static bool run_owner_rights(int dummy)
6621 static struct cli_state *cli = NULL;
6622 const char *fname = "owner_rights.txt";
6623 uint16_t fnum = (uint16_t)-1;
6624 struct security_descriptor *sd = NULL;
6625 struct security_descriptor *newsd = NULL;
6627 TALLOC_CTX *frame = NULL;
6629 frame = talloc_stackframe();
6630 printf("starting owner rights test\n");
6632 /* Windows connection. */
6633 if (!torture_open_connection(&cli, 0)) {
6637 smbXcli_conn_set_sockopt(cli->conn, sockops);
6639 /* Start with a clean slate. */
6640 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6642 /* Create the test file. */
6643 /* Now try and open for read and write-dac. */
6644 status = cli_ntcreate(cli,
6648 FILE_ATTRIBUTE_NORMAL,
6649 FILE_SHARE_READ|FILE_SHARE_WRITE|
6656 if (!NT_STATUS_IS_OK(status)) {
6657 printf("Create of %s - %s\n", fname, nt_errstr(status));
6661 /* Get the original SD. */
6662 status = cli_query_secdesc(cli,
6666 if (!NT_STATUS_IS_OK(status)) {
6667 printf("cli_query_secdesc failed for %s (%s)\n",
6668 fname, nt_errstr(status));
6673 * Add an "owner-rights" ACE denying WRITE_DATA,
6674 * and an "owner-rights" ACE allowing READ_DATA.
6677 newsd = security_descriptor_dacl_create(frame,
6682 SEC_ACE_TYPE_ACCESS_DENIED,
6686 SEC_ACE_TYPE_ACCESS_ALLOWED,
6690 if (newsd == NULL) {
6693 sd->dacl = security_acl_concatenate(frame,
6696 if (sd->dacl == NULL) {
6699 status = cli_set_secdesc(cli, fnum, sd);
6700 if (!NT_STATUS_IS_OK(status)) {
6701 printf("cli_set_secdesc failed for %s (%s)\n",
6702 fname, nt_errstr(status));
6705 status = cli_close(cli, fnum);
6706 if (!NT_STATUS_IS_OK(status)) {
6707 printf("close failed for %s (%s)\n",
6708 fname, nt_errstr(status));
6711 fnum = (uint16_t)-1;
6713 /* Try and open for FILE_WRITE_DATA */
6714 status = cli_ntcreate(cli,
6718 FILE_ATTRIBUTE_NORMAL,
6719 FILE_SHARE_READ|FILE_SHARE_WRITE|
6726 if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
6727 printf("Open of %s - %s\n", fname, nt_errstr(status));
6731 /* Now try and open for FILE_READ_DATA */
6732 status = cli_ntcreate(cli,
6736 FILE_ATTRIBUTE_NORMAL,
6737 FILE_SHARE_READ|FILE_SHARE_WRITE|
6744 if (!NT_STATUS_IS_OK(status)) {
6745 printf("Open of %s - %s\n", fname, nt_errstr(status));
6749 status = cli_close(cli, fnum);
6750 if (!NT_STATUS_IS_OK(status)) {
6751 printf("close failed for %s (%s)\n",
6752 fname, nt_errstr(status));
6756 /* Restore clean slate. */
6758 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6760 /* Create the test file. */
6761 status = cli_ntcreate(cli,
6765 FILE_ATTRIBUTE_NORMAL,
6766 FILE_SHARE_READ|FILE_SHARE_WRITE|
6773 if (!NT_STATUS_IS_OK(status)) {
6774 printf("Create of %s - %s\n", fname, nt_errstr(status));
6778 /* Get the original SD. */
6779 status = cli_query_secdesc(cli,
6783 if (!NT_STATUS_IS_OK(status)) {
6784 printf("cli_query_secdesc failed for %s (%s)\n",
6785 fname, nt_errstr(status));
6790 * Add an "owner-rights ACE denying WRITE_DATA,
6791 * and an "owner-rights ACE allowing READ_DATA|WRITE_DATA.
6794 newsd = security_descriptor_dacl_create(frame,
6799 SEC_ACE_TYPE_ACCESS_DENIED,
6803 SEC_ACE_TYPE_ACCESS_ALLOWED,
6804 FILE_READ_DATA|FILE_WRITE_DATA,
6807 if (newsd == NULL) {
6810 sd->dacl = security_acl_concatenate(frame,
6813 if (sd->dacl == NULL) {
6816 status = cli_set_secdesc(cli, fnum, sd);
6817 if (!NT_STATUS_IS_OK(status)) {
6818 printf("cli_set_secdesc failed for %s (%s)\n",
6819 fname, nt_errstr(status));
6822 status = cli_close(cli, fnum);
6823 if (!NT_STATUS_IS_OK(status)) {
6824 printf("close failed for %s (%s)\n",
6825 fname, nt_errstr(status));
6828 fnum = (uint16_t)-1;
6830 /* Try and open for FILE_WRITE_DATA */
6831 status = cli_ntcreate(cli,
6835 FILE_ATTRIBUTE_NORMAL,
6836 FILE_SHARE_READ|FILE_SHARE_WRITE|
6843 if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
6844 printf("Open of %s - %s\n", fname, nt_errstr(status));
6848 /* Now try and open for FILE_READ_DATA */
6849 status = cli_ntcreate(cli,
6853 FILE_ATTRIBUTE_NORMAL,
6854 FILE_SHARE_READ|FILE_SHARE_WRITE|
6861 if (!NT_STATUS_IS_OK(status)) {
6862 printf("Open of %s - %s\n", fname, nt_errstr(status));
6866 status = cli_close(cli, fnum);
6867 if (!NT_STATUS_IS_OK(status)) {
6868 printf("close failed for %s (%s)\n",
6869 fname, nt_errstr(status));
6873 /* Restore clean slate. */
6875 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6878 /* Create the test file. */
6879 status = cli_ntcreate(cli,
6883 FILE_ATTRIBUTE_NORMAL,
6884 FILE_SHARE_READ|FILE_SHARE_WRITE|
6891 if (!NT_STATUS_IS_OK(status)) {
6892 printf("Create of %s - %s\n", fname, nt_errstr(status));
6896 /* Get the original SD. */
6897 status = cli_query_secdesc(cli,
6901 if (!NT_STATUS_IS_OK(status)) {
6902 printf("cli_query_secdesc failed for %s (%s)\n",
6903 fname, nt_errstr(status));
6908 * Add an "authenticated users" ACE allowing READ_DATA,
6909 * add an "owner-rights" denying READ_DATA,
6910 * and an "authenticated users" ACE allowing WRITE_DATA.
6913 newsd = security_descriptor_dacl_create(frame,
6917 SID_NT_AUTHENTICATED_USERS,
6918 SEC_ACE_TYPE_ACCESS_ALLOWED,
6922 SEC_ACE_TYPE_ACCESS_DENIED,
6925 SID_NT_AUTHENTICATED_USERS,
6926 SEC_ACE_TYPE_ACCESS_ALLOWED,
6930 if (newsd == NULL) {
6931 printf("newsd == NULL\n");
6934 sd->dacl = security_acl_concatenate(frame,
6937 if (sd->dacl == NULL) {
6938 printf("sd->dacl == NULL\n");
6941 status = cli_set_secdesc(cli, fnum, sd);
6942 if (!NT_STATUS_IS_OK(status)) {
6943 printf("cli_set_secdesc failed for %s (%s)\n",
6944 fname, nt_errstr(status));
6947 status = cli_close(cli, fnum);
6948 if (!NT_STATUS_IS_OK(status)) {
6949 printf("close failed for %s (%s)\n",
6950 fname, nt_errstr(status));
6953 fnum = (uint16_t)-1;
6955 /* Now try and open for FILE_READ_DATA|FILE_WRITE_DATA */
6956 status = cli_ntcreate(cli,
6959 FILE_READ_DATA|FILE_WRITE_DATA,
6960 FILE_ATTRIBUTE_NORMAL,
6961 FILE_SHARE_READ|FILE_SHARE_WRITE|
6968 if (!NT_STATUS_IS_OK(status)) {
6969 printf("Open of %s - %s\n", fname, nt_errstr(status));
6973 status = cli_close(cli, fnum);
6974 if (!NT_STATUS_IS_OK(status)) {
6975 printf("close failed for %s (%s)\n",
6976 fname, nt_errstr(status));
6980 cli_unlink(cli, fname,
6981 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6989 if (fnum != (uint16_t)-1) {
6990 cli_close(cli, fnum);
6992 cli_unlink(cli, fname,
6993 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
6994 torture_close_connection(cli);
7002 * Test SMB1-specific open with SEC_FLAG_SYSTEM_SECURITY.
7003 * Note this test only works with a user with SeSecurityPrivilege set.
7005 * NB. This is also tested in samba3.base.createx_access
7006 * but this makes it very explicit what we're looking for.
7008 static bool run_smb1_system_security(int dummy)
7010 static struct cli_state *cli = NULL;
7011 const char *fname = "system_security.txt";
7012 uint16_t fnum = (uint16_t)-1;
7014 TALLOC_CTX *frame = NULL;
7016 frame = talloc_stackframe();
7017 printf("starting smb1 system security test\n");
7019 /* SMB1 connection - torture_open_connection() forces this. */
7020 if (!torture_open_connection(&cli, 0)) {
7024 smbXcli_conn_set_sockopt(cli->conn, sockops);
7026 /* Start with a clean slate. */
7027 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7029 /* Create the test file. */
7030 status = cli_ntcreate(cli,
7034 FILE_ATTRIBUTE_NORMAL,
7035 FILE_SHARE_READ|FILE_SHARE_WRITE|
7042 if (!NT_STATUS_IS_OK(status)) {
7043 printf("Create of %s - %s\n", fname, nt_errstr(status));
7047 status = cli_close(cli, fnum);
7049 /* Open with SEC_FLAG_SYSTEM_SECURITY only. */
7051 * On SMB1 this succeeds - SMB2 it fails,
7052 * see the SMB2-SACL test.
7054 status = cli_ntcreate(cli,
7057 SEC_FLAG_SYSTEM_SECURITY,
7058 FILE_ATTRIBUTE_NORMAL,
7059 FILE_SHARE_READ|FILE_SHARE_WRITE|
7066 if (!NT_STATUS_IS_OK(status)) {
7067 printf("Open of %s - %s\n", fname, nt_errstr(status));
7071 status = cli_close(cli, fnum);
7073 cli_unlink(cli, fname,
7074 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7076 torture_close_connection(cli);
7083 if (fnum != (uint16_t)-1) {
7084 cli_close(cli, fnum);
7086 cli_unlink(cli, fname,
7087 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7088 torture_close_connection(cli);
7095 static bool run_pipe_number(int dummy)
7097 struct cli_state *cli1;
7098 const char *pipe_name = "\\SPOOLSS";
7103 printf("starting pipenumber test\n");
7104 if (!torture_open_connection(&cli1, 0)) {
7108 smbXcli_conn_set_sockopt(cli1->conn, sockops);
7110 status = cli_ntcreate(cli1, pipe_name, 0, FILE_READ_DATA,
7111 FILE_ATTRIBUTE_NORMAL,
7112 FILE_SHARE_READ|FILE_SHARE_WRITE,
7113 FILE_OPEN_IF, 0, 0, &fnum, NULL);
7114 if (!NT_STATUS_IS_OK(status)) {
7115 printf("Open of pipe %s failed with error (%s)\n", pipe_name, nt_errstr(status));
7119 printf("\r%6d", num_pipes);
7122 printf("pipe_number test - we can open %d %s pipes.\n", num_pipes, pipe_name );
7123 torture_close_connection(cli1);
7128 Test open mode returns on read-only files.
7130 static bool run_opentest(int dummy)
7132 static struct cli_state *cli1;
7133 static struct cli_state *cli2;
7134 const char *fname = "\\readonly.file";
7135 uint16_t fnum1, fnum2;
7138 bool correct = True;
7142 printf("starting open test\n");
7144 if (!torture_open_connection(&cli1, 0)) {
7148 cli_setatr(cli1, fname, 0, 0);
7149 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7151 smbXcli_conn_set_sockopt(cli1->conn, sockops);
7153 status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
7154 if (!NT_STATUS_IS_OK(status)) {
7155 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
7159 status = cli_close(cli1, fnum1);
7160 if (!NT_STATUS_IS_OK(status)) {
7161 printf("close2 failed (%s)\n", nt_errstr(status));
7165 status = cli_setatr(cli1, fname, FILE_ATTRIBUTE_READONLY, 0);
7166 if (!NT_STATUS_IS_OK(status)) {
7167 printf("cli_setatr failed (%s)\n", nt_errstr(status));
7171 status = cli_openx(cli1, fname, O_RDONLY, DENY_WRITE, &fnum1);
7172 if (!NT_STATUS_IS_OK(status)) {
7173 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
7177 /* This will fail - but the error should be ERRnoaccess, not ERRbadshare. */
7178 status = cli_openx(cli1, fname, O_RDWR, DENY_ALL, &fnum2);
7180 if (check_error(__LINE__, status, ERRDOS, ERRnoaccess,
7181 NT_STATUS_ACCESS_DENIED)) {
7182 printf("correct error code ERRDOS/ERRnoaccess returned\n");
7185 printf("finished open test 1\n");
7187 cli_close(cli1, fnum1);
7189 /* Now try not readonly and ensure ERRbadshare is returned. */
7191 cli_setatr(cli1, fname, 0, 0);
7193 status = cli_openx(cli1, fname, O_RDONLY, DENY_WRITE, &fnum1);
7194 if (!NT_STATUS_IS_OK(status)) {
7195 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
7199 /* This will fail - but the error should be ERRshare. */
7200 status = cli_openx(cli1, fname, O_RDWR, DENY_ALL, &fnum2);
7202 if (check_error(__LINE__, status, ERRDOS, ERRbadshare,
7203 NT_STATUS_SHARING_VIOLATION)) {
7204 printf("correct error code ERRDOS/ERRbadshare returned\n");
7207 status = cli_close(cli1, fnum1);
7208 if (!NT_STATUS_IS_OK(status)) {
7209 printf("close2 failed (%s)\n", nt_errstr(status));
7213 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7215 printf("finished open test 2\n");
7217 /* Test truncate open disposition on file opened for read. */
7218 status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum1);
7219 if (!NT_STATUS_IS_OK(status)) {
7220 printf("(3) open (1) of %s failed (%s)\n", fname, nt_errstr(status));
7224 /* write 20 bytes. */
7226 memset(buf, '\0', 20);
7228 status = cli_writeall(cli1, fnum1, 0, (uint8_t *)buf, 0, 20, NULL);
7229 if (!NT_STATUS_IS_OK(status)) {
7230 printf("write failed (%s)\n", nt_errstr(status));
7234 status = cli_close(cli1, fnum1);
7235 if (!NT_STATUS_IS_OK(status)) {
7236 printf("(3) close1 failed (%s)\n", nt_errstr(status));
7240 /* Ensure size == 20. */
7241 status = cli_getatr(cli1, fname, NULL, &fsize, NULL);
7242 if (!NT_STATUS_IS_OK(status)) {
7243 printf("(3) getatr failed (%s)\n", nt_errstr(status));
7248 printf("(3) file size != 20\n");
7252 /* Now test if we can truncate a file opened for readonly. */
7253 status = cli_openx(cli1, fname, O_RDONLY|O_TRUNC, DENY_NONE, &fnum1);
7254 if (!NT_STATUS_IS_OK(status)) {
7255 printf("(3) open (2) of %s failed (%s)\n", fname, nt_errstr(status));
7259 status = cli_close(cli1, fnum1);
7260 if (!NT_STATUS_IS_OK(status)) {
7261 printf("close2 failed (%s)\n", nt_errstr(status));
7265 /* Ensure size == 0. */
7266 status = cli_getatr(cli1, fname, NULL, &fsize, NULL);
7267 if (!NT_STATUS_IS_OK(status)) {
7268 printf("(3) getatr failed (%s)\n", nt_errstr(status));
7273 printf("(3) file size != 0\n");
7276 printf("finished open test 3\n");
7278 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7280 printf("Do ctemp tests\n");
7281 status = cli_ctemp(cli1, talloc_tos(), "\\", &fnum1, &tmp_path);
7282 if (!NT_STATUS_IS_OK(status)) {
7283 printf("ctemp failed (%s)\n", nt_errstr(status));
7287 printf("ctemp gave path %s\n", tmp_path);
7288 status = cli_close(cli1, fnum1);
7289 if (!NT_STATUS_IS_OK(status)) {
7290 printf("close of temp failed (%s)\n", nt_errstr(status));
7293 status = cli_unlink(cli1, tmp_path, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7294 if (!NT_STATUS_IS_OK(status)) {
7295 printf("unlink of temp failed (%s)\n", nt_errstr(status));
7298 /* Test the non-io opens... */
7300 if (!torture_open_connection(&cli2, 1)) {
7304 cli_setatr(cli2, fname, 0, 0);
7305 cli_unlink(cli2, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7307 smbXcli_conn_set_sockopt(cli2->conn, sockops);
7309 printf("TEST #1 testing 2 non-io opens (no delete)\n");
7310 status = cli_ntcreate(cli1, fname, 0, FILE_READ_ATTRIBUTES,
7311 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7312 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
7313 if (!NT_STATUS_IS_OK(status)) {
7314 printf("TEST #1 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
7318 status = cli_ntcreate(cli2, fname, 0, FILE_READ_ATTRIBUTES,
7319 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7320 FILE_OPEN_IF, 0, 0, &fnum2, NULL);
7321 if (!NT_STATUS_IS_OK(status)) {
7322 printf("TEST #1 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
7326 status = cli_close(cli1, fnum1);
7327 if (!NT_STATUS_IS_OK(status)) {
7328 printf("TEST #1 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
7332 status = cli_close(cli2, fnum2);
7333 if (!NT_STATUS_IS_OK(status)) {
7334 printf("TEST #1 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
7338 printf("non-io open test #1 passed.\n");
7340 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7342 printf("TEST #2 testing 2 non-io opens (first with delete)\n");
7344 status = cli_ntcreate(cli1, fname, 0,
7345 DELETE_ACCESS|FILE_READ_ATTRIBUTES,
7346 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7347 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
7348 if (!NT_STATUS_IS_OK(status)) {
7349 printf("TEST #2 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
7353 status = cli_ntcreate(cli2, fname, 0, FILE_READ_ATTRIBUTES,
7354 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7355 FILE_OPEN_IF, 0, 0, &fnum2, NULL);
7356 if (!NT_STATUS_IS_OK(status)) {
7357 printf("TEST #2 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
7361 status = cli_close(cli1, fnum1);
7362 if (!NT_STATUS_IS_OK(status)) {
7363 printf("TEST #2 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
7367 status = cli_close(cli2, fnum2);
7368 if (!NT_STATUS_IS_OK(status)) {
7369 printf("TEST #2 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
7373 printf("non-io open test #2 passed.\n");
7375 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7377 printf("TEST #3 testing 2 non-io opens (second with delete)\n");
7379 status = cli_ntcreate(cli1, fname, 0, FILE_READ_ATTRIBUTES,
7380 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7381 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
7382 if (!NT_STATUS_IS_OK(status)) {
7383 printf("TEST #3 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
7387 status = cli_ntcreate(cli2, fname, 0,
7388 DELETE_ACCESS|FILE_READ_ATTRIBUTES,
7389 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7390 FILE_OPEN_IF, 0, 0, &fnum2, NULL);
7391 if (!NT_STATUS_IS_OK(status)) {
7392 printf("TEST #3 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
7396 status = cli_close(cli1, fnum1);
7397 if (!NT_STATUS_IS_OK(status)) {
7398 printf("TEST #3 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
7402 status = cli_close(cli2, fnum2);
7403 if (!NT_STATUS_IS_OK(status)) {
7404 printf("TEST #3 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
7408 printf("non-io open test #3 passed.\n");
7410 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7412 printf("TEST #4 testing 2 non-io opens (both with delete)\n");
7414 status = cli_ntcreate(cli1, fname, 0,
7415 DELETE_ACCESS|FILE_READ_ATTRIBUTES,
7416 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7417 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
7418 if (!NT_STATUS_IS_OK(status)) {
7419 printf("TEST #4 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
7423 status = cli_ntcreate(cli2, fname, 0,
7424 DELETE_ACCESS|FILE_READ_ATTRIBUTES,
7425 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7426 FILE_OPEN_IF, 0, 0, &fnum2, NULL);
7427 if (NT_STATUS_IS_OK(status)) {
7428 printf("TEST #4 open 2 of %s SUCCEEDED - should have failed (%s)\n", fname, nt_errstr(status));
7432 printf("TEST #4 open 2 of %s gave %s (correct error should be %s)\n", fname, nt_errstr(status), "sharing violation");
7434 status = cli_close(cli1, fnum1);
7435 if (!NT_STATUS_IS_OK(status)) {
7436 printf("TEST #4 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
7440 printf("non-io open test #4 passed.\n");
7442 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7444 printf("TEST #5 testing 2 non-io opens (both with delete - both with file share delete)\n");
7446 status = cli_ntcreate(cli1, fname, 0,
7447 DELETE_ACCESS|FILE_READ_ATTRIBUTES,
7448 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_DELETE,
7449 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
7450 if (!NT_STATUS_IS_OK(status)) {
7451 printf("TEST #5 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
7455 status = cli_ntcreate(cli2, fname, 0,
7456 DELETE_ACCESS|FILE_READ_ATTRIBUTES,
7457 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_DELETE,
7458 FILE_OPEN_IF, 0, 0, &fnum2, NULL);
7459 if (!NT_STATUS_IS_OK(status)) {
7460 printf("TEST #5 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
7464 status = cli_close(cli1, fnum1);
7465 if (!NT_STATUS_IS_OK(status)) {
7466 printf("TEST #5 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
7470 status = cli_close(cli2, fnum2);
7471 if (!NT_STATUS_IS_OK(status)) {
7472 printf("TEST #5 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
7476 printf("non-io open test #5 passed.\n");
7478 printf("TEST #6 testing 1 non-io open, one io open\n");
7480 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7482 status = cli_ntcreate(cli1, fname, 0, FILE_READ_DATA,
7483 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7484 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
7485 if (!NT_STATUS_IS_OK(status)) {
7486 printf("TEST #6 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
7490 status = cli_ntcreate(cli2, fname, 0, FILE_READ_ATTRIBUTES,
7491 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ,
7492 FILE_OPEN_IF, 0, 0, &fnum2, NULL);
7493 if (!NT_STATUS_IS_OK(status)) {
7494 printf("TEST #6 open 2 of %s failed (%s)\n", fname, nt_errstr(status));
7498 status = cli_close(cli1, fnum1);
7499 if (!NT_STATUS_IS_OK(status)) {
7500 printf("TEST #6 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
7504 status = cli_close(cli2, fnum2);
7505 if (!NT_STATUS_IS_OK(status)) {
7506 printf("TEST #6 close 2 of %s failed (%s)\n", fname, nt_errstr(status));
7510 printf("non-io open test #6 passed.\n");
7512 printf("TEST #7 testing 1 non-io open, one io open with delete\n");
7514 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7516 status = cli_ntcreate(cli1, fname, 0, FILE_READ_DATA,
7517 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_NONE,
7518 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
7519 if (!NT_STATUS_IS_OK(status)) {
7520 printf("TEST #7 open 1 of %s failed (%s)\n", fname, nt_errstr(status));
7524 status = cli_ntcreate(cli2, fname, 0,
7525 DELETE_ACCESS|FILE_READ_ATTRIBUTES,
7526 FILE_ATTRIBUTE_NORMAL,
7527 FILE_SHARE_READ|FILE_SHARE_DELETE,
7528 FILE_OPEN_IF, 0, 0, &fnum2, NULL);
7529 if (NT_STATUS_IS_OK(status)) {
7530 printf("TEST #7 open 2 of %s SUCCEEDED - should have failed (%s)\n", fname, nt_errstr(status));
7534 printf("TEST #7 open 2 of %s gave %s (correct error should be %s)\n", fname, nt_errstr(status), "sharing violation");
7536 status = cli_close(cli1, fnum1);
7537 if (!NT_STATUS_IS_OK(status)) {
7538 printf("TEST #7 close 1 of %s failed (%s)\n", fname, nt_errstr(status));
7542 printf("non-io open test #7 passed.\n");
7544 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
7546 printf("TEST #8 testing open without WRITE_ATTRIBUTES, updating close write time.\n");
7547 status = cli_ntcreate(cli1, fname, 0, FILE_WRITE_DATA, FILE_ATTRIBUTE_NORMAL,
7548 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
7549 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
7550 if (!NT_STATUS_IS_OK(status)) {
7551 printf("TEST #8 open of %s failed (%s)\n", fname, nt_errstr(status));
7556 /* Write to ensure we have to update the file time. */
7557 status = cli_writeall(cli1, fnum1, 0, (const uint8_t *)"TEST DATA\n", 0, 10,
7559 if (!NT_STATUS_IS_OK(status)) {
7560 printf("TEST #8 cli_write failed: %s\n", nt_errstr(status));
7565 status = cli_close(cli1, fnum1);
7566 if (!NT_STATUS_IS_OK(status)) {
7567 printf("TEST #8 close of %s failed (%s)\n", fname, nt_errstr(status));
7573 if (!torture_close_connection(cli1)) {
7576 if (!torture_close_connection(cli2)) {
7583 NTSTATUS torture_setup_unix_extensions(struct cli_state *cli)
7585 uint16_t major, minor;
7586 uint32_t caplow, caphigh;
7589 if (!SERVER_HAS_UNIX_CIFS(cli)) {
7590 printf("Server doesn't support UNIX CIFS extensions.\n");
7591 return NT_STATUS_NOT_SUPPORTED;
7594 status = cli_unix_extensions_version(cli, &major, &minor, &caplow,
7596 if (!NT_STATUS_IS_OK(status)) {
7597 printf("Server didn't return UNIX CIFS extensions: %s\n",
7602 status = cli_set_unix_extensions_capabilities(cli, major, minor,
7604 if (!NT_STATUS_IS_OK(status)) {
7605 printf("Server doesn't support setting UNIX CIFS extensions: "
7606 "%s.\n", nt_errstr(status));
7610 return NT_STATUS_OK;
7614 Test POSIX open /mkdir calls.
7616 static bool run_simple_posix_open_test(int dummy)
7618 static struct cli_state *cli1;
7619 const char *fname = "posix:file";
7620 const char *hname = "posix:hlink";
7621 const char *sname = "posix:symlink";
7622 const char *dname = "posix:dir";
7624 char *target = NULL;
7625 uint16_t fnum1 = (uint16_t)-1;
7626 SMB_STRUCT_STAT sbuf;
7627 bool correct = false;
7630 const char *fname_windows = "windows_file";
7631 uint16_t fnum2 = (uint16_t)-1;
7633 printf("Starting simple POSIX open test\n");
7635 if (!torture_open_connection(&cli1, 0)) {
7639 smbXcli_conn_set_sockopt(cli1->conn, sockops);
7641 status = torture_setup_unix_extensions(cli1);
7642 if (!NT_STATUS_IS_OK(status)) {
7646 cli_setatr(cli1, fname, 0, 0);
7647 cli_posix_unlink(cli1, fname);
7648 cli_setatr(cli1, dname, 0, 0);
7649 cli_posix_rmdir(cli1, dname);
7650 cli_setatr(cli1, hname, 0, 0);
7651 cli_posix_unlink(cli1, hname);
7652 cli_setatr(cli1, sname, 0, 0);
7653 cli_posix_unlink(cli1, sname);
7654 cli_setatr(cli1, fname_windows, 0, 0);
7655 cli_posix_unlink(cli1, fname_windows);
7657 /* Create a directory. */
7658 status = cli_posix_mkdir(cli1, dname, 0777);
7659 if (!NT_STATUS_IS_OK(status)) {
7660 printf("POSIX mkdir of %s failed (%s)\n", dname, nt_errstr(status));
7664 status = cli_posix_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL,
7666 if (!NT_STATUS_IS_OK(status)) {
7667 printf("POSIX create of %s failed (%s)\n", fname, nt_errstr(status));
7671 /* Test ftruncate - set file size. */
7672 status = cli_ftruncate(cli1, fnum1, 1000);
7673 if (!NT_STATUS_IS_OK(status)) {
7674 printf("ftruncate failed (%s)\n", nt_errstr(status));
7678 /* Ensure st_size == 1000 */
7679 status = cli_posix_stat(cli1, fname, &sbuf);
7680 if (!NT_STATUS_IS_OK(status)) {
7681 printf("stat failed (%s)\n", nt_errstr(status));
7685 if (sbuf.st_ex_size != 1000) {
7686 printf("ftruncate - stat size (%u) != 1000\n", (unsigned int)sbuf.st_ex_size);
7690 /* Ensure st_mode == 0600 */
7691 if ((sbuf.st_ex_mode & 07777) != 0600) {
7692 printf("posix_open - bad permissions 0%o != 0600\n",
7693 (unsigned int)(sbuf.st_ex_mode & 07777));
7697 /* Test ftruncate - set file size back to zero. */
7698 status = cli_ftruncate(cli1, fnum1, 0);
7699 if (!NT_STATUS_IS_OK(status)) {
7700 printf("ftruncate failed (%s)\n", nt_errstr(status));
7704 status = cli_close(cli1, fnum1);
7705 if (!NT_STATUS_IS_OK(status)) {
7706 printf("close failed (%s)\n", nt_errstr(status));
7710 /* Now open the file again for read only. */
7711 status = cli_posix_open(cli1, fname, O_RDONLY, 0, &fnum1);
7712 if (!NT_STATUS_IS_OK(status)) {
7713 printf("POSIX open of %s failed (%s)\n", fname, nt_errstr(status));
7717 /* Now unlink while open. */
7718 status = cli_posix_unlink(cli1, fname);
7719 if (!NT_STATUS_IS_OK(status)) {
7720 printf("POSIX unlink of %s failed (%s)\n", fname, nt_errstr(status));
7724 status = cli_close(cli1, fnum1);
7725 if (!NT_STATUS_IS_OK(status)) {
7726 printf("close(2) failed (%s)\n", nt_errstr(status));
7730 /* Ensure the file has gone. */
7731 status = cli_posix_open(cli1, fname, O_RDONLY, 0, &fnum1);
7732 if (NT_STATUS_IS_OK(status)) {
7733 printf("POSIX open of %s succeeded, should have been deleted.\n", fname);
7737 /* Create again to test open with O_TRUNC. */
7738 status = cli_posix_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL, 0600, &fnum1);
7739 if (!NT_STATUS_IS_OK(status)) {
7740 printf("POSIX create of %s failed (%s)\n", fname, nt_errstr(status));
7744 /* Test ftruncate - set file size. */
7745 status = cli_ftruncate(cli1, fnum1, 1000);
7746 if (!NT_STATUS_IS_OK(status)) {
7747 printf("ftruncate failed (%s)\n", nt_errstr(status));
7751 /* Ensure st_size == 1000 */
7752 status = cli_posix_stat(cli1, fname, &sbuf);
7753 if (!NT_STATUS_IS_OK(status)) {
7754 printf("stat failed (%s)\n", nt_errstr(status));
7758 if (sbuf.st_ex_size != 1000) {
7759 printf("ftruncate - stat size (%u) != 1000\n", (unsigned int)sbuf.st_ex_size);
7763 status = cli_close(cli1, fnum1);
7764 if (!NT_STATUS_IS_OK(status)) {
7765 printf("close(2) failed (%s)\n", nt_errstr(status));
7769 /* Re-open with O_TRUNC. */
7770 status = cli_posix_open(cli1, fname, O_WRONLY|O_TRUNC, 0600, &fnum1);
7771 if (!NT_STATUS_IS_OK(status)) {
7772 printf("POSIX create of %s failed (%s)\n", fname, nt_errstr(status));
7776 /* Ensure st_size == 0 */
7777 status = cli_posix_stat(cli1, fname, &sbuf);
7778 if (!NT_STATUS_IS_OK(status)) {
7779 printf("stat failed (%s)\n", nt_errstr(status));
7783 if (sbuf.st_ex_size != 0) {
7784 printf("O_TRUNC - stat size (%u) != 0\n", (unsigned int)sbuf.st_ex_size);
7788 status = cli_close(cli1, fnum1);
7789 if (!NT_STATUS_IS_OK(status)) {
7790 printf("close failed (%s)\n", nt_errstr(status));
7794 status = cli_posix_unlink(cli1, fname);
7795 if (!NT_STATUS_IS_OK(status)) {
7796 printf("POSIX unlink of %s failed (%s)\n", fname, nt_errstr(status));
7800 status = cli_posix_open(cli1, dname, O_RDONLY, 0, &fnum1);
7801 if (!NT_STATUS_IS_OK(status)) {
7802 printf("POSIX open directory O_RDONLY of %s failed (%s)\n",
7803 dname, nt_errstr(status));
7807 cli_close(cli1, fnum1);
7809 /* What happens when we try and POSIX open a directory for write ? */
7810 status = cli_posix_open(cli1, dname, O_RDWR, 0, &fnum1);
7811 if (NT_STATUS_IS_OK(status)) {
7812 printf("POSIX open of directory %s succeeded, "
7813 "should have failed.\n",
7817 if (!check_both_error(__LINE__, status, ERRDOS, EISDIR,
7818 NT_STATUS_FILE_IS_A_DIRECTORY)) {
7823 /* Create the file. */
7824 status = cli_posix_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL,
7826 if (!NT_STATUS_IS_OK(status)) {
7827 printf("POSIX create of %s failed (%s)\n", fname, nt_errstr(status));
7831 /* Write some data into it. */
7832 status = cli_writeall(cli1, fnum1, 0, (const uint8_t *)"TEST DATA\n", 0, 10,
7834 if (!NT_STATUS_IS_OK(status)) {
7835 printf("cli_write failed: %s\n", nt_errstr(status));
7839 cli_close(cli1, fnum1);
7841 /* Now create a hardlink. */
7842 status = cli_posix_hardlink(cli1, fname, hname);
7843 if (!NT_STATUS_IS_OK(status)) {
7844 printf("POSIX hardlink of %s failed (%s)\n", hname, nt_errstr(status));
7848 /* Now create a symlink. */
7849 status = cli_posix_symlink(cli1, fname, sname);
7850 if (!NT_STATUS_IS_OK(status)) {
7851 printf("POSIX symlink of %s failed (%s)\n", sname, nt_errstr(status));
7855 /* Open the hardlink for read. */
7856 status = cli_posix_open(cli1, hname, O_RDONLY, 0, &fnum1);
7857 if (!NT_STATUS_IS_OK(status)) {
7858 printf("POSIX open of %s failed (%s)\n", hname, nt_errstr(status));
7862 status = cli_read(cli1, fnum1, buf, 0, 10, &nread);
7863 if (!NT_STATUS_IS_OK(status)) {
7864 printf("POSIX read of %s failed (%s)\n", hname,
7867 } else if (nread != 10) {
7868 printf("POSIX read of %s failed. Received %ld, expected %d\n",
7869 hname, (unsigned long)nread, 10);
7873 if (memcmp(buf, "TEST DATA\n", 10)) {
7874 printf("invalid data read from hardlink\n");
7878 /* Do a POSIX lock/unlock. */
7879 status = cli_posix_lock(cli1, fnum1, 0, 100, true, READ_LOCK);
7880 if (!NT_STATUS_IS_OK(status)) {
7881 printf("POSIX lock failed %s\n", nt_errstr(status));
7885 /* Punch a hole in the locked area. */
7886 status = cli_posix_unlock(cli1, fnum1, 10, 80);
7887 if (!NT_STATUS_IS_OK(status)) {
7888 printf("POSIX unlock failed %s\n", nt_errstr(status));
7892 cli_close(cli1, fnum1);
7894 /* Open the symlink for read - this should fail. A POSIX
7895 client should not be doing opens on a symlink. */
7896 status = cli_posix_open(cli1, sname, O_RDONLY, 0, &fnum1);
7897 if (NT_STATUS_IS_OK(status)) {
7898 printf("POSIX open of %s succeeded (should have failed)\n", sname);
7901 if (!check_both_error(__LINE__, status, ERRDOS, ERRbadpath,
7902 NT_STATUS_OBJECT_PATH_NOT_FOUND)) {
7903 printf("POSIX open of %s should have failed "
7904 "with NT_STATUS_OBJECT_PATH_NOT_FOUND, "
7905 "failed with %s instead.\n",
7906 sname, nt_errstr(status));
7911 status = cli_posix_readlink(cli1, sname, talloc_tos(), &target);
7912 if (!NT_STATUS_IS_OK(status)) {
7913 printf("POSIX readlink on %s failed (%s)\n", sname, nt_errstr(status));
7917 if (strcmp(target, fname) != 0) {
7918 printf("POSIX readlink on %s failed to match name %s (read %s)\n",
7919 sname, fname, target);
7923 status = cli_posix_rmdir(cli1, dname);
7924 if (!NT_STATUS_IS_OK(status)) {
7925 printf("POSIX rmdir failed (%s)\n", nt_errstr(status));
7929 /* Check directory opens with a specific permission. */
7930 status = cli_posix_mkdir(cli1, dname, 0700);
7931 if (!NT_STATUS_IS_OK(status)) {
7932 printf("POSIX mkdir of %s failed (%s)\n", dname, nt_errstr(status));
7936 /* Ensure st_mode == 0700 */
7937 status = cli_posix_stat(cli1, dname, &sbuf);
7938 if (!NT_STATUS_IS_OK(status)) {
7939 printf("stat failed (%s)\n", nt_errstr(status));
7943 if ((sbuf.st_ex_mode & 07777) != 0700) {
7944 printf("posix_mkdir - bad permissions 0%o != 0700\n",
7945 (unsigned int)(sbuf.st_ex_mode & 07777));
7950 * Now create a Windows file, and attempt a POSIX unlink.
7951 * This should fail with a sharing violation but due to:
7953 * [Bug 9571] Unlink after open causes smbd to panic
7955 * ensure we've fixed the lock ordering violation.
7958 status = cli_ntcreate(cli1, fname_windows, 0,
7959 FILE_READ_DATA|FILE_WRITE_DATA, 0,
7960 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
7962 0x0, 0x0, &fnum2, NULL);
7963 if (!NT_STATUS_IS_OK(status)) {
7964 printf("Windows create of %s failed (%s)\n", fname_windows,
7969 /* Now try posix_unlink. */
7970 status = cli_posix_unlink(cli1, fname_windows);
7971 if (!NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
7972 printf("POSIX unlink of %s should fail "
7973 "with NT_STATUS_SHARING_VIOLATION "
7974 "got %s instead !\n",
7980 cli_close(cli1, fnum2);
7982 printf("Simple POSIX open test passed\n");
7987 if (fnum1 != (uint16_t)-1) {
7988 cli_close(cli1, fnum1);
7989 fnum1 = (uint16_t)-1;
7992 if (fnum2 != (uint16_t)-1) {
7993 cli_close(cli1, fnum2);
7994 fnum2 = (uint16_t)-1;
7997 cli_setatr(cli1, sname, 0, 0);
7998 cli_posix_unlink(cli1, sname);
7999 cli_setatr(cli1, hname, 0, 0);
8000 cli_posix_unlink(cli1, hname);
8001 cli_setatr(cli1, fname, 0, 0);
8002 cli_posix_unlink(cli1, fname);
8003 cli_setatr(cli1, dname, 0, 0);
8004 cli_posix_rmdir(cli1, dname);
8005 cli_setatr(cli1, fname_windows, 0, 0);
8006 cli_posix_unlink(cli1, fname_windows);
8008 if (!torture_close_connection(cli1)) {
8016 Test POSIX and Windows ACLs are rejected on symlinks.
8018 static bool run_acl_symlink_test(int dummy)
8020 static struct cli_state *cli;
8021 const char *fname = "posix_file";
8022 const char *sname = "posix_symlink";
8023 uint16_t fnum = (uint16_t)-1;
8024 bool correct = false;
8026 char *posix_acl = NULL;
8027 size_t posix_acl_len = 0;
8028 char *posix_acl_sym = NULL;
8029 size_t posix_acl_len_sym = 0;
8030 struct security_descriptor *sd = NULL;
8031 struct security_descriptor *sd_sym = NULL;
8032 TALLOC_CTX *frame = NULL;
8034 frame = talloc_stackframe();
8036 printf("Starting acl symlink test\n");
8038 if (!torture_open_connection(&cli, 0)) {
8043 smbXcli_conn_set_sockopt(cli->conn, sockops);
8045 status = torture_setup_unix_extensions(cli);
8046 if (!NT_STATUS_IS_OK(status)) {
8051 cli_setatr(cli, fname, 0, 0);
8052 cli_posix_unlink(cli, fname);
8053 cli_setatr(cli, sname, 0, 0);
8054 cli_posix_unlink(cli, sname);
8056 status = cli_ntcreate(cli,
8059 READ_CONTROL_ACCESS,
8061 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
8068 if (!NT_STATUS_IS_OK(status)) {
8069 printf("cli_ntcreate of %s failed (%s)\n",
8075 /* Get the Windows ACL on the file. */
8076 status = cli_query_secdesc(cli,
8080 if (!NT_STATUS_IS_OK(status)) {
8081 printf("cli_query_secdesc failed (%s)\n",
8086 /* Get the POSIX ACL on the file. */
8087 status = cli_posix_getacl(cli,
8093 if (!NT_STATUS_IS_OK(status)) {
8094 printf("cli_posix_getacl failed (%s)\n",
8099 status = cli_close(cli, fnum);
8100 if (!NT_STATUS_IS_OK(status)) {
8101 printf("close failed (%s)\n", nt_errstr(status));
8104 fnum = (uint16_t)-1;
8106 /* Now create a symlink. */
8107 status = cli_posix_symlink(cli, fname, sname);
8108 if (!NT_STATUS_IS_OK(status)) {
8109 printf("cli_posix_symlink of %s -> %s failed (%s)\n",
8116 /* Open a handle on the symlink for SD set/get should fail. */
8117 status = cli_ntcreate(cli,
8120 READ_CONTROL_ACCESS|SEC_STD_WRITE_DAC,
8122 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
8129 if (NT_STATUS_IS_OK(status)) {
8130 printf("Symlink open for getsd/setsd of %s "
8131 "succeeded (should fail)\n",
8136 /* Open a handle on the symlink. */
8137 status = cli_ntcreate(cli,
8140 FILE_READ_ATTRIBUTES|FILE_WRITE_ATTRIBUTES,
8142 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
8149 if (!NT_STATUS_IS_OK(status)) {
8150 printf("cli_posix_open of %s failed (%s)\n",
8156 /* Get the Windows ACL on the symlink handle. Should fail */
8157 status = cli_query_secdesc(cli,
8162 if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
8163 printf("cli_query_secdesc on a symlink gave %s. "
8164 "Should be NT_STATUS_ACCESS_DENIED.\n",
8169 /* Get the POSIX ACL on the symlink pathname. Should fail. */
8170 status = cli_posix_getacl(cli,
8176 if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
8177 printf("cli_posix_getacl on a symlink gave %s. "
8178 "Should be NT_STATUS_ACCESS_DENIED.\n",
8183 /* Set the Windows ACL on the symlink handle. Should fail */
8184 status = cli_set_security_descriptor(cli,
8189 if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
8190 printf("cli_query_secdesc on a symlink gave %s. "
8191 "Should be NT_STATUS_ACCESS_DENIED.\n",
8196 /* Set the POSIX ACL on the symlink pathname. Should fail. */
8197 status = cli_posix_setacl(cli,
8202 if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
8203 printf("cli_posix_setacl on a symlink gave %s. "
8204 "Should be NT_STATUS_ACCESS_DENIED.\n",
8209 printf("ACL symlink test passed\n");
8214 if (fnum != (uint16_t)-1) {
8215 cli_close(cli, fnum);
8216 fnum = (uint16_t)-1;
8219 cli_setatr(cli, sname, 0, 0);
8220 cli_posix_unlink(cli, sname);
8221 cli_setatr(cli, fname, 0, 0);
8222 cli_posix_unlink(cli, fname);
8224 if (!torture_close_connection(cli)) {
8233 Test POSIX can delete a file containing streams.
8235 static bool run_posix_stream_delete(int dummy)
8237 struct cli_state *cli1 = NULL;
8238 struct cli_state *cli2 = NULL;
8239 const char *fname = "streamfile";
8240 const char *stream_fname = "streamfile:Zone.Identifier:$DATA";
8241 uint16_t fnum1 = (uint16_t)-1;
8242 bool correct = false;
8244 TALLOC_CTX *frame = NULL;
8246 frame = talloc_stackframe();
8248 printf("Starting POSIX stream delete test\n");
8250 if (!torture_open_connection(&cli1, 0) ||
8251 !torture_open_connection(&cli2, 1)) {
8256 smbXcli_conn_set_sockopt(cli1->conn, sockops);
8257 smbXcli_conn_set_sockopt(cli2->conn, sockops);
8259 status = torture_setup_unix_extensions(cli2);
8260 if (!NT_STATUS_IS_OK(status)) {
8264 cli_setatr(cli1, fname, 0, 0);
8265 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
8267 /* Create the file. */
8268 status = cli_ntcreate(cli1,
8271 READ_CONTROL_ACCESS,
8273 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
8280 if (!NT_STATUS_IS_OK(status)) {
8281 printf("cli_ntcreate of %s failed (%s)\n",
8287 status = cli_close(cli1, fnum1);
8288 if (!NT_STATUS_IS_OK(status)) {
8289 printf("cli_close of %s failed (%s)\n",
8294 fnum1 = (uint16_t)-1;
8296 /* Now create the stream. */
8297 status = cli_ntcreate(cli1,
8302 FILE_SHARE_READ|FILE_SHARE_WRITE,
8309 if (!NT_STATUS_IS_OK(status)) {
8310 printf("cli_ntcreate of %s failed (%s)\n",
8316 /* Leave the stream handle open... */
8318 /* POSIX unlink should fail. */
8319 status = cli_posix_unlink(cli2, fname);
8320 if (NT_STATUS_IS_OK(status)) {
8321 printf("cli_posix_unlink of %s succeeded, should have failed\n",
8326 if (!NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
8327 printf("cli_posix_unlink of %s failed with (%s) "
8328 "should have been NT_STATUS_SHARING_VIOLATION\n",
8334 /* Close the stream handle. */
8335 status = cli_close(cli1, fnum1);
8336 if (!NT_STATUS_IS_OK(status)) {
8337 printf("cli_close of %s failed (%s)\n",
8342 fnum1 = (uint16_t)-1;
8344 /* POSIX unlink after stream handle closed should succeed. */
8345 status = cli_posix_unlink(cli2, fname);
8346 if (!NT_STATUS_IS_OK(status)) {
8347 printf("cli_posix_unlink of %s failed (%s)\n",
8353 printf("POSIX stream delete test passed\n");
8358 if (fnum1 != (uint16_t)-1) {
8359 cli_close(cli1, fnum1);
8360 fnum1 = (uint16_t)-1;
8363 cli_setatr(cli1, fname, 0, 0);
8364 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
8366 if (!torture_close_connection(cli1)) {
8369 if (!torture_close_connection(cli2)) {
8378 Test setting EA's are rejected on symlinks.
8380 static bool run_ea_symlink_test(int dummy)
8382 static struct cli_state *cli;
8383 const char *fname = "posix_file_ea";
8384 const char *sname = "posix_symlink_ea";
8385 const char *ea_name = "testea_name";
8386 const char *ea_value = "testea_value";
8387 uint16_t fnum = (uint16_t)-1;
8388 bool correct = false;
8391 struct ea_struct *eas = NULL;
8392 TALLOC_CTX *frame = NULL;
8394 frame = talloc_stackframe();
8396 printf("Starting EA symlink test\n");
8398 if (!torture_open_connection(&cli, 0)) {
8403 smbXcli_conn_set_sockopt(cli->conn, sockops);
8405 status = torture_setup_unix_extensions(cli);
8406 if (!NT_STATUS_IS_OK(status)) {
8411 cli_setatr(cli, fname, 0, 0);
8412 cli_posix_unlink(cli, fname);
8413 cli_setatr(cli, sname, 0, 0);
8414 cli_posix_unlink(cli, sname);
8416 status = cli_ntcreate(cli,
8419 READ_CONTROL_ACCESS,
8421 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
8428 if (!NT_STATUS_IS_OK(status)) {
8429 printf("cli_ntcreate of %s failed (%s)\n",
8435 status = cli_close(cli, fnum);
8436 if (!NT_STATUS_IS_OK(status)) {
8437 printf("close failed (%s)\n",
8441 fnum = (uint16_t)-1;
8443 /* Set an EA on the path. */
8444 status = cli_set_ea_path(cli,
8448 strlen(ea_value)+1);
8450 if (!NT_STATUS_IS_OK(status)) {
8451 printf("cli_set_ea_path failed (%s)\n",
8456 /* Now create a symlink. */
8457 status = cli_posix_symlink(cli, fname, sname);
8458 if (!NT_STATUS_IS_OK(status)) {
8459 printf("cli_posix_symlink of %s -> %s failed (%s)\n",
8466 /* Get the EA list on the path. Should return value set. */
8467 status = cli_get_ea_list_path(cli,
8473 if (!NT_STATUS_IS_OK(status)) {
8474 printf("cli_get_ea_list_path failed (%s)\n",
8479 /* Ensure the EA we set is there. */
8480 for (i=0; i<num_eas; i++) {
8481 if (strcmp(eas[i].name, ea_name) == 0 &&
8482 eas[i].value.length == strlen(ea_value)+1 &&
8483 memcmp(eas[i].value.data,
8485 eas[i].value.length) == 0) {
8491 printf("Didn't find EA on pathname %s\n",
8499 /* Get the EA list on the symlink. Should return empty list. */
8500 status = cli_get_ea_list_path(cli,
8506 if (!NT_STATUS_IS_OK(status)) {
8507 printf("cli_get_ea_list_path failed (%s)\n",
8513 printf("cli_get_ea_list_path failed (%s)\n",
8518 /* Set an EA on the symlink. Should fail. */
8519 status = cli_set_ea_path(cli,
8523 strlen(ea_value)+1);
8525 if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
8526 printf("cli_set_ea_path on a symlink gave %s. "
8527 "Should be NT_STATUS_ACCESS_DENIED.\n",
8532 printf("EA symlink test passed\n");
8537 if (fnum != (uint16_t)-1) {
8538 cli_close(cli, fnum);
8539 fnum = (uint16_t)-1;
8542 cli_setatr(cli, sname, 0, 0);
8543 cli_posix_unlink(cli, sname);
8544 cli_setatr(cli, fname, 0, 0);
8545 cli_posix_unlink(cli, fname);
8547 if (!torture_close_connection(cli)) {
8556 Test POSIX locks are OFD-locks.
8558 static bool run_posix_ofd_lock_test(int dummy)
8560 static struct cli_state *cli;
8561 const char *fname = "posix_file";
8562 uint16_t fnum1 = (uint16_t)-1;
8563 uint16_t fnum2 = (uint16_t)-1;
8564 bool correct = false;
8566 TALLOC_CTX *frame = NULL;
8568 frame = talloc_stackframe();
8570 printf("Starting POSIX ofd-lock test\n");
8572 if (!torture_open_connection(&cli, 0)) {
8577 smbXcli_conn_set_sockopt(cli->conn, sockops);
8579 status = torture_setup_unix_extensions(cli);
8580 if (!NT_STATUS_IS_OK(status)) {
8585 cli_setatr(cli, fname, 0, 0);
8586 cli_posix_unlink(cli, fname);
8588 /* Open the file twice. */
8589 status = cli_posix_open(cli, fname, O_RDWR|O_CREAT|O_EXCL,
8591 if (!NT_STATUS_IS_OK(status)) {
8592 printf("First POSIX open of %s failed\n", fname);
8596 status = cli_posix_open(cli, fname, O_RDWR, 0, &fnum2);
8597 if (!NT_STATUS_IS_OK(status)) {
8598 printf("First POSIX open of %s failed\n", fname);
8602 /* Set a 0-50 lock on fnum1. */
8603 status = cli_posix_lock(cli, fnum1, 0, 50, false, WRITE_LOCK);
8604 if (!NT_STATUS_IS_OK(status)) {
8605 printf("POSIX lock (1) failed %s\n", nt_errstr(status));
8609 /* Set a 60-100 lock on fnum2. */
8610 status = cli_posix_lock(cli, fnum2, 60, 100, false, WRITE_LOCK);
8611 if (!NT_STATUS_IS_OK(status)) {
8612 printf("POSIX lock (2) failed %s\n", nt_errstr(status));
8616 /* close fnum1 - 0-50 lock should go away. */
8617 status = cli_close(cli, fnum1);
8618 if (!NT_STATUS_IS_OK(status)) {
8619 printf("close failed (%s)\n",
8623 fnum1 = (uint16_t)-1;
8625 /* Change the lock context. */
8626 cli_setpid(cli, cli_getpid(cli) + 1);
8628 /* Re-open fnum1. */
8629 status = cli_posix_open(cli, fname, O_RDWR, 0, &fnum1);
8630 if (!NT_STATUS_IS_OK(status)) {
8631 printf("Third POSIX open of %s failed\n", fname);
8635 /* 60-100 lock should still be there. */
8636 status = cli_posix_lock(cli, fnum1, 60, 100, false, WRITE_LOCK);
8637 if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
8638 printf("POSIX lock 60-100 not there %s\n", nt_errstr(status));
8642 /* 0-50 lock should be gone. */
8643 status = cli_posix_lock(cli, fnum1, 0, 50, false, WRITE_LOCK);
8644 if (!NT_STATUS_IS_OK(status)) {
8645 printf("POSIX lock 0-50 failed %s\n", nt_errstr(status));
8649 printf("POSIX OFD lock test passed\n");
8654 if (fnum1 != (uint16_t)-1) {
8655 cli_close(cli, fnum1);
8656 fnum1 = (uint16_t)-1;
8658 if (fnum2 != (uint16_t)-1) {
8659 cli_close(cli, fnum2);
8660 fnum2 = (uint16_t)-1;
8663 cli_setatr(cli, fname, 0, 0);
8664 cli_posix_unlink(cli, fname);
8666 if (!torture_close_connection(cli)) {
8674 struct posix_blocking_state {
8675 struct tevent_context *ev;
8676 struct cli_state *cli1;
8678 struct cli_state *cli2;
8684 static void posix_blocking_locked(struct tevent_req *subreq);
8685 static void posix_blocking_gotblocked(struct tevent_req *subreq);
8686 static void posix_blocking_gotecho(struct tevent_req *subreq);
8687 static void posix_blocking_unlocked(struct tevent_req *subreq);
8689 static struct tevent_req *posix_blocking_send(
8690 TALLOC_CTX *mem_ctx,
8691 struct tevent_context *ev,
8692 struct cli_state *cli1,
8694 struct cli_state *cli2,
8697 struct tevent_req *req = NULL, *subreq = NULL;
8698 struct posix_blocking_state *state = NULL;
8700 req = tevent_req_create(mem_ctx, &state, struct posix_blocking_state);
8706 state->fnum1 = fnum1;
8708 state->fnum2 = fnum2;
8710 subreq = cli_posix_lock_send(
8719 if (tevent_req_nomem(subreq, req)) {
8720 return tevent_req_post(req, ev);
8722 tevent_req_set_callback(subreq, posix_blocking_locked, req);
8726 static void posix_blocking_locked(struct tevent_req *subreq)
8728 struct tevent_req *req = tevent_req_callback_data(
8729 subreq, struct tevent_req);
8730 struct posix_blocking_state *state = tevent_req_data(
8731 req, struct posix_blocking_state);
8734 status = cli_posix_lock_recv(subreq);
8735 TALLOC_FREE(subreq);
8736 if (tevent_req_nterror(req, status)) {
8740 subreq = cli_posix_lock_send(
8749 if (tevent_req_nomem(subreq, req)) {
8752 tevent_req_set_callback(subreq, posix_blocking_gotblocked, req);
8754 /* Make sure the blocking request is delivered */
8755 subreq = cli_echo_send(
8760 (DATA_BLOB) { .data = (uint8_t *)state, .length = 1 });
8761 if (tevent_req_nomem(subreq, req)) {
8764 tevent_req_set_callback(subreq, posix_blocking_gotecho, req);
8767 static void posix_blocking_gotblocked(struct tevent_req *subreq)
8769 struct tevent_req *req = tevent_req_callback_data(
8770 subreq, struct tevent_req);
8771 struct posix_blocking_state *state = tevent_req_data(
8772 req, struct posix_blocking_state);
8775 status = cli_posix_lock_recv(subreq);
8776 TALLOC_FREE(subreq);
8777 if (tevent_req_nterror(req, status)) {
8780 if (!state->gotecho) {
8781 printf("blocked req got through before echo\n");
8782 tevent_req_nterror(req, NT_STATUS_INVALID_LOCK_SEQUENCE);
8785 tevent_req_done(req);
8788 static void posix_blocking_gotecho(struct tevent_req *subreq)
8790 struct tevent_req *req = tevent_req_callback_data(
8791 subreq, struct tevent_req);
8792 struct posix_blocking_state *state = tevent_req_data(
8793 req, struct posix_blocking_state);
8796 status = cli_echo_recv(subreq);
8797 TALLOC_FREE(subreq);
8798 if (tevent_req_nterror(req, status)) {
8801 if (state->gotblocked) {
8802 printf("blocked req got through before echo\n");
8803 tevent_req_nterror(req, NT_STATUS_INVALID_LOCK_SEQUENCE);
8806 state->gotecho = true;
8808 subreq = cli_posix_lock_send(
8817 if (tevent_req_nomem(subreq, req)) {
8820 tevent_req_set_callback(subreq, posix_blocking_unlocked, req);
8823 static void posix_blocking_unlocked(struct tevent_req *subreq)
8825 struct tevent_req *req = tevent_req_callback_data(
8826 subreq, struct tevent_req);
8829 status = cli_posix_lock_recv(subreq);
8830 TALLOC_FREE(subreq);
8831 if (tevent_req_nterror(req, status)) {
8834 /* tevent_req_done in posix_blocking_gotlocked */
8837 static NTSTATUS posix_blocking_recv(struct tevent_req *req)
8839 return tevent_req_simple_recv_ntstatus(req);
8842 static bool run_posix_blocking_lock(int dummy)
8844 struct tevent_context *ev = NULL;
8845 struct cli_state *cli1 = NULL, *cli2 = NULL;
8846 const char *fname = "posix_blocking";
8847 uint16_t fnum1 = UINT16_MAX, fnum2 = UINT16_MAX;
8848 struct tevent_req *req = NULL;
8853 printf("Starting posix blocking lock test\n");
8855 ev = samba_tevent_context_init(NULL);
8860 ok = torture_open_connection(&cli1, 0);
8864 ok = torture_open_connection(&cli2, 0);
8869 smbXcli_conn_set_sockopt(cli1->conn, sockops);
8871 status = torture_setup_unix_extensions(cli1);
8872 if (!NT_STATUS_IS_OK(status)) {
8876 cli_setatr(cli1, fname, 0, 0);
8877 cli_posix_unlink(cli1, fname);
8879 status = cli_posix_open(cli1, fname, O_RDWR|O_CREAT|O_EXCL,
8881 if (!NT_STATUS_IS_OK(status)) {
8882 printf("First POSIX open of %s failed: %s\n",
8888 status = cli_posix_open(cli2, fname, O_RDWR, 0600, &fnum2);
8889 if (!NT_STATUS_IS_OK(status)) {
8890 printf("Second POSIX open of %s failed: %s\n",
8896 req = posix_blocking_send(ev, ev, cli1, fnum1, cli2, fnum2);
8898 printf("cli_posix_blocking failed\n");
8902 ok = tevent_req_poll_ntstatus(req, ev, &status);
8904 printf("tevent_req_poll_ntstatus failed: %s\n",
8908 status = posix_blocking_recv(req);
8910 if (!NT_STATUS_IS_OK(status)) {
8911 printf("posix_blocking_recv returned %s\n",
8919 if (fnum1 != UINT16_MAX) {
8920 cli_close(cli1, fnum1);
8923 if (fnum2 != UINT16_MAX) {
8924 cli_close(cli2, fnum2);
8929 cli_setatr(cli1, fname, 0, 0);
8930 cli_posix_unlink(cli1, fname);
8936 ok &= torture_close_connection(cli1);
8940 ok &= torture_close_connection(cli2);
8952 Test POSIX mkdir is case-sensitive.
8954 static bool run_posix_mkdir_test(int dummy)
8956 static struct cli_state *cli;
8957 const char *fname_foo = "POSIX_foo";
8958 const char *fname_foo_Foo = "POSIX_foo/Foo";
8959 const char *fname_foo_foo = "POSIX_foo/foo";
8960 const char *fname_Foo = "POSIX_Foo";
8961 const char *fname_Foo_Foo = "POSIX_Foo/Foo";
8962 const char *fname_Foo_foo = "POSIX_Foo/foo";
8963 bool correct = false;
8965 TALLOC_CTX *frame = NULL;
8966 uint16_t fnum = (uint16_t)-1;
8968 frame = talloc_stackframe();
8970 printf("Starting POSIX mkdir test\n");
8972 if (!torture_open_connection(&cli, 0)) {
8977 smbXcli_conn_set_sockopt(cli->conn, sockops);
8979 status = torture_setup_unix_extensions(cli);
8980 if (!NT_STATUS_IS_OK(status)) {
8985 cli_posix_rmdir(cli, fname_foo_foo);
8986 cli_posix_rmdir(cli, fname_foo_Foo);
8987 cli_posix_rmdir(cli, fname_foo);
8989 cli_posix_rmdir(cli, fname_Foo_foo);
8990 cli_posix_rmdir(cli, fname_Foo_Foo);
8991 cli_posix_rmdir(cli, fname_Foo);
8994 * Create a file POSIX_foo then try
8995 * and use it in a directory path by
8996 * doing mkdir POSIX_foo/bar.
8997 * The mkdir should fail with
8998 * NT_STATUS_OBJECT_PATH_NOT_FOUND
9001 status = cli_posix_open(cli,
9006 if (!NT_STATUS_IS_OK(status)) {
9007 printf("cli_posix_open of %s failed error %s\n",
9013 status = cli_posix_mkdir(cli, fname_foo_foo, 0777);
9014 if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_PATH_NOT_FOUND)) {
9015 printf("cli_posix_mkdir of %s should fail with "
9016 "NT_STATUS_OBJECT_PATH_NOT_FOUND got "
9023 status = cli_close(cli, fnum);
9024 if (!NT_STATUS_IS_OK(status)) {
9025 printf("cli_close failed %s\n", nt_errstr(status));
9028 fnum = (uint16_t)-1;
9030 status = cli_posix_unlink(cli, fname_foo);
9031 if (!NT_STATUS_IS_OK(status)) {
9032 printf("cli_posix_unlink of %s failed error %s\n",
9039 * Now we've deleted everything, posix_mkdir, posix_rmdir,
9040 * posix_open, posix_unlink, on
9041 * POSIX_foo/foo should return NT_STATUS_OBJECT_PATH_NOT_FOUND
9042 * not silently create POSIX_foo/foo.
9045 status = cli_posix_mkdir(cli, fname_foo_foo, 0777);
9046 if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_PATH_NOT_FOUND)) {
9047 printf("cli_posix_mkdir of %s should fail with "
9048 "NT_STATUS_OBJECT_PATH_NOT_FOUND got "
9055 status = cli_posix_rmdir(cli, fname_foo_foo);
9056 if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_PATH_NOT_FOUND)) {
9057 printf("cli_posix_rmdir of %s should fail with "
9058 "NT_STATUS_OBJECT_PATH_NOT_FOUND got "
9065 status = cli_posix_open(cli,
9070 if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_PATH_NOT_FOUND)) {
9071 printf("cli_posix_open of %s should fail with "
9072 "NT_STATUS_OBJECT_PATH_NOT_FOUND got "
9079 status = cli_posix_unlink(cli, fname_foo_foo);
9080 if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_PATH_NOT_FOUND)) {
9081 printf("cli_posix_unlink of %s should fail with "
9082 "NT_STATUS_OBJECT_PATH_NOT_FOUND got "
9089 status = cli_posix_mkdir(cli, fname_foo, 0777);
9090 if (!NT_STATUS_IS_OK(status)) {
9091 printf("cli_posix_mkdir of %s failed\n", fname_foo);
9095 status = cli_posix_mkdir(cli, fname_Foo, 0777);
9096 if (!NT_STATUS_IS_OK(status)) {
9097 printf("cli_posix_mkdir of %s failed\n", fname_Foo);
9101 status = cli_posix_mkdir(cli, fname_foo_foo, 0777);
9102 if (!NT_STATUS_IS_OK(status)) {
9103 printf("cli_posix_mkdir of %s failed\n", fname_foo_foo);
9107 status = cli_posix_mkdir(cli, fname_foo_Foo, 0777);
9108 if (!NT_STATUS_IS_OK(status)) {
9109 printf("cli_posix_mkdir of %s failed\n", fname_foo_Foo);
9113 status = cli_posix_mkdir(cli, fname_Foo_foo, 0777);
9114 if (!NT_STATUS_IS_OK(status)) {
9115 printf("cli_posix_mkdir of %s failed\n", fname_Foo_foo);
9119 status = cli_posix_mkdir(cli, fname_Foo_Foo, 0777);
9120 if (!NT_STATUS_IS_OK(status)) {
9121 printf("cli_posix_mkdir of %s failed\n", fname_Foo_Foo);
9125 printf("POSIX mkdir test passed\n");
9130 if (fnum != (uint16_t)-1) {
9131 cli_close(cli, fnum);
9132 fnum = (uint16_t)-1;
9135 cli_posix_rmdir(cli, fname_foo_foo);
9136 cli_posix_rmdir(cli, fname_foo_Foo);
9137 cli_posix_rmdir(cli, fname_foo);
9139 cli_posix_rmdir(cli, fname_Foo_foo);
9140 cli_posix_rmdir(cli, fname_Foo_Foo);
9141 cli_posix_rmdir(cli, fname_Foo);
9143 if (!torture_close_connection(cli)) {
9151 struct posix_acl_oplock_state {
9152 struct tevent_context *ev;
9153 struct cli_state *cli;
9159 static void posix_acl_oplock_got_break(struct tevent_req *req)
9161 struct posix_acl_oplock_state *state = tevent_req_callback_data(
9162 req, struct posix_acl_oplock_state);
9167 status = cli_smb_oplock_break_waiter_recv(req, &fnum, &level);
9169 if (!NT_STATUS_IS_OK(status)) {
9170 printf("cli_smb_oplock_break_waiter_recv returned %s\n",
9174 *state->got_break = true;
9176 req = cli_oplock_ack_send(state, state->ev, state->cli, fnum,
9179 printf("cli_oplock_ack_send failed\n");
9184 static void posix_acl_oplock_got_acl(struct tevent_req *req)
9186 struct posix_acl_oplock_state *state = tevent_req_callback_data(
9187 req, struct posix_acl_oplock_state);
9188 size_t ret_size = 0;
9189 char *ret_data = NULL;
9191 state->status = cli_posix_getacl_recv(req,
9196 if (!NT_STATUS_IS_OK(state->status)) {
9197 printf("cli_posix_getacl_recv returned %s\n",
9198 nt_errstr(state->status));
9200 *state->acl_ret = true;
9203 static bool run_posix_acl_oplock_test(int dummy)
9205 struct tevent_context *ev;
9206 struct cli_state *cli1, *cli2;
9207 struct tevent_req *oplock_req, *getacl_req;
9208 const char *fname = "posix_acl_oplock";
9210 int saved_use_oplocks = use_oplocks;
9212 bool correct = true;
9213 bool got_break = false;
9214 bool acl_ret = false;
9216 struct posix_acl_oplock_state *state;
9218 printf("starting posix_acl_oplock test\n");
9220 if (!torture_open_connection(&cli1, 0)) {
9221 use_level_II_oplocks = false;
9222 use_oplocks = saved_use_oplocks;
9226 if (!torture_open_connection(&cli2, 1)) {
9227 use_level_II_oplocks = false;
9228 use_oplocks = saved_use_oplocks;
9232 /* Setup posix on cli2 only. */
9233 status = torture_setup_unix_extensions(cli2);
9234 if (!NT_STATUS_IS_OK(status)) {
9238 smbXcli_conn_set_sockopt(cli1->conn, sockops);
9239 smbXcli_conn_set_sockopt(cli2->conn, sockops);
9241 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
9243 /* Create the file on the Windows connection. */
9244 status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE,
9246 if (!NT_STATUS_IS_OK(status)) {
9247 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
9251 status = cli_close(cli1, fnum);
9252 if (!NT_STATUS_IS_OK(status)) {
9253 printf("close1 failed (%s)\n", nt_errstr(status));
9257 cli1->use_oplocks = true;
9259 /* Open with oplock. */
9260 status = cli_ntcreate(cli1,
9264 FILE_ATTRIBUTE_NORMAL,
9265 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
9272 if (!NT_STATUS_IS_OK(status)) {
9273 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
9277 ev = samba_tevent_context_init(talloc_tos());
9279 printf("tevent_context_init failed\n");
9283 state = talloc_zero(ev, struct posix_acl_oplock_state);
9284 if (state == NULL) {
9285 printf("talloc failed\n");
9290 state->got_break = &got_break;
9291 state->acl_ret = &acl_ret;
9293 oplock_req = cli_smb_oplock_break_waiter_send(
9294 talloc_tos(), ev, cli1);
9295 if (oplock_req == NULL) {
9296 printf("cli_smb_oplock_break_waiter_send failed\n");
9299 tevent_req_set_callback(oplock_req, posix_acl_oplock_got_break, state);
9301 /* Get ACL on POSIX connection - should break oplock. */
9302 getacl_req = cli_posix_getacl_send(talloc_tos(),
9306 if (getacl_req == NULL) {
9307 printf("cli_posix_getacl_send failed\n");
9310 tevent_req_set_callback(getacl_req, posix_acl_oplock_got_acl, state);
9312 while (!got_break || !acl_ret) {
9314 ret = tevent_loop_once(ev);
9316 printf("tevent_loop_once failed: %s\n",
9322 if (!NT_STATUS_IS_OK(state->status)) {
9323 printf("getacl failed (%s)\n", nt_errstr(state->status));
9327 status = cli_close(cli1, fnum);
9328 if (!NT_STATUS_IS_OK(status)) {
9329 printf("close2 failed (%s)\n", nt_errstr(status));
9333 status = cli_unlink(cli1,
9335 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
9336 if (!NT_STATUS_IS_OK(status)) {
9337 printf("unlink failed (%s)\n", nt_errstr(status));
9341 if (!torture_close_connection(cli1)) {
9344 if (!torture_close_connection(cli2)) {
9352 printf("finished posix acl oplock test\n");
9357 static bool run_posix_acl_shareroot_test(int dummy)
9359 struct cli_state *cli;
9361 bool correct = false;
9362 char *posix_acl = NULL;
9363 size_t posix_acl_len = 0;
9364 uint16_t num_file_acls = 0;
9365 uint16_t num_dir_acls = 0;
9367 uint32_t expected_size = 0;
9368 bool got_user = false;
9369 bool got_group = false;
9370 bool got_other = false;
9371 TALLOC_CTX *frame = NULL;
9373 frame = talloc_stackframe();
9375 printf("starting posix_acl_shareroot test\n");
9377 if (!torture_open_connection(&cli, 0)) {
9382 smbXcli_conn_set_sockopt(cli->conn, sockops);
9384 status = torture_setup_unix_extensions(cli);
9385 if (!NT_STATUS_IS_OK(status)) {
9386 printf("Failed to setup unix extensions\n");
9390 /* Get the POSIX ACL on the root of the share. */
9391 status = cli_posix_getacl(cli,
9397 if (!NT_STATUS_IS_OK(status)) {
9398 printf("cli_posix_getacl of '.' failed (%s)\n",
9403 if (posix_acl_len < 6 ||
9404 SVAL(posix_acl,0) != SMB_POSIX_ACL_VERSION) {
9405 printf("getfacl ., unknown POSIX acl version %u.\n",
9406 (unsigned int)CVAL(posix_acl,0) );
9410 num_file_acls = SVAL(posix_acl,2);
9411 num_dir_acls = SVAL(posix_acl,4);
9412 expected_size = SMB_POSIX_ACL_HEADER_SIZE +
9413 SMB_POSIX_ACL_ENTRY_SIZE*
9414 (num_file_acls+num_dir_acls);
9416 if (posix_acl_len != expected_size) {
9417 printf("incorrect POSIX acl buffer size "
9418 "(should be %u, was %u).\n",
9419 (unsigned int)expected_size,
9420 (unsigned int)posix_acl_len);
9425 * We don't need to know what the ACL's are
9426 * we just need to know we have at least 3
9427 * file entries (u,g,o).
9430 for (i = 0; i < num_file_acls; i++) {
9431 unsigned char tagtype =
9433 SMB_POSIX_ACL_HEADER_SIZE+
9434 (i*SMB_POSIX_ACL_ENTRY_SIZE));
9437 case SMB_POSIX_ACL_USER_OBJ:
9440 case SMB_POSIX_ACL_GROUP_OBJ:
9443 case SMB_POSIX_ACL_OTHER:
9452 printf("Missing user entry\n");
9457 printf("Missing group entry\n");
9462 printf("Missing other entry\n");
9470 if (!torture_close_connection(cli)) {
9474 printf("finished posix acl shareroot test\n");
9480 static uint32_t open_attrs_table[] = {
9481 FILE_ATTRIBUTE_NORMAL,
9482 FILE_ATTRIBUTE_ARCHIVE,
9483 FILE_ATTRIBUTE_READONLY,
9484 FILE_ATTRIBUTE_HIDDEN,
9485 FILE_ATTRIBUTE_SYSTEM,
9487 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY,
9488 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN,
9489 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM,
9490 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN,
9491 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM,
9492 FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM,
9494 FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN,
9495 FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM,
9496 FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM,
9497 FILE_ATTRIBUTE_HIDDEN,FILE_ATTRIBUTE_SYSTEM,
9500 struct trunc_open_results {
9503 uint32_t trunc_attr;
9504 uint32_t result_attr;
9507 static struct trunc_open_results attr_results[] = {
9508 { 0, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_ARCHIVE },
9509 { 1, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_ARCHIVE },
9510 { 2, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_READONLY, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY },
9511 { 16, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_ARCHIVE },
9512 { 17, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_ARCHIVE },
9513 { 18, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_READONLY, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY },
9514 { 51, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
9515 { 54, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
9516 { 56, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN },
9517 { 68, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
9518 { 71, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
9519 { 73, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM },
9520 { 99, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_HIDDEN,FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
9521 { 102, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
9522 { 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 },
9523 { 116, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
9524 { 119, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
9525 { 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 },
9526 { 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 },
9527 { 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 },
9528 { 227, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
9529 { 230, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN },
9530 { 232, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN },
9531 { 244, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
9532 { 247, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_SYSTEM },
9533 { 249, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM }
9536 static bool run_openattrtest(int dummy)
9538 static struct cli_state *cli1;
9539 const char *fname = "\\openattr.file";
9541 bool correct = True;
9543 unsigned int i, j, k, l;
9546 printf("starting open attr test\n");
9548 if (!torture_open_connection(&cli1, 0)) {
9552 smbXcli_conn_set_sockopt(cli1->conn, sockops);
9554 for (k = 0, i = 0; i < sizeof(open_attrs_table)/sizeof(uint32_t); i++) {
9555 cli_setatr(cli1, fname, 0, 0);
9556 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
9558 status = cli_ntcreate(cli1, fname, 0, FILE_WRITE_DATA,
9559 open_attrs_table[i], FILE_SHARE_NONE,
9560 FILE_OVERWRITE_IF, 0, 0, &fnum1, NULL);
9561 if (!NT_STATUS_IS_OK(status)) {
9562 printf("open %d (1) of %s failed (%s)\n", i, fname, nt_errstr(status));
9566 status = cli_close(cli1, fnum1);
9567 if (!NT_STATUS_IS_OK(status)) {
9568 printf("close %d (1) of %s failed (%s)\n", i, fname, nt_errstr(status));
9572 for (j = 0; j < sizeof(open_attrs_table)/sizeof(uint32_t); j++) {
9573 status = cli_ntcreate(cli1, fname, 0,
9574 FILE_READ_DATA|FILE_WRITE_DATA,
9575 open_attrs_table[j],
9576 FILE_SHARE_NONE, FILE_OVERWRITE,
9577 0, 0, &fnum1, NULL);
9578 if (!NT_STATUS_IS_OK(status)) {
9579 for (l = 0; l < sizeof(attr_results)/sizeof(struct trunc_open_results); l++) {
9580 if (attr_results[l].num == k) {
9581 printf("[%d] trunc open 0x%x -> 0x%x of %s failed - should have succeeded !(0x%x:%s)\n",
9582 k, open_attrs_table[i],
9583 open_attrs_table[j],
9584 fname, NT_STATUS_V(status), nt_errstr(status));
9589 if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
9590 printf("[%d] trunc open 0x%x -> 0x%x failed with wrong error code %s\n",
9591 k, open_attrs_table[i], open_attrs_table[j],
9596 printf("[%d] trunc open 0x%x -> 0x%x failed\n", k, open_attrs_table[i], open_attrs_table[j]);
9602 status = cli_close(cli1, fnum1);
9603 if (!NT_STATUS_IS_OK(status)) {
9604 printf("close %d (2) of %s failed (%s)\n", j, fname, nt_errstr(status));
9608 status = cli_getatr(cli1, fname, &attr, NULL, NULL);
9609 if (!NT_STATUS_IS_OK(status)) {
9610 printf("getatr(2) failed (%s)\n", nt_errstr(status));
9615 printf("[%d] getatr check [0x%x] trunc [0x%x] got attr 0x%x\n",
9616 k, open_attrs_table[i], open_attrs_table[j], attr );
9619 for (l = 0; l < sizeof(attr_results)/sizeof(struct trunc_open_results); l++) {
9620 if (attr_results[l].num == k) {
9621 if (attr != attr_results[l].result_attr ||
9622 open_attrs_table[i] != attr_results[l].init_attr ||
9623 open_attrs_table[j] != attr_results[l].trunc_attr) {
9624 printf("getatr check failed. [0x%x] trunc [0x%x] got attr 0x%x, should be 0x%x\n",
9625 open_attrs_table[i],
9626 open_attrs_table[j],
9628 attr_results[l].result_attr);
9638 cli_setatr(cli1, fname, 0, 0);
9639 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
9641 printf("open attr test %s.\n", correct ? "passed" : "failed");
9643 if (!torture_close_connection(cli1)) {
9649 static NTSTATUS list_fn(const char *mnt, struct file_info *finfo,
9650 const char *name, void *state)
9652 int *matched = (int *)state;
9653 if (matched != NULL) {
9656 return NT_STATUS_OK;
9660 test directory listing speed
9662 static bool run_dirtest(int dummy)
9665 static struct cli_state *cli;
9667 struct timeval core_start;
9668 bool correct = True;
9671 printf("starting directory test\n");
9673 if (!torture_open_connection(&cli, 0)) {
9677 smbXcli_conn_set_sockopt(cli->conn, sockops);
9680 for (i=0;i<torture_numops;i++) {
9682 slprintf(fname, sizeof(fname), "\\%x", (int)random());
9683 if (!NT_STATUS_IS_OK(cli_openx(cli, fname, O_RDWR|O_CREAT, DENY_NONE, &fnum))) {
9684 fprintf(stderr,"Failed to open %s\n", fname);
9687 cli_close(cli, fnum);
9690 core_start = timeval_current();
9693 cli_list(cli, "a*.*", 0, list_fn, &matched);
9694 printf("Matched %d\n", matched);
9697 cli_list(cli, "b*.*", 0, list_fn, &matched);
9698 printf("Matched %d\n", matched);
9701 cli_list(cli, "xyzabc", 0, list_fn, &matched);
9702 printf("Matched %d\n", matched);
9704 printf("dirtest core %g seconds\n", timeval_elapsed(&core_start));
9707 for (i=0;i<torture_numops;i++) {
9709 slprintf(fname, sizeof(fname), "\\%x", (int)random());
9710 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
9713 if (!torture_close_connection(cli)) {
9717 printf("finished dirtest\n");
9722 static NTSTATUS del_fn(const char *mnt, struct file_info *finfo, const char *mask,
9725 struct cli_state *pcli = (struct cli_state *)state;
9727 slprintf(fname, sizeof(fname), "\\LISTDIR\\%s", finfo->name);
9729 if (strcmp(finfo->name, ".") == 0 || strcmp(finfo->name, "..") == 0)
9730 return NT_STATUS_OK;
9732 if (finfo->attr & FILE_ATTRIBUTE_DIRECTORY) {
9733 if (!NT_STATUS_IS_OK(cli_rmdir(pcli, fname)))
9734 printf("del_fn: failed to rmdir %s\n,", fname );
9736 if (!NT_STATUS_IS_OK(cli_unlink(pcli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN)))
9737 printf("del_fn: failed to unlink %s\n,", fname );
9739 return NT_STATUS_OK;
9744 sees what IOCTLs are supported
9746 bool torture_ioctl_test(int dummy)
9748 static struct cli_state *cli;
9749 uint16_t device, function;
9751 const char *fname = "\\ioctl.dat";
9755 if (!torture_open_connection(&cli, 0)) {
9759 printf("starting ioctl test\n");
9761 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
9763 status = cli_openx(cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
9764 if (!NT_STATUS_IS_OK(status)) {
9765 printf("open of %s failed (%s)\n", fname, nt_errstr(status));
9769 status = cli_raw_ioctl(cli, fnum, 0x2d0000 | (0x0420<<2), &blob);
9770 printf("ioctl device info: %s\n", nt_errstr(status));
9772 status = cli_raw_ioctl(cli, fnum, IOCTL_QUERY_JOB_INFO, &blob);
9773 printf("ioctl job info: %s\n", nt_errstr(status));
9775 for (device=0;device<0x100;device++) {
9776 printf("ioctl test with device = 0x%x\n", device);
9777 for (function=0;function<0x100;function++) {
9778 uint32_t code = (device<<16) | function;
9780 status = cli_raw_ioctl(cli, fnum, code, &blob);
9782 if (NT_STATUS_IS_OK(status)) {
9783 printf("ioctl 0x%x OK : %d bytes\n", (int)code,
9785 data_blob_free(&blob);
9790 if (!torture_close_connection(cli)) {
9799 tries varients of chkpath
9801 bool torture_chkpath_test(int dummy)
9803 static struct cli_state *cli;
9808 if (!torture_open_connection(&cli, 0)) {
9812 printf("starting chkpath test\n");
9814 /* cleanup from an old run */
9815 cli_rmdir(cli, "\\chkpath.dir\\dir2");
9816 cli_unlink(cli, "\\chkpath.dir\\*", FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
9817 cli_rmdir(cli, "\\chkpath.dir");
9819 status = cli_mkdir(cli, "\\chkpath.dir");
9820 if (!NT_STATUS_IS_OK(status)) {
9821 printf("mkdir1 failed : %s\n", nt_errstr(status));
9825 status = cli_mkdir(cli, "\\chkpath.dir\\dir2");
9826 if (!NT_STATUS_IS_OK(status)) {
9827 printf("mkdir2 failed : %s\n", nt_errstr(status));
9831 status = cli_openx(cli, "\\chkpath.dir\\foo.txt", O_RDWR|O_CREAT|O_EXCL,
9833 if (!NT_STATUS_IS_OK(status)) {
9834 printf("open1 failed (%s)\n", nt_errstr(status));
9837 cli_close(cli, fnum);
9839 status = cli_chkpath(cli, "\\chkpath.dir");
9840 if (!NT_STATUS_IS_OK(status)) {
9841 printf("chkpath1 failed: %s\n", nt_errstr(status));
9845 status = cli_chkpath(cli, "\\chkpath.dir\\dir2");
9846 if (!NT_STATUS_IS_OK(status)) {
9847 printf("chkpath2 failed: %s\n", nt_errstr(status));
9851 status = cli_chkpath(cli, "\\chkpath.dir\\foo.txt");
9852 if (!NT_STATUS_IS_OK(status)) {
9853 ret = check_error(__LINE__, status, ERRDOS, ERRbadpath,
9854 NT_STATUS_NOT_A_DIRECTORY);
9856 printf("* chkpath on a file should fail\n");
9860 status = cli_chkpath(cli, "\\chkpath.dir\\bar.txt");
9861 if (!NT_STATUS_IS_OK(status)) {
9862 ret = check_error(__LINE__, status, ERRDOS, ERRbadfile,
9863 NT_STATUS_OBJECT_NAME_NOT_FOUND);
9865 printf("* chkpath on a non existent file should fail\n");
9869 status = cli_chkpath(cli, "\\chkpath.dir\\dirxx\\bar.txt");
9870 if (!NT_STATUS_IS_OK(status)) {
9871 ret = check_error(__LINE__, status, ERRDOS, ERRbadpath,
9872 NT_STATUS_OBJECT_PATH_NOT_FOUND);
9874 printf("* chkpath on a non existent component should fail\n");
9878 cli_rmdir(cli, "\\chkpath.dir\\dir2");
9879 cli_unlink(cli, "\\chkpath.dir\\*", FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
9880 cli_rmdir(cli, "\\chkpath.dir");
9882 if (!torture_close_connection(cli)) {
9889 static bool run_eatest(int dummy)
9891 static struct cli_state *cli;
9892 const char *fname = "\\eatest.txt";
9893 bool correct = True;
9897 struct ea_struct *ea_list = NULL;
9898 TALLOC_CTX *mem_ctx = talloc_init("eatest");
9901 printf("starting eatest\n");
9903 if (!torture_open_connection(&cli, 0)) {
9904 talloc_destroy(mem_ctx);
9908 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
9910 status = cli_ntcreate(cli, fname, 0,
9911 FIRST_DESIRED_ACCESS, FILE_ATTRIBUTE_ARCHIVE,
9912 FILE_SHARE_NONE, FILE_OVERWRITE_IF,
9913 0x4044, 0, &fnum, NULL);
9914 if (!NT_STATUS_IS_OK(status)) {
9915 printf("open failed - %s\n", nt_errstr(status));
9916 talloc_destroy(mem_ctx);
9920 for (i = 0; i < 10; i++) {
9921 fstring ea_name, ea_val;
9923 slprintf(ea_name, sizeof(ea_name), "EA_%d", i);
9924 memset(ea_val, (char)i+1, i+1);
9925 status = cli_set_ea_fnum(cli, fnum, ea_name, ea_val, i+1);
9926 if (!NT_STATUS_IS_OK(status)) {
9927 printf("ea_set of name %s failed - %s\n", ea_name,
9929 talloc_destroy(mem_ctx);
9934 cli_close(cli, fnum);
9935 for (i = 0; i < 10; i++) {
9936 fstring ea_name, ea_val;
9938 slprintf(ea_name, sizeof(ea_name), "EA_%d", i+10);
9939 memset(ea_val, (char)i+1, i+1);
9940 status = cli_set_ea_path(cli, fname, ea_name, ea_val, i+1);
9941 if (!NT_STATUS_IS_OK(status)) {
9942 printf("ea_set of name %s failed - %s\n", ea_name,
9944 talloc_destroy(mem_ctx);
9949 status = cli_get_ea_list_path(cli, fname, mem_ctx, &num_eas, &ea_list);
9950 if (!NT_STATUS_IS_OK(status)) {
9951 printf("ea_get list failed - %s\n", nt_errstr(status));
9955 printf("num_eas = %d\n", (int)num_eas);
9957 if (num_eas != 20) {
9958 printf("Should be 20 EA's stored... failing.\n");
9962 for (i = 0; i < num_eas; i++) {
9963 printf("%d: ea_name = %s. Val = ", i, ea_list[i].name);
9964 dump_data(0, ea_list[i].value.data,
9965 ea_list[i].value.length);
9968 /* Setting EA's to zero length deletes them. Test this */
9969 printf("Now deleting all EA's - case indepenent....\n");
9972 cli_set_ea_path(cli, fname, "", "", 0);
9974 for (i = 0; i < 20; i++) {
9976 slprintf(ea_name, sizeof(ea_name), "ea_%d", i);
9977 status = cli_set_ea_path(cli, fname, ea_name, "", 0);
9978 if (!NT_STATUS_IS_OK(status)) {
9979 printf("ea_set of name %s failed - %s\n", ea_name,
9981 talloc_destroy(mem_ctx);
9987 status = cli_get_ea_list_path(cli, fname, mem_ctx, &num_eas, &ea_list);
9988 if (!NT_STATUS_IS_OK(status)) {
9989 printf("ea_get list failed - %s\n", nt_errstr(status));
9993 printf("num_eas = %d\n", (int)num_eas);
9994 for (i = 0; i < num_eas; i++) {
9995 printf("%d: ea_name = %s. Val = ", i, ea_list[i].name);
9996 dump_data(0, ea_list[i].value.data,
9997 ea_list[i].value.length);
10000 if (num_eas != 0) {
10001 printf("deleting EA's failed.\n");
10005 /* Try and delete a non existent EA. */
10006 status = cli_set_ea_path(cli, fname, "foo", "", 0);
10007 if (!NT_STATUS_IS_OK(status)) {
10008 printf("deleting non-existent EA 'foo' should succeed. %s\n",
10009 nt_errstr(status));
10013 talloc_destroy(mem_ctx);
10014 if (!torture_close_connection(cli)) {
10021 static bool run_dirtest1(int dummy)
10024 static struct cli_state *cli;
10027 bool correct = True;
10029 printf("starting directory test\n");
10031 if (!torture_open_connection(&cli, 0)) {
10035 smbXcli_conn_set_sockopt(cli->conn, sockops);
10037 cli_list(cli, "\\LISTDIR\\*", 0, del_fn, cli);
10038 cli_list(cli, "\\LISTDIR\\*", FILE_ATTRIBUTE_DIRECTORY, del_fn, cli);
10039 cli_rmdir(cli, "\\LISTDIR");
10040 cli_mkdir(cli, "\\LISTDIR");
10042 /* Create 1000 files and 1000 directories. */
10043 for (i=0;i<1000;i++) {
10045 slprintf(fname, sizeof(fname), "\\LISTDIR\\f%d", i);
10046 if (!NT_STATUS_IS_OK(cli_ntcreate(cli, fname, 0, GENERIC_ALL_ACCESS, FILE_ATTRIBUTE_ARCHIVE,
10047 FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OVERWRITE_IF,
10048 0, 0, &fnum, NULL))) {
10049 fprintf(stderr,"Failed to open %s\n", fname);
10052 cli_close(cli, fnum);
10054 for (i=0;i<1000;i++) {
10056 slprintf(fname, sizeof(fname), "\\LISTDIR\\d%d", i);
10057 if (!NT_STATUS_IS_OK(cli_mkdir(cli, fname))) {
10058 fprintf(stderr,"Failed to open %s\n", fname);
10063 /* Now ensure that doing an old list sees both files and directories. */
10065 cli_list_old(cli, "\\LISTDIR\\*", FILE_ATTRIBUTE_DIRECTORY, list_fn, &num_seen);
10066 printf("num_seen = %d\n", num_seen );
10067 /* We should see 100 files + 1000 directories + . and .. */
10068 if (num_seen != 2002)
10071 /* Ensure if we have the "must have" bits we only see the
10072 * relevent entries.
10075 cli_list_old(cli, "\\LISTDIR\\*", (FILE_ATTRIBUTE_DIRECTORY<<8)|FILE_ATTRIBUTE_DIRECTORY, list_fn, &num_seen);
10076 printf("num_seen = %d\n", num_seen );
10077 if (num_seen != 1002)
10081 cli_list_old(cli, "\\LISTDIR\\*", (FILE_ATTRIBUTE_ARCHIVE<<8)|FILE_ATTRIBUTE_DIRECTORY, list_fn, &num_seen);
10082 printf("num_seen = %d\n", num_seen );
10083 if (num_seen != 1000)
10086 /* Delete everything. */
10087 cli_list(cli, "\\LISTDIR\\*", 0, del_fn, cli);
10088 cli_list(cli, "\\LISTDIR\\*", FILE_ATTRIBUTE_DIRECTORY, del_fn, cli);
10089 cli_rmdir(cli, "\\LISTDIR");
10092 printf("Matched %d\n", cli_list(cli, "a*.*", 0, list_fn, NULL));
10093 printf("Matched %d\n", cli_list(cli, "b*.*", 0, list_fn, NULL));
10094 printf("Matched %d\n", cli_list(cli, "xyzabc", 0, list_fn, NULL));
10097 if (!torture_close_connection(cli)) {
10101 printf("finished dirtest1\n");
10106 static bool run_error_map_extract(int dummy) {
10108 static struct cli_state *c_dos;
10109 static struct cli_state *c_nt;
10117 NTSTATUS nt_status;
10121 /* NT-Error connection */
10123 disable_spnego = true;
10124 if (!(c_nt = open_nbt_connection())) {
10125 disable_spnego = false;
10128 disable_spnego = false;
10130 status = smbXcli_negprot(c_nt->conn, c_nt->timeout, PROTOCOL_CORE,
10133 if (!NT_STATUS_IS_OK(status)) {
10134 printf("%s rejected the NT-error negprot (%s)\n", host,
10135 nt_errstr(status));
10136 cli_shutdown(c_nt);
10140 status = cli_session_setup_anon(c_nt);
10141 if (!NT_STATUS_IS_OK(status)) {
10142 printf("%s rejected the NT-error initial session setup (%s)\n",host, nt_errstr(status));
10146 /* DOS-Error connection */
10148 disable_spnego = true;
10149 force_dos_errors = true;
10150 if (!(c_dos = open_nbt_connection())) {
10151 disable_spnego = false;
10152 force_dos_errors = false;
10155 disable_spnego = false;
10156 force_dos_errors = false;
10158 status = smbXcli_negprot(c_dos->conn, c_dos->timeout, PROTOCOL_CORE,
10160 if (!NT_STATUS_IS_OK(status)) {
10161 printf("%s rejected the DOS-error negprot (%s)\n", host,
10162 nt_errstr(status));
10163 cli_shutdown(c_dos);
10167 status = cli_session_setup_anon(c_dos);
10168 if (!NT_STATUS_IS_OK(status)) {
10169 printf("%s rejected the DOS-error initial session setup (%s)\n",
10170 host, nt_errstr(status));
10174 c_nt->map_dos_errors = false;
10175 c_dos->map_dos_errors = false;
10177 for (error=(0xc0000000 | 0x1); error < (0xc0000000| 0xFFF); error++) {
10178 struct cli_credentials *user_creds = NULL;
10180 fstr_sprintf(user, "%X", error);
10182 user_creds = cli_session_creds_init(talloc_tos(),
10187 false, /* use_kerberos */
10188 false, /* fallback_after_kerberos */
10189 false, /* use_ccache */
10190 false); /* password_is_nt_hash */
10191 if (user_creds == NULL) {
10192 printf("cli_session_creds_init(%s) failed\n", user);
10196 status = cli_session_setup_creds(c_nt, user_creds);
10197 if (NT_STATUS_IS_OK(status)) {
10198 printf("/** Session setup succeeded. This shouldn't happen...*/\n");
10201 /* Case #1: 32-bit NT errors */
10202 if (!NT_STATUS_IS_DOS(status)) {
10203 nt_status = status;
10205 printf("/** Dos error on NT connection! (%s) */\n",
10206 nt_errstr(status));
10207 nt_status = NT_STATUS(0xc0000000);
10210 status = cli_session_setup_creds(c_dos, 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 printf("/** NT error on DOS connection! (%s) */\n",
10218 nt_errstr(status));
10219 errnum = errclass = 0;
10221 errclass = NT_STATUS_DOS_CLASS(status);
10222 errnum = NT_STATUS_DOS_CODE(status);
10225 if (NT_STATUS_V(nt_status) != error) {
10226 printf("/*\t{ This NT error code was 'sqashed'\n\t from %s to %s \n\t during the session setup }\n*/\n",
10227 get_nt_error_c_code(talloc_tos(), NT_STATUS(error)),
10228 get_nt_error_c_code(talloc_tos(), nt_status));
10231 printf("\t{%s,\t%s,\t%s},\n",
10232 smb_dos_err_class(errclass),
10233 smb_dos_err_name(errclass, errnum),
10234 get_nt_error_c_code(talloc_tos(), NT_STATUS(error)));
10236 TALLOC_FREE(user_creds);
10241 static bool run_sesssetup_bench(int dummy)
10243 static struct cli_state *c;
10244 const char *fname = "\\file.dat";
10249 if (!torture_open_connection(&c, 0)) {
10253 status = cli_ntcreate(c, fname, 0, GENERIC_ALL_ACCESS|DELETE_ACCESS,
10254 FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
10255 FILE_DELETE_ON_CLOSE, 0, &fnum, NULL);
10256 if (!NT_STATUS_IS_OK(status)) {
10257 d_printf("open %s failed: %s\n", fname, nt_errstr(status));
10261 for (i=0; i<torture_numops; i++) {
10262 status = cli_session_setup_creds(c, torture_creds);
10263 if (!NT_STATUS_IS_OK(status)) {
10264 d_printf("(%s) cli_session_setup_creds failed: %s\n",
10265 __location__, nt_errstr(status));
10269 d_printf("\r%d ", (int)cli_state_get_uid(c));
10271 status = cli_ulogoff(c);
10272 if (!NT_STATUS_IS_OK(status)) {
10273 d_printf("(%s) cli_ulogoff failed: %s\n",
10274 __location__, nt_errstr(status));
10282 static bool subst_test(const char *str, const char *user, const char *domain,
10283 uid_t uid, gid_t gid, const char *expected)
10286 bool result = true;
10288 subst = talloc_sub_specified(talloc_tos(), str, user, NULL, domain, uid, gid);
10290 if (strcmp(subst, expected) != 0) {
10291 printf("sub_specified(%s, %s, %s, %d, %d) returned [%s], expected "
10292 "[%s]\n", str, user, domain, (int)uid, (int)gid, subst,
10297 TALLOC_FREE(subst);
10301 static void chain1_open_completion(struct tevent_req *req)
10305 status = cli_openx_recv(req, &fnum);
10308 d_printf("cli_openx_recv returned %s: %d\n",
10310 NT_STATUS_IS_OK(status) ? fnum : -1);
10313 static void chain1_write_completion(struct tevent_req *req)
10317 status = cli_write_andx_recv(req, &written);
10320 d_printf("cli_write_andx_recv returned %s: %d\n",
10322 NT_STATUS_IS_OK(status) ? (int)written : -1);
10325 static void chain1_close_completion(struct tevent_req *req)
10328 bool *done = (bool *)tevent_req_callback_data_void(req);
10330 status = cli_close_recv(req);
10335 d_printf("cli_close returned %s\n", nt_errstr(status));
10338 static bool run_chain1(int dummy)
10340 struct cli_state *cli1;
10341 struct tevent_context *evt = samba_tevent_context_init(NULL);
10342 struct tevent_req *reqs[3], *smbreqs[3];
10344 const char *str = "foobar";
10345 const char *fname = "\\test_chain";
10348 printf("starting chain1 test\n");
10349 if (!torture_open_connection(&cli1, 0)) {
10353 smbXcli_conn_set_sockopt(cli1->conn, sockops);
10355 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
10357 reqs[0] = cli_openx_create(talloc_tos(), evt, cli1, fname,
10358 O_CREAT|O_RDWR, 0, &smbreqs[0]);
10359 if (reqs[0] == NULL) return false;
10360 tevent_req_set_callback(reqs[0], chain1_open_completion, NULL);
10363 reqs[1] = cli_write_andx_create(talloc_tos(), evt, cli1, 0, 0,
10364 (const uint8_t *)str, 0, strlen(str)+1,
10365 smbreqs, 1, &smbreqs[1]);
10366 if (reqs[1] == NULL) return false;
10367 tevent_req_set_callback(reqs[1], chain1_write_completion, NULL);
10369 reqs[2] = cli_smb1_close_create(talloc_tos(), evt, cli1, 0, &smbreqs[2]);
10370 if (reqs[2] == NULL) return false;
10371 tevent_req_set_callback(reqs[2], chain1_close_completion, &done);
10373 status = smb1cli_req_chain_submit(smbreqs, ARRAY_SIZE(smbreqs));
10374 if (!NT_STATUS_IS_OK(status)) {
10379 tevent_loop_once(evt);
10382 torture_close_connection(cli1);
10386 static void chain2_sesssetup_completion(struct tevent_req *req)
10389 status = cli_session_setup_guest_recv(req);
10390 d_printf("sesssetup returned %s\n", nt_errstr(status));
10393 static void chain2_tcon_completion(struct tevent_req *req)
10395 bool *done = (bool *)tevent_req_callback_data_void(req);
10397 status = cli_tcon_andx_recv(req);
10398 d_printf("tcon_and_x returned %s\n", nt_errstr(status));
10402 static bool run_chain2(int dummy)
10404 struct cli_state *cli1;
10405 struct tevent_context *evt = samba_tevent_context_init(NULL);
10406 struct tevent_req *reqs[2], *smbreqs[2];
10409 int flags = CLI_FULL_CONNECTION_FORCE_SMB1;
10411 printf("starting chain2 test\n");
10412 status = cli_start_connection(&cli1, lp_netbios_name(), host, NULL,
10413 port_to_use, SMB_SIGNING_DEFAULT, flags);
10414 if (!NT_STATUS_IS_OK(status)) {
10418 smbXcli_conn_set_sockopt(cli1->conn, sockops);
10420 reqs[0] = cli_session_setup_guest_create(talloc_tos(), evt, cli1,
10422 if (reqs[0] == NULL) return false;
10423 tevent_req_set_callback(reqs[0], chain2_sesssetup_completion, NULL);
10425 reqs[1] = cli_tcon_andx_create(talloc_tos(), evt, cli1, "IPC$",
10426 "?????", NULL, 0, &smbreqs[1]);
10427 if (reqs[1] == NULL) return false;
10428 tevent_req_set_callback(reqs[1], chain2_tcon_completion, &done);
10430 status = smb1cli_req_chain_submit(smbreqs, ARRAY_SIZE(smbreqs));
10431 if (!NT_STATUS_IS_OK(status)) {
10436 tevent_loop_once(evt);
10439 torture_close_connection(cli1);
10444 struct torture_createdel_state {
10445 struct tevent_context *ev;
10446 struct cli_state *cli;
10449 static void torture_createdel_created(struct tevent_req *subreq);
10450 static void torture_createdel_closed(struct tevent_req *subreq);
10452 static struct tevent_req *torture_createdel_send(TALLOC_CTX *mem_ctx,
10453 struct tevent_context *ev,
10454 struct cli_state *cli,
10457 struct tevent_req *req, *subreq;
10458 struct torture_createdel_state *state;
10460 req = tevent_req_create(mem_ctx, &state,
10461 struct torture_createdel_state);
10468 subreq = cli_ntcreate_send(
10469 state, ev, cli, name, 0,
10470 FILE_READ_DATA|FILE_WRITE_DATA|DELETE_ACCESS,
10471 FILE_ATTRIBUTE_NORMAL,
10472 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
10473 FILE_OPEN_IF, FILE_DELETE_ON_CLOSE,
10474 SMB2_IMPERSONATION_IMPERSONATION, 0);
10476 if (tevent_req_nomem(subreq, req)) {
10477 return tevent_req_post(req, ev);
10479 tevent_req_set_callback(subreq, torture_createdel_created, req);
10483 static void torture_createdel_created(struct tevent_req *subreq)
10485 struct tevent_req *req = tevent_req_callback_data(
10486 subreq, struct tevent_req);
10487 struct torture_createdel_state *state = tevent_req_data(
10488 req, struct torture_createdel_state);
10492 status = cli_ntcreate_recv(subreq, &fnum, NULL);
10493 TALLOC_FREE(subreq);
10494 if (tevent_req_nterror(req, status)) {
10495 DEBUG(10, ("cli_ntcreate_recv returned %s\n",
10496 nt_errstr(status)));
10500 subreq = cli_close_send(state, state->ev, state->cli, fnum);
10501 if (tevent_req_nomem(subreq, req)) {
10504 tevent_req_set_callback(subreq, torture_createdel_closed, req);
10507 static void torture_createdel_closed(struct tevent_req *subreq)
10509 struct tevent_req *req = tevent_req_callback_data(
10510 subreq, struct tevent_req);
10513 status = cli_close_recv(subreq);
10514 if (tevent_req_nterror(req, status)) {
10515 DEBUG(10, ("cli_close_recv returned %s\n", nt_errstr(status)));
10518 tevent_req_done(req);
10521 static NTSTATUS torture_createdel_recv(struct tevent_req *req)
10523 return tevent_req_simple_recv_ntstatus(req);
10526 struct torture_createdels_state {
10527 struct tevent_context *ev;
10528 struct cli_state *cli;
10529 const char *base_name;
10533 struct tevent_req **reqs;
10536 static void torture_createdels_done(struct tevent_req *subreq);
10538 static struct tevent_req *torture_createdels_send(TALLOC_CTX *mem_ctx,
10539 struct tevent_context *ev,
10540 struct cli_state *cli,
10541 const char *base_name,
10545 struct tevent_req *req;
10546 struct torture_createdels_state *state;
10549 req = tevent_req_create(mem_ctx, &state,
10550 struct torture_createdels_state);
10556 state->base_name = talloc_strdup(state, base_name);
10557 if (tevent_req_nomem(state->base_name, req)) {
10558 return tevent_req_post(req, ev);
10560 state->num_files = MAX(num_parallel, num_files);
10562 state->received = 0;
10564 state->reqs = talloc_array(state, struct tevent_req *, num_parallel);
10565 if (tevent_req_nomem(state->reqs, req)) {
10566 return tevent_req_post(req, ev);
10569 for (i=0; i<num_parallel; i++) {
10572 name = talloc_asprintf(state, "%s%8.8d", state->base_name,
10574 if (tevent_req_nomem(name, req)) {
10575 return tevent_req_post(req, ev);
10577 state->reqs[i] = torture_createdel_send(
10578 state->reqs, state->ev, state->cli, name);
10579 if (tevent_req_nomem(state->reqs[i], req)) {
10580 return tevent_req_post(req, ev);
10582 name = talloc_move(state->reqs[i], &name);
10583 tevent_req_set_callback(state->reqs[i],
10584 torture_createdels_done, req);
10590 static void torture_createdels_done(struct tevent_req *subreq)
10592 struct tevent_req *req = tevent_req_callback_data(
10593 subreq, struct tevent_req);
10594 struct torture_createdels_state *state = tevent_req_data(
10595 req, struct torture_createdels_state);
10596 size_t num_parallel = talloc_array_length(state->reqs);
10601 status = torture_createdel_recv(subreq);
10602 if (!NT_STATUS_IS_OK(status)){
10603 DEBUG(10, ("torture_createdel_recv returned %s\n",
10604 nt_errstr(status)));
10605 TALLOC_FREE(subreq);
10606 tevent_req_nterror(req, status);
10610 for (i=0; i<num_parallel; i++) {
10611 if (subreq == state->reqs[i]) {
10615 if (i == num_parallel) {
10616 DEBUG(10, ("received something we did not send\n"));
10617 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
10620 TALLOC_FREE(state->reqs[i]);
10622 if (state->sent >= state->num_files) {
10623 tevent_req_done(req);
10627 name = talloc_asprintf(state, "%s%8.8d", state->base_name,
10629 if (tevent_req_nomem(name, req)) {
10632 state->reqs[i] = torture_createdel_send(state->reqs, state->ev,
10634 if (tevent_req_nomem(state->reqs[i], req)) {
10637 name = talloc_move(state->reqs[i], &name);
10638 tevent_req_set_callback(state->reqs[i], torture_createdels_done, req);
10642 static NTSTATUS torture_createdels_recv(struct tevent_req *req)
10644 return tevent_req_simple_recv_ntstatus(req);
10647 struct swallow_notify_state {
10648 struct tevent_context *ev;
10649 struct cli_state *cli;
10651 uint32_t completion_filter;
10653 bool (*fn)(uint32_t action, const char *name, void *priv);
10657 static void swallow_notify_done(struct tevent_req *subreq);
10659 static struct tevent_req *swallow_notify_send(TALLOC_CTX *mem_ctx,
10660 struct tevent_context *ev,
10661 struct cli_state *cli,
10663 uint32_t completion_filter,
10665 bool (*fn)(uint32_t action,
10670 struct tevent_req *req, *subreq;
10671 struct swallow_notify_state *state;
10673 req = tevent_req_create(mem_ctx, &state,
10674 struct swallow_notify_state);
10680 state->fnum = fnum;
10681 state->completion_filter = completion_filter;
10682 state->recursive = recursive;
10684 state->priv = priv;
10686 subreq = cli_notify_send(state, state->ev, state->cli, state->fnum,
10687 0xffff, state->completion_filter,
10689 if (tevent_req_nomem(subreq, req)) {
10690 return tevent_req_post(req, ev);
10692 tevent_req_set_callback(subreq, swallow_notify_done, req);
10696 static void swallow_notify_done(struct tevent_req *subreq)
10698 struct tevent_req *req = tevent_req_callback_data(
10699 subreq, struct tevent_req);
10700 struct swallow_notify_state *state = tevent_req_data(
10701 req, struct swallow_notify_state);
10703 uint32_t i, num_changes;
10704 struct notify_change *changes;
10706 status = cli_notify_recv(subreq, state, &num_changes, &changes);
10707 TALLOC_FREE(subreq);
10708 if (!NT_STATUS_IS_OK(status)) {
10709 DEBUG(10, ("cli_notify_recv returned %s\n",
10710 nt_errstr(status)));
10711 tevent_req_nterror(req, status);
10715 for (i=0; i<num_changes; i++) {
10716 state->fn(changes[i].action, changes[i].name, state->priv);
10718 TALLOC_FREE(changes);
10720 subreq = cli_notify_send(state, state->ev, state->cli, state->fnum,
10721 0xffff, state->completion_filter,
10723 if (tevent_req_nomem(subreq, req)) {
10726 tevent_req_set_callback(subreq, swallow_notify_done, req);
10729 static bool print_notifies(uint32_t action, const char *name, void *priv)
10731 if (DEBUGLEVEL > 5) {
10732 d_printf("%d %s\n", (int)action, name);
10737 static void notify_bench_done(struct tevent_req *req)
10739 int *num_finished = (int *)tevent_req_callback_data_void(req);
10740 *num_finished += 1;
10743 static bool run_notify_bench(int dummy)
10745 const char *dname = "\\notify-bench";
10746 struct tevent_context *ev;
10749 struct tevent_req *req1;
10750 struct tevent_req *req2 = NULL;
10751 int i, num_unc_names;
10752 int num_finished = 0;
10754 printf("starting notify-bench test\n");
10756 if (use_multishare_conn) {
10758 unc_list = file_lines_load(multishare_conn_fname,
10759 &num_unc_names, 0, NULL);
10760 if (!unc_list || num_unc_names <= 0) {
10761 d_printf("Failed to load unc names list from '%s'\n",
10762 multishare_conn_fname);
10765 TALLOC_FREE(unc_list);
10770 ev = samba_tevent_context_init(talloc_tos());
10772 d_printf("tevent_context_init failed\n");
10776 for (i=0; i<num_unc_names; i++) {
10777 struct cli_state *cli;
10780 base_fname = talloc_asprintf(talloc_tos(), "%s\\file%3.3d.",
10782 if (base_fname == NULL) {
10786 if (!torture_open_connection(&cli, i)) {
10790 status = cli_ntcreate(cli, dname, 0,
10791 MAXIMUM_ALLOWED_ACCESS,
10792 0, FILE_SHARE_READ|FILE_SHARE_WRITE|
10794 FILE_OPEN_IF, FILE_DIRECTORY_FILE, 0,
10797 if (!NT_STATUS_IS_OK(status)) {
10798 d_printf("Could not create %s: %s\n", dname,
10799 nt_errstr(status));
10803 req1 = swallow_notify_send(talloc_tos(), ev, cli, dnum,
10804 FILE_NOTIFY_CHANGE_FILE_NAME |
10805 FILE_NOTIFY_CHANGE_DIR_NAME |
10806 FILE_NOTIFY_CHANGE_ATTRIBUTES |
10807 FILE_NOTIFY_CHANGE_LAST_WRITE,
10808 false, print_notifies, NULL);
10809 if (req1 == NULL) {
10810 d_printf("Could not create notify request\n");
10814 req2 = torture_createdels_send(talloc_tos(), ev, cli,
10815 base_fname, 10, torture_numops);
10816 if (req2 == NULL) {
10817 d_printf("Could not create createdels request\n");
10820 TALLOC_FREE(base_fname);
10822 tevent_req_set_callback(req2, notify_bench_done,
10826 while (num_finished < num_unc_names) {
10828 ret = tevent_loop_once(ev);
10830 d_printf("tevent_loop_once failed\n");
10835 if (!tevent_req_poll(req2, ev)) {
10836 d_printf("tevent_req_poll failed\n");
10839 status = torture_createdels_recv(req2);
10840 d_printf("torture_createdels_recv returned %s\n", nt_errstr(status));
10845 static bool run_mangle1(int dummy)
10847 struct cli_state *cli;
10848 const char *fname = "this_is_a_long_fname_to_be_mangled.txt";
10852 time_t change_time, access_time, write_time;
10856 printf("starting mangle1 test\n");
10857 if (!torture_open_connection(&cli, 0)) {
10861 smbXcli_conn_set_sockopt(cli->conn, sockops);
10863 status = cli_ntcreate(cli, fname, 0, GENERIC_ALL_ACCESS|DELETE_ACCESS,
10864 FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
10865 0, 0, &fnum, NULL);
10866 if (!NT_STATUS_IS_OK(status)) {
10867 d_printf("open %s failed: %s\n", fname, nt_errstr(status));
10870 cli_close(cli, fnum);
10872 status = cli_qpathinfo_alt_name(cli, fname, alt_name);
10873 if (!NT_STATUS_IS_OK(status)) {
10874 d_printf("cli_qpathinfo_alt_name failed: %s\n",
10875 nt_errstr(status));
10878 d_printf("alt_name: %s\n", alt_name);
10880 status = cli_openx(cli, alt_name, O_RDONLY, DENY_NONE, &fnum);
10881 if (!NT_STATUS_IS_OK(status)) {
10882 d_printf("cli_openx(%s) failed: %s\n", alt_name,
10883 nt_errstr(status));
10886 cli_close(cli, fnum);
10888 status = cli_qpathinfo1(cli, alt_name, &change_time, &access_time,
10889 &write_time, &size, &attr);
10890 if (!NT_STATUS_IS_OK(status)) {
10891 d_printf("cli_qpathinfo1(%s) failed: %s\n", alt_name,
10892 nt_errstr(status));
10899 static NTSTATUS mangle_illegal_list_shortname_fn(const char *mntpoint,
10900 struct file_info *f,
10904 if (f->short_name == NULL) {
10905 return NT_STATUS_OK;
10908 if (strlen(f->short_name) == 0) {
10909 return NT_STATUS_OK;
10912 printf("unexpected shortname: %s\n", f->short_name);
10914 return NT_STATUS_OBJECT_NAME_INVALID;
10917 static NTSTATUS mangle_illegal_list_name_fn(const char *mntpoint,
10918 struct file_info *f,
10922 char *name = state;
10924 printf("name: %s\n", f->name);
10925 fstrcpy(name, f->name);
10926 return NT_STATUS_OK;
10929 static bool run_mangle_illegal(int dummy)
10931 struct cli_state *cli = NULL;
10932 struct cli_state *cli_posix = NULL;
10933 const char *fname = "\\MANGLE_ILLEGAL\\this_is_a_long_fname_to_be_mangled.txt";
10934 const char *illegal_fname = "MANGLE_ILLEGAL/foo:bar";
10935 char *mangled_path = NULL;
10941 printf("starting mangle-illegal test\n");
10943 if (!torture_open_connection(&cli, 0)) {
10947 smbXcli_conn_set_sockopt(cli->conn, sockops);
10949 if (!torture_open_connection(&cli_posix, 0)) {
10953 smbXcli_conn_set_sockopt(cli_posix->conn, sockops);
10955 status = torture_setup_unix_extensions(cli_posix);
10956 if (!NT_STATUS_IS_OK(status)) {
10960 cli_rmdir(cli, "\\MANGLE_ILLEGAL");
10961 status = cli_mkdir(cli, "\\MANGLE_ILLEGAL");
10962 if (!NT_STATUS_IS_OK(status)) {
10963 printf("mkdir1 failed : %s\n", nt_errstr(status));
10968 * Create a file with illegal NTFS characters and test that we
10969 * get a usable mangled name
10972 cli_setatr(cli_posix, illegal_fname, 0, 0);
10973 cli_posix_unlink(cli_posix, illegal_fname);
10975 status = cli_posix_open(cli_posix, illegal_fname, O_RDWR|O_CREAT|O_EXCL,
10977 if (!NT_STATUS_IS_OK(status)) {
10978 printf("POSIX create of %s failed (%s)\n",
10979 illegal_fname, nt_errstr(status));
10983 status = cli_close(cli_posix, fnum);
10984 if (!NT_STATUS_IS_OK(status)) {
10985 printf("close failed (%s)\n", nt_errstr(status));
10989 status = cli_list(cli, "\\MANGLE_ILLEGAL\\*", 0, mangle_illegal_list_name_fn, &name);
10990 if (!NT_STATUS_IS_OK(status)) {
10991 d_printf("cli_list failed: %s\n", nt_errstr(status));
10995 mangled_path = talloc_asprintf(talloc_tos(), "\\MANGLE_ILLEGAL\\%s", name);
10996 if (mangled_path == NULL) {
11000 status = cli_openx(cli, mangled_path, O_RDONLY, DENY_NONE, &fnum);
11001 if (!NT_STATUS_IS_OK(status)) {
11002 d_printf("cli_openx(%s) failed: %s\n", mangled_path, nt_errstr(status));
11003 TALLOC_FREE(mangled_path);
11006 TALLOC_FREE(mangled_path);
11007 cli_close(cli, fnum);
11009 cli_setatr(cli_posix, illegal_fname, 0, 0);
11010 cli_posix_unlink(cli_posix, illegal_fname);
11013 * Create a file with a long name and check that we got *no* short name.
11016 status = cli_ntcreate(cli, fname, 0, GENERIC_ALL_ACCESS|DELETE_ACCESS,
11017 FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
11018 0, 0, &fnum, NULL);
11019 if (!NT_STATUS_IS_OK(status)) {
11020 d_printf("open %s failed: %s\n", fname, nt_errstr(status));
11023 cli_close(cli, fnum);
11025 status = cli_list(cli, fname, 0, mangle_illegal_list_shortname_fn, &alt_name);
11026 if (!NT_STATUS_IS_OK(status)) {
11027 d_printf("cli_list failed\n");
11031 cli_unlink(cli, fname, 0);
11032 cli_rmdir(cli, "\\MANGLE_ILLEGAL");
11034 if (!torture_close_connection(cli_posix)) {
11038 if (!torture_close_connection(cli)) {
11045 static size_t null_source(uint8_t *buf, size_t n, void *priv)
11047 size_t *to_pull = (size_t *)priv;
11048 size_t thistime = *to_pull;
11050 thistime = MIN(thistime, n);
11051 if (thistime == 0) {
11055 memset(buf, 0, thistime);
11056 *to_pull -= thistime;
11060 static bool run_windows_write(int dummy)
11062 struct cli_state *cli1;
11066 const char *fname = "\\writetest.txt";
11067 struct timeval start_time;
11072 printf("starting windows_write test\n");
11073 if (!torture_open_connection(&cli1, 0)) {
11077 status = cli_openx(cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE, &fnum);
11078 if (!NT_STATUS_IS_OK(status)) {
11079 printf("open failed (%s)\n", nt_errstr(status));
11083 smbXcli_conn_set_sockopt(cli1->conn, sockops);
11085 start_time = timeval_current();
11087 for (i=0; i<torture_numops; i++) {
11089 off_t start = i * torture_blocksize;
11090 size_t to_pull = torture_blocksize - 1;
11092 status = cli_writeall(cli1, fnum, 0, &c,
11093 start + torture_blocksize - 1, 1, NULL);
11094 if (!NT_STATUS_IS_OK(status)) {
11095 printf("cli_write failed: %s\n", nt_errstr(status));
11099 status = cli_push(cli1, fnum, 0, i * torture_blocksize, torture_blocksize,
11100 null_source, &to_pull);
11101 if (!NT_STATUS_IS_OK(status)) {
11102 printf("cli_push returned: %s\n", nt_errstr(status));
11107 seconds = timeval_elapsed(&start_time);
11108 kbytes = (double)torture_blocksize * torture_numops;
11111 printf("Wrote %d kbytes in %.2f seconds: %d kb/sec\n", (int)kbytes,
11112 (double)seconds, (int)(kbytes/seconds));
11116 cli_close(cli1, fnum);
11117 cli_unlink(cli1, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
11118 torture_close_connection(cli1);
11122 static size_t calc_expected_return(struct cli_state *cli, size_t len_requested)
11124 size_t max_pdu = 0x1FFFF;
11126 if (cli->server_posix_capabilities & CIFS_UNIX_LARGE_READ_CAP) {
11127 max_pdu = 0xFFFFFF;
11130 if (smb1cli_conn_signing_is_active(cli->conn)) {
11134 if (smb1cli_conn_encryption_on(cli->conn)) {
11135 max_pdu = CLI_BUFFER_SIZE;
11138 if ((len_requested & 0xFFFF0000) == 0xFFFF0000) {
11139 len_requested &= 0xFFFF;
11142 return MIN(len_requested,
11143 max_pdu - (MIN_SMB_SIZE + VWV(12) + 1 /* padding byte */));
11146 static bool check_read_call(struct cli_state *cli,
11149 size_t len_requested)
11152 struct tevent_req *subreq = NULL;
11153 ssize_t len_read = 0;
11154 size_t len_expected = 0;
11155 struct tevent_context *ev = NULL;
11157 ev = samba_tevent_context_init(talloc_tos());
11162 subreq = cli_read_andx_send(talloc_tos(),
11169 if (!tevent_req_poll_ntstatus(subreq, ev, &status)) {
11173 status = cli_read_andx_recv(subreq, &len_read, &buf);
11174 if (!NT_STATUS_IS_OK(status)) {
11175 d_printf("cli_read_andx_recv failed: %s\n", nt_errstr(status));
11179 TALLOC_FREE(subreq);
11182 len_expected = calc_expected_return(cli, len_requested);
11184 if (len_expected > 0x10000 && len_read == 0x10000) {
11185 /* Windows servers only return a max of 0x10000,
11186 doesn't matter if you set CAP_LARGE_READX in
11187 the client sessionsetupX call or not. */
11188 d_printf("Windows server - returned 0x10000 on a read of 0x%x\n",
11189 (unsigned int)len_requested);
11190 } else if (len_read != len_expected) {
11191 d_printf("read of 0x%x failed: got 0x%x, expected 0x%x\n",
11192 (unsigned int)len_requested,
11193 (unsigned int)len_read,
11194 (unsigned int)len_expected);
11197 d_printf("Correct read reply.\n");
11203 /* Test large readX variants. */
11204 static bool large_readx_tests(struct cli_state *cli,
11208 /* A read of 0xFFFF0001 should *always* return 1 byte. */
11209 if (check_read_call(cli, fnum, buf, 0xFFFF0001) == false) {
11212 /* A read of 0x10000 should return 0x10000 bytes. */
11213 if (check_read_call(cli, fnum, buf, 0x10000) == false) {
11216 /* A read of 0x10000 should return 0x10001 bytes. */
11217 if (check_read_call(cli, fnum, buf, 0x10001) == false) {
11220 /* A read of 0x1FFFF - (MIN_SMB_SIZE + VWV(12) should return
11221 the requested number of bytes. */
11222 if (check_read_call(cli, fnum, buf, 0x1FFFF - (MIN_SMB_SIZE + VWV(12))) == false) {
11225 /* A read of 1MB should return 1MB bytes (on Samba). */
11226 if (check_read_call(cli, fnum, buf, 0x100000) == false) {
11230 if (check_read_call(cli, fnum, buf, 0x20001) == false) {
11233 if (check_read_call(cli, fnum, buf, 0x22000001) == false) {
11236 if (check_read_call(cli, fnum, buf, 0xFFFE0001) == false) {
11242 static bool run_large_readx(int dummy)
11244 uint8_t *buf = NULL;
11245 struct cli_state *cli1 = NULL;
11246 struct cli_state *cli2 = NULL;
11247 bool correct = false;
11248 const char *fname = "\\large_readx.dat";
11250 uint16_t fnum1 = UINT16_MAX;
11251 uint32_t normal_caps = 0;
11252 size_t file_size = 20*1024*1024;
11253 TALLOC_CTX *frame = talloc_stackframe();
11257 enum smb_signing_setting signing_setting;
11258 enum protocol_types protocol;
11262 .signing_setting = SMB_SIGNING_IF_REQUIRED,
11263 .protocol = PROTOCOL_NT1,
11265 .name = "NT1 - SIGNING_REQUIRED",
11266 .signing_setting = SMB_SIGNING_REQUIRED,
11267 .protocol = PROTOCOL_NT1,
11271 printf("starting large_readx test\n");
11273 if (!torture_open_connection(&cli1, 0)) {
11277 normal_caps = smb1cli_conn_capabilities(cli1->conn);
11279 if (!(normal_caps & CAP_LARGE_READX)) {
11280 d_printf("Server doesn't have CAP_LARGE_READX 0x%x\n",
11281 (unsigned int)normal_caps);
11285 /* Create a file of size 4MB. */
11286 status = cli_ntcreate(cli1, fname, 0, GENERIC_ALL_ACCESS,
11287 FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
11288 0, 0, &fnum1, NULL);
11290 if (!NT_STATUS_IS_OK(status)) {
11291 d_printf("open %s failed: %s\n", fname, nt_errstr(status));
11295 /* Write file_size bytes. */
11296 buf = talloc_zero_array(frame, uint8_t, file_size);
11301 status = cli_writeall(cli1,
11308 if (!NT_STATUS_IS_OK(status)) {
11309 d_printf("cli_writeall failed: %s\n", nt_errstr(status));
11313 status = cli_close(cli1, fnum1);
11314 if (!NT_STATUS_IS_OK(status)) {
11315 d_printf("cli_close failed: %s\n", nt_errstr(status));
11319 fnum1 = UINT16_MAX;
11321 for (i=0; i < ARRAY_SIZE(runs); i++) {
11322 enum smb_signing_setting saved_signing_setting = signing_state;
11323 uint16_t fnum2 = -1;
11326 (runs[i].signing_setting == SMB_SIGNING_REQUIRED))
11328 d_printf("skip[%u] - %s\n", (unsigned)i, runs[i].name);
11332 d_printf("run[%u] - %s\n", (unsigned)i, runs[i].name);
11334 signing_state = runs[i].signing_setting;
11335 cli2 = open_nbt_connection();
11336 signing_state = saved_signing_setting;
11337 if (cli2 == NULL) {
11341 status = smbXcli_negprot(cli2->conn,
11345 if (!NT_STATUS_IS_OK(status)) {
11349 status = cli_session_setup_creds(cli2, torture_creds);
11350 if (!NT_STATUS_IS_OK(status)) {
11354 status = cli_tree_connect(cli2,
11358 if (!NT_STATUS_IS_OK(status)) {
11362 cli_set_timeout(cli2, 120000); /* set a really long timeout (2 minutes) */
11364 normal_caps = smb1cli_conn_capabilities(cli2->conn);
11366 if (!(normal_caps & CAP_LARGE_READX)) {
11367 d_printf("Server doesn't have CAP_LARGE_READX 0x%x\n",
11368 (unsigned int)normal_caps);
11373 if (force_cli_encryption(cli2, share) == false) {
11376 } else if (SERVER_HAS_UNIX_CIFS(cli2)) {
11377 uint16_t major, minor;
11378 uint32_t caplow, caphigh;
11380 status = cli_unix_extensions_version(cli2,
11382 &caplow, &caphigh);
11383 if (!NT_STATUS_IS_OK(status)) {
11388 status = cli_ntcreate(cli2, fname, 0, FILE_READ_DATA,
11389 FILE_ATTRIBUTE_NORMAL, 0, FILE_OPEN,
11390 0, 0, &fnum2, NULL);
11391 if (!NT_STATUS_IS_OK(status)) {
11392 d_printf("Second open %s failed: %s\n", fname, nt_errstr(status));
11396 /* All reads must return less than file_size bytes. */
11397 if (!large_readx_tests(cli2, fnum2, buf)) {
11401 status = cli_close(cli2, fnum2);
11402 if (!NT_STATUS_IS_OK(status)) {
11403 d_printf("cli_close failed: %s\n", nt_errstr(status));
11408 if (!torture_close_connection(cli2)) {
11415 printf("Success on large_readx test\n");
11420 if (!torture_close_connection(cli2)) {
11426 if (fnum1 != UINT16_MAX) {
11427 status = cli_close(cli1, fnum1);
11428 if (!NT_STATUS_IS_OK(status)) {
11429 d_printf("cli_close failed: %s\n", nt_errstr(status));
11431 fnum1 = UINT16_MAX;
11434 status = cli_unlink(cli1, fname,
11435 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
11436 if (!NT_STATUS_IS_OK(status)) {
11437 printf("unlink failed (%s)\n", nt_errstr(status));
11440 if (!torture_close_connection(cli1)) {
11445 TALLOC_FREE(frame);
11447 printf("finished large_readx test\n");
11451 static NTSTATUS msdfs_attribute_list_fn(const char *mnt,
11452 struct file_info *finfo,
11454 void *private_data)
11456 uint32_t *p_attr = (uint32_t *)private_data;
11458 if (strequal(finfo->name, test_filename)) {
11459 *p_attr = finfo->attr;
11462 return NT_STATUS_OK;
11465 static bool run_msdfs_attribute(int dummy)
11467 static struct cli_state *cli;
11468 bool correct = false;
11472 printf("Starting MSDFS-ATTRIBUTE test\n");
11474 if (test_filename == NULL || test_filename[0] == '\0') {
11475 printf("MSDFS-ATTRIBUTE test "
11476 "needs -f filename-of-msdfs-link\n");
11481 * NB. We use torture_open_connection_flags() not
11482 * torture_open_connection() as the latter forces
11485 if (!torture_open_connection_flags(&cli, 0, 0)) {
11489 smbXcli_conn_set_sockopt(cli->conn, sockops);
11491 status = cli_list(cli,
11493 FILE_ATTRIBUTE_DIRECTORY,
11494 msdfs_attribute_list_fn,
11497 if (!NT_STATUS_IS_OK(status)) {
11498 printf("cli_list failed with %s\n",
11499 nt_errstr(status));
11502 if ((attr & FILE_ATTRIBUTE_REPARSE_POINT) == 0) {
11503 printf("file %s should have "
11504 "FILE_ATTRIBUTE_REPARSE_POINT set. attr = 0x%x\n",
11506 (unsigned int)attr);
11510 if ((attr & FILE_ATTRIBUTE_DIRECTORY) == 0) {
11511 printf("file %s should have "
11512 "FILE_ATTRIBUTE_DIRECTORY set. attr = 0x%x\n",
11514 (unsigned int)attr);
11522 torture_close_connection(cli);
11526 static bool run_cli_echo(int dummy)
11528 struct cli_state *cli;
11531 printf("starting cli_echo test\n");
11532 if (!torture_open_connection(&cli, 0)) {
11535 smbXcli_conn_set_sockopt(cli->conn, sockops);
11537 status = cli_echo(cli, 5, data_blob_const("hello", 5));
11539 d_printf("cli_echo returned %s\n", nt_errstr(status));
11541 torture_close_connection(cli);
11542 return NT_STATUS_IS_OK(status);
11545 static int splice_status(off_t written, void *priv)
11550 static bool run_cli_splice(int dummy)
11552 uint8_t *buf = NULL;
11553 struct cli_state *cli1 = NULL;
11554 bool correct = false;
11555 const char *fname_src = "\\splice_src.dat";
11556 const char *fname_dst = "\\splice_dst.dat";
11558 uint16_t fnum1 = UINT16_MAX;
11559 uint16_t fnum2 = UINT16_MAX;
11560 size_t file_size = 2*1024*1024;
11561 size_t splice_size = 1*1024*1024 + 713;
11562 uint8_t digest1[16], digest2[16];
11565 TALLOC_CTX *frame = talloc_stackframe();
11567 printf("starting cli_splice test\n");
11569 if (!torture_open_connection(&cli1, 0)) {
11573 cli_unlink(cli1, fname_src,
11574 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
11575 cli_unlink(cli1, fname_dst,
11576 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
11578 /* Create a file */
11579 status = cli_ntcreate(cli1, fname_src, 0, GENERIC_ALL_ACCESS,
11580 FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
11581 0, 0, &fnum1, NULL);
11583 if (!NT_STATUS_IS_OK(status)) {
11584 d_printf("open %s failed: %s\n", fname_src, nt_errstr(status));
11588 /* Write file_size bytes - must be bigger than splice_size. */
11589 buf = talloc_zero_array(frame, uint8_t, file_size);
11591 d_printf("talloc_fail\n");
11595 /* Fill it with random numbers. */
11596 generate_random_buffer(buf, file_size);
11598 /* MD5 the first 1MB + 713 bytes. */
11599 gnutls_hash_fast(GNUTLS_DIG_MD5,
11604 status = cli_writeall(cli1,
11611 if (!NT_STATUS_IS_OK(status)) {
11612 d_printf("cli_writeall failed: %s\n", nt_errstr(status));
11616 status = cli_ntcreate(cli1, fname_dst, 0, GENERIC_ALL_ACCESS,
11617 FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
11618 0, 0, &fnum2, NULL);
11620 if (!NT_STATUS_IS_OK(status)) {
11621 d_printf("open %s failed: %s\n", fname_dst, nt_errstr(status));
11625 /* Now splice 1MB + 713 bytes. */
11626 status = cli_splice(cli1,
11637 if (!NT_STATUS_IS_OK(status)) {
11638 d_printf("cli_splice failed: %s\n", nt_errstr(status));
11642 /* Clear the old buffer. */
11643 memset(buf, '\0', file_size);
11645 /* Read the new file. */
11646 status = cli_read(cli1, fnum2, (char *)buf, 0, splice_size, &nread);
11647 if (!NT_STATUS_IS_OK(status)) {
11648 d_printf("cli_read failed: %s\n", nt_errstr(status));
11651 if (nread != splice_size) {
11652 d_printf("bad read of 0x%x, should be 0x%x\n",
11653 (unsigned int)nread,
11654 (unsigned int)splice_size);
11658 /* MD5 the first 1MB + 713 bytes. */
11659 gnutls_hash_fast(GNUTLS_DIG_MD5,
11664 /* Must be the same. */
11665 if (memcmp(digest1, digest2, 16) != 0) {
11666 d_printf("bad MD5 compare\n");
11671 printf("Success on cli_splice test\n");
11676 if (fnum1 != UINT16_MAX) {
11677 cli_close(cli1, fnum1);
11679 if (fnum2 != UINT16_MAX) {
11680 cli_close(cli1, fnum2);
11683 cli_unlink(cli1, fname_src,
11684 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
11685 cli_unlink(cli1, fname_dst,
11686 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
11688 if (!torture_close_connection(cli1)) {
11693 TALLOC_FREE(frame);
11697 static bool run_uid_regression_test(int dummy)
11699 static struct cli_state *cli;
11702 bool correct = True;
11703 struct smbXcli_tcon *orig_tcon = NULL;
11706 printf("starting uid regression test\n");
11708 if (!torture_open_connection(&cli, 0)) {
11712 smbXcli_conn_set_sockopt(cli->conn, sockops);
11714 /* Ok - now save then logoff our current user. */
11715 old_vuid = cli_state_get_uid(cli);
11717 status = cli_ulogoff(cli);
11718 if (!NT_STATUS_IS_OK(status)) {
11719 d_printf("(%s) cli_ulogoff failed: %s\n",
11720 __location__, nt_errstr(status));
11725 cli_state_set_uid(cli, old_vuid);
11727 /* Try an operation. */
11728 status = cli_mkdir(cli, "\\uid_reg_test");
11729 if (NT_STATUS_IS_OK(status)) {
11730 d_printf("(%s) cli_mkdir succeeded\n",
11735 /* Should be bad uid. */
11736 if (!check_error(__LINE__, status, ERRSRV, ERRbaduid,
11737 NT_STATUS_USER_SESSION_DELETED)) {
11743 old_cnum = cli_state_get_tid(cli);
11744 orig_tcon = cli_state_save_tcon(cli);
11745 if (orig_tcon == NULL) {
11750 /* Now try a SMBtdis with the invalid vuid set to zero. */
11751 cli_state_set_uid(cli, 0);
11753 /* This should succeed. */
11754 status = cli_tdis(cli);
11756 if (NT_STATUS_IS_OK(status)) {
11757 d_printf("First tdis with invalid vuid should succeed.\n");
11759 d_printf("First tdis failed (%s)\n", nt_errstr(status));
11761 cli_state_restore_tcon(cli, orig_tcon);
11765 cli_state_restore_tcon(cli, orig_tcon);
11766 cli_state_set_uid(cli, old_vuid);
11767 cli_state_set_tid(cli, old_cnum);
11769 /* This should fail. */
11770 status = cli_tdis(cli);
11771 if (NT_STATUS_IS_OK(status)) {
11772 d_printf("Second tdis with invalid vuid should fail - succeeded instead !.\n");
11776 /* Should be bad tid. */
11777 if (!check_error(__LINE__, status, ERRSRV, ERRinvnid,
11778 NT_STATUS_NETWORK_NAME_DELETED)) {
11784 cli_rmdir(cli, "\\uid_reg_test");
11793 static const char *illegal_chars = "*\\/?<>|\":";
11794 static char force_shortname_chars[] = " +,.[];=\177";
11796 static NTSTATUS shortname_del_fn(const char *mnt, struct file_info *finfo,
11797 const char *mask, void *state)
11799 struct cli_state *pcli = (struct cli_state *)state;
11801 NTSTATUS status = NT_STATUS_OK;
11803 slprintf(fname, sizeof(fname), "\\shortname\\%s", finfo->name);
11805 if (strcmp(finfo->name, ".") == 0 || strcmp(finfo->name, "..") == 0)
11806 return NT_STATUS_OK;
11808 if (finfo->attr & FILE_ATTRIBUTE_DIRECTORY) {
11809 status = cli_rmdir(pcli, fname);
11810 if (!NT_STATUS_IS_OK(status)) {
11811 printf("del_fn: failed to rmdir %s\n,", fname );
11814 status = cli_unlink(pcli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
11815 if (!NT_STATUS_IS_OK(status)) {
11816 printf("del_fn: failed to unlink %s\n,", fname );
11828 static NTSTATUS shortname_list_fn(const char *mnt, struct file_info *finfo,
11829 const char *name, void *state)
11831 struct sn_state *s = (struct sn_state *)state;
11835 printf("shortname list: i = %d, name = |%s|, shortname = |%s|\n",
11836 i, finfo->name, finfo->short_name);
11839 if (strchr(force_shortname_chars, i)) {
11840 if (!finfo->short_name) {
11841 /* Shortname not created when it should be. */
11842 d_printf("(%s) ERROR: Shortname was not created for file %s containing %d\n",
11843 __location__, finfo->name, i);
11846 } else if (finfo->short_name){
11847 /* Shortname created when it should not be. */
11848 d_printf("(%s) ERROR: Shortname %s was created for file %s\n",
11849 __location__, finfo->short_name, finfo->name);
11853 return NT_STATUS_OK;
11856 static bool run_shortname_test(int dummy)
11858 static struct cli_state *cli;
11859 bool correct = True;
11865 printf("starting shortname test\n");
11867 if (!torture_open_connection(&cli, 0)) {
11871 smbXcli_conn_set_sockopt(cli->conn, sockops);
11873 cli_list(cli, "\\shortname\\*", 0, shortname_del_fn, cli);
11874 cli_list(cli, "\\shortname\\*", FILE_ATTRIBUTE_DIRECTORY, shortname_del_fn, cli);
11875 cli_rmdir(cli, "\\shortname");
11877 status = cli_mkdir(cli, "\\shortname");
11878 if (!NT_STATUS_IS_OK(status)) {
11879 d_printf("(%s) cli_mkdir of \\shortname failed: %s\n",
11880 __location__, nt_errstr(status));
11885 if (strlcpy(fname, "\\shortname\\", sizeof(fname)) >= sizeof(fname)) {
11889 if (strlcat(fname, "test .txt", sizeof(fname)) >= sizeof(fname)) {
11896 for (i = 32; i < 128; i++) {
11897 uint16_t fnum = (uint16_t)-1;
11901 if (strchr(illegal_chars, i)) {
11906 status = cli_ntcreate(cli, fname, 0, GENERIC_ALL_ACCESS, FILE_ATTRIBUTE_NORMAL,
11907 FILE_SHARE_READ|FILE_SHARE_WRITE,
11908 FILE_OVERWRITE_IF, 0, 0, &fnum, NULL);
11909 if (!NT_STATUS_IS_OK(status)) {
11910 d_printf("(%s) cli_nt_create of %s failed: %s\n",
11911 __location__, fname, nt_errstr(status));
11915 cli_close(cli, fnum);
11918 status = cli_list(cli, "\\shortname\\test*.*", 0,
11919 shortname_list_fn, &s);
11920 if (s.matched != 1) {
11921 d_printf("(%s) failed to list %s: %s\n",
11922 __location__, fname, nt_errstr(status));
11927 status = cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
11928 if (!NT_STATUS_IS_OK(status)) {
11929 d_printf("(%s) failed to delete %s: %s\n",
11930 __location__, fname, nt_errstr(status));
11943 cli_list(cli, "\\shortname\\*", 0, shortname_del_fn, cli);
11944 cli_list(cli, "\\shortname\\*", FILE_ATTRIBUTE_DIRECTORY, shortname_del_fn, cli);
11945 cli_rmdir(cli, "\\shortname");
11946 torture_close_connection(cli);
11950 TLDAPRC callback_code;
11952 static void pagedsearch_cb(struct tevent_req *req)
11955 struct tldap_message *msg;
11958 rc = tldap_search_paged_recv(req, talloc_tos(), &msg);
11959 if (!TLDAP_RC_IS_SUCCESS(rc)) {
11960 d_printf("tldap_search_paged_recv failed: %s\n",
11961 tldap_rc2string(rc));
11962 callback_code = rc;
11965 if (tldap_msg_type(msg) != TLDAP_RES_SEARCH_ENTRY) {
11969 if (!tldap_entry_dn(msg, &dn)) {
11970 d_printf("tldap_entry_dn failed\n");
11973 d_printf("%s\n", dn);
11977 enum tldap_extended_val {
11984 * Construct an extended dn control with either no value, 0 or 1
11986 * No value and 0 are equivalent (non-hyphenated GUID)
11987 * 1 has the hyphenated GUID
11989 static struct tldap_control *
11990 tldap_build_extended_control(enum tldap_extended_val val)
11992 struct tldap_control empty_control;
11993 struct asn1_data *data;
11995 ZERO_STRUCT(empty_control);
11997 if (val != EXTENDED_NONE) {
11998 data = asn1_init(talloc_tos(), ASN1_MAX_TREE_DEPTH);
12004 if (!asn1_push_tag(data, ASN1_SEQUENCE(0))) {
12008 if (!asn1_write_Integer(data, (int)val)) {
12012 if (!asn1_pop_tag(data)) {
12016 if (!asn1_blob(data, &empty_control.value)) {
12021 empty_control.oid = "1.2.840.113556.1.4.529";
12022 empty_control.critical = true;
12024 return tldap_add_control(talloc_tos(), NULL, 0, &empty_control);
12028 static bool tldap_test_dn_guid_format(struct tldap_context *ld, const char *basedn,
12029 enum tldap_extended_val control_val)
12031 struct tldap_control *control = tldap_build_extended_control(control_val);
12033 struct tldap_message **msg;
12036 rc = tldap_search(ld, basedn, TLDAP_SCOPE_BASE,
12037 "(objectClass=*)", NULL, 0, 0,
12039 0, 0, 0, 0, talloc_tos(), &msg);
12040 if (!TLDAP_RC_IS_SUCCESS(rc)) {
12041 d_printf("tldap_search for domain DN failed: %s\n",
12042 tldap_errstr(talloc_tos(), ld, rc));
12046 if (!tldap_entry_dn(msg[0], &dn)) {
12047 d_printf("tldap_search domain DN fetch failed: %s\n",
12048 tldap_errstr(talloc_tos(), ld, rc));
12052 d_printf("%s\n", dn);
12055 uint32_t time_mid, time_hi_and_version;
12056 uint32_t clock_seq[2];
12060 switch (control_val) {
12061 case EXTENDED_NONE:
12062 case EXTENDED_ZERO:
12064 * When reading GUIDs with hyphens, scanf will treat
12065 * hyphen as a hex character (and counts as part of the
12066 * width). This creates leftover GUID string which we
12067 * check will for with 'next' and closing '>'.
12069 if (12 == sscanf(dn, "<GUID=%08x%04x%04x%02x%02x%02x%02x%02x%02x%02x%02x>%c",
12070 &time_low, &time_mid,
12071 &time_hi_and_version, &clock_seq[0],
12072 &clock_seq[1], &node[0], &node[1],
12073 &node[2], &node[3], &node[4],
12074 &node[5], &next)) {
12075 /* This GUID is good */
12077 d_printf("GUID format in control (no hyphens) doesn't match output\n");
12083 if (12 == sscanf(dn,
12084 "<GUID=%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x>%c",
12085 &time_low, &time_mid,
12086 &time_hi_and_version, &clock_seq[0],
12087 &clock_seq[1], &node[0], &node[1],
12088 &node[2], &node[3], &node[4],
12089 &node[5], &next)) {
12090 /* This GUID is good */
12092 d_printf("GUID format in control (with hyphens) doesn't match output\n");
12105 static bool run_tldap(int dummy)
12107 struct tldap_context *ld;
12111 struct sockaddr_storage addr;
12112 struct tevent_context *ev;
12113 struct tevent_req *req;
12115 const char *filter;
12117 if (!resolve_name(host, &addr, 0, false)) {
12118 d_printf("could not find host %s\n", host);
12121 status = open_socket_out(&addr, 389, 9999, &fd);
12122 if (!NT_STATUS_IS_OK(status)) {
12123 d_printf("open_socket_out failed: %s\n", nt_errstr(status));
12127 ld = tldap_context_create(talloc_tos(), fd);
12130 d_printf("tldap_context_create failed\n");
12134 rc = tldap_fetch_rootdse(ld);
12135 if (!TLDAP_RC_IS_SUCCESS(rc)) {
12136 d_printf("tldap_fetch_rootdse failed: %s\n",
12137 tldap_errstr(talloc_tos(), ld, rc));
12141 basedn = tldap_talloc_single_attribute(
12142 tldap_rootdse(ld), "defaultNamingContext", talloc_tos());
12143 if (basedn == NULL) {
12144 d_printf("no defaultNamingContext\n");
12147 d_printf("defaultNamingContext: %s\n", basedn);
12149 ev = samba_tevent_context_init(talloc_tos());
12151 d_printf("tevent_context_init failed\n");
12155 rc = tldap_gensec_bind(ld, torture_creds, "ldap", host, NULL,
12156 loadparm_init_s3(talloc_tos(),
12157 loadparm_s3_helpers()),
12158 GENSEC_FEATURE_SIGN | GENSEC_FEATURE_SEAL);
12160 if (!TLDAP_RC_IS_SUCCESS(rc)) {
12161 d_printf("tldap_gensec_bind failed\n");
12165 callback_code = TLDAP_SUCCESS;
12167 req = tldap_search_paged_send(talloc_tos(), ev, ld, basedn,
12168 TLDAP_SCOPE_SUB, "(objectclass=*)",
12170 NULL, 0, NULL, 0, 0, 0, 0, 5);
12172 d_printf("tldap_search_paged_send failed\n");
12175 tevent_req_set_callback(req, pagedsearch_cb, NULL);
12177 tevent_req_poll(req, ev);
12181 rc = callback_code;
12183 if (!TLDAP_RC_IS_SUCCESS(rc)) {
12184 d_printf("tldap_search with paging failed: %s\n",
12185 tldap_errstr(talloc_tos(), ld, rc));
12189 /* test search filters against rootDSE */
12190 filter = "(&(|(name=samba)(nextRid<=10000000)(usnChanged>=10)(samba~=ambas)(!(name=s*m*a)))"
12191 "(|(name:=samba)(name:dn:2.5.13.5:=samba)(:dn:2.5.13.5:=samba)(!(name=*samba))))";
12193 rc = tldap_search(ld, "", TLDAP_SCOPE_BASE, filter,
12194 NULL, 0, 0, NULL, 0, NULL, 0, 0, 0, 0,
12195 talloc_tos(), NULL);
12196 if (!TLDAP_RC_IS_SUCCESS(rc)) {
12197 d_printf("tldap_search with complex filter failed: %s\n",
12198 tldap_errstr(talloc_tos(), ld, rc));
12203 * Tests to check for regression of:
12205 * https://bugzilla.samba.org/show_bug.cgi?id=14029
12207 * TLDAP used here to pick apart the original string DN (with GUID)
12209 if (!tldap_test_dn_guid_format(ld, basedn, EXTENDED_NONE)) {
12210 d_printf("tldap_search with extended dn (no val) failed: %s\n",
12211 tldap_errstr(talloc_tos(), ld, rc));
12214 if (!tldap_test_dn_guid_format(ld, basedn, EXTENDED_ZERO)) {
12215 d_printf("tldap_search with extended dn (0) failed: %s\n",
12216 tldap_errstr(talloc_tos(), ld, rc));
12219 if (!tldap_test_dn_guid_format(ld, basedn, EXTENDED_ONE)) {
12220 d_printf("tldap_search with extended dn (1) failed: %s\n",
12221 tldap_errstr(talloc_tos(), ld, rc));
12229 /* Torture test to ensure no regression of :
12230 https://bugzilla.samba.org/show_bug.cgi?id=7084
12233 static bool run_dir_createtime(int dummy)
12235 struct cli_state *cli;
12236 const char *dname = "\\testdir_createtime";
12237 const char *fname = "\\testdir_createtime\\testfile";
12239 struct timespec create_time;
12240 struct timespec create_time1;
12245 if (!torture_open_connection(&cli, 0)) {
12249 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
12250 /* Ensure ino is zero, SMB2 gets a real one. */
12253 /* Ensure ino is -1, SMB1 never gets a real one. */
12254 ino = (uint64_t)-1;
12257 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
12258 cli_rmdir(cli, dname);
12260 status = cli_mkdir(cli, dname);
12261 if (!NT_STATUS_IS_OK(status)) {
12262 printf("mkdir failed: %s\n", nt_errstr(status));
12266 status = cli_qpathinfo2(cli, dname, &create_time, NULL, NULL, NULL,
12268 if (!NT_STATUS_IS_OK(status)) {
12269 printf("cli_qpathinfo2 returned %s\n",
12270 nt_errstr(status));
12274 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
12275 /* SMB2 should always return an inode. */
12277 printf("SMB2 bad inode (0)\n");
12281 /* SMB1 must always return zero here. */
12283 printf("SMB1 bad inode (!0)\n");
12288 /* Sleep 3 seconds, then create a file. */
12291 status = cli_openx(cli, fname, O_RDWR | O_CREAT | O_EXCL,
12293 if (!NT_STATUS_IS_OK(status)) {
12294 printf("cli_openx failed: %s\n", nt_errstr(status));
12298 status = cli_qpathinfo2(cli, dname, &create_time1, NULL, NULL, NULL,
12300 if (!NT_STATUS_IS_OK(status)) {
12301 printf("cli_qpathinfo2 (2) returned %s\n",
12302 nt_errstr(status));
12306 if (timespec_compare(&create_time1, &create_time)) {
12307 printf("run_dir_createtime: create time was updated (error)\n");
12309 printf("run_dir_createtime: create time was not updated (correct)\n");
12315 cli_unlink(cli, fname, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
12316 cli_rmdir(cli, dname);
12317 if (!torture_close_connection(cli)) {
12324 static bool run_streamerror(int dummy)
12326 struct cli_state *cli;
12327 const char *dname = "\\testdir_streamerror";
12328 const char *streamname =
12329 "testdir_streamerror:{4c8cc155-6c1e-11d1-8e41-00c04fb9386d}:$DATA";
12331 time_t change_time, access_time, write_time;
12337 if (!torture_open_connection(&cli, 0)) {
12341 cli_unlink(cli, "\\testdir_streamerror\\*", FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
12342 cli_rmdir(cli, dname);
12344 status = cli_mkdir(cli, dname);
12345 if (!NT_STATUS_IS_OK(status)) {
12346 printf("mkdir failed: %s\n", nt_errstr(status));
12350 status = cli_qpathinfo1(cli, streamname, &change_time, &access_time,
12351 &write_time, &size, &attr);
12352 if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
12353 printf("pathinfo returned %s, expected "
12354 "NT_STATUS_OBJECT_NAME_NOT_FOUND\n",
12355 nt_errstr(status));
12359 status = cli_ntcreate(cli, streamname, 0x16,
12360 FILE_READ_DATA|FILE_READ_EA|
12361 FILE_READ_ATTRIBUTES|READ_CONTROL_ACCESS,
12362 FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ,
12363 FILE_OPEN, 0, 0, &fnum, NULL);
12365 if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
12366 printf("ntcreate returned %s, expected "
12367 "NT_STATUS_OBJECT_NAME_NOT_FOUND\n",
12368 nt_errstr(status));
12373 cli_rmdir(cli, dname);
12377 struct pidtest_state {
12383 static void pid_echo_done(struct tevent_req *subreq);
12385 static struct tevent_req *pid_echo_send(TALLOC_CTX *mem_ctx,
12386 struct tevent_context *ev,
12387 struct cli_state *cli)
12389 struct tevent_req *req, *subreq;
12390 struct pidtest_state *state;
12392 req = tevent_req_create(mem_ctx, &state, struct pidtest_state);
12397 SSVAL(state->vwv, 0, 1);
12398 state->data = data_blob_const("hello", 5);
12400 subreq = smb1cli_req_send(state,
12404 0, 0, /* *_flags */
12405 0, 0, /* *_flags2 */
12407 0xDEADBEEF, /* pid */
12409 NULL, /* session */
12410 ARRAY_SIZE(state->vwv), state->vwv,
12411 state->data.length, state->data.data);
12413 if (tevent_req_nomem(subreq, req)) {
12414 return tevent_req_post(req, ev);
12416 tevent_req_set_callback(subreq, pid_echo_done, req);
12420 static void pid_echo_done(struct tevent_req *subreq)
12422 struct tevent_req *req = tevent_req_callback_data(
12423 subreq, struct tevent_req);
12424 struct pidtest_state *state = tevent_req_data(
12425 req, struct pidtest_state);
12427 uint32_t num_bytes;
12428 uint8_t *bytes = NULL;
12429 struct iovec *recv_iov = NULL;
12430 uint8_t *phdr = NULL;
12431 uint16_t pidlow = 0;
12432 uint16_t pidhigh = 0;
12433 struct smb1cli_req_expected_response expected[] = {
12435 .status = NT_STATUS_OK,
12440 status = smb1cli_req_recv(subreq, state,
12445 NULL, /* pvwv_offset */
12448 NULL, /* pbytes_offset */
12450 expected, ARRAY_SIZE(expected));
12452 TALLOC_FREE(subreq);
12454 if (!NT_STATUS_IS_OK(status)) {
12455 tevent_req_nterror(req, status);
12459 if (num_bytes != state->data.length) {
12460 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
12464 if (memcmp(bytes, state->data.data, num_bytes) != 0) {
12465 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
12469 /* Check pid low/high == DEADBEEF */
12470 pidlow = SVAL(phdr, HDR_PID);
12471 if (pidlow != 0xBEEF){
12472 printf("Incorrect pidlow 0x%x, should be 0xBEEF\n",
12473 (unsigned int)pidlow);
12474 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
12477 pidhigh = SVAL(phdr, HDR_PIDHIGH);
12478 if (pidhigh != 0xDEAD){
12479 printf("Incorrect pidhigh 0x%x, should be 0xDEAD\n",
12480 (unsigned int)pidhigh);
12481 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
12485 tevent_req_done(req);
12488 static NTSTATUS pid_echo_recv(struct tevent_req *req)
12490 return tevent_req_simple_recv_ntstatus(req);
12493 static bool run_pidhigh(int dummy)
12495 bool success = false;
12496 struct cli_state *cli = NULL;
12498 struct tevent_context *ev = NULL;
12499 struct tevent_req *req = NULL;
12500 TALLOC_CTX *frame = talloc_stackframe();
12502 printf("starting pid high test\n");
12503 if (!torture_open_connection(&cli, 0)) {
12506 smbXcli_conn_set_sockopt(cli->conn, sockops);
12508 ev = samba_tevent_context_init(frame);
12513 req = pid_echo_send(frame, ev, cli);
12518 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
12522 status = pid_echo_recv(req);
12523 if (NT_STATUS_IS_OK(status)) {
12524 printf("pid high test ok\n");
12530 TALLOC_FREE(frame);
12531 torture_close_connection(cli);
12536 Test Windows open on a bad POSIX symlink.
12538 static bool run_symlink_open_test(int dummy)
12540 static struct cli_state *cli;
12541 const char *fname = "non_existant_file";
12542 const char *sname = "dangling_symlink";
12543 uint16_t fnum = (uint16_t)-1;
12544 bool correct = false;
12546 TALLOC_CTX *frame = NULL;
12548 frame = talloc_stackframe();
12550 printf("Starting Windows bad symlink open test\n");
12552 if (!torture_open_connection(&cli, 0)) {
12553 TALLOC_FREE(frame);
12557 smbXcli_conn_set_sockopt(cli->conn, sockops);
12559 status = torture_setup_unix_extensions(cli);
12560 if (!NT_STATUS_IS_OK(status)) {
12561 TALLOC_FREE(frame);
12565 /* Ensure nothing exists. */
12566 cli_setatr(cli, fname, 0, 0);
12567 cli_posix_unlink(cli, fname);
12568 cli_setatr(cli, sname, 0, 0);
12569 cli_posix_unlink(cli, sname);
12571 /* Create a symlink pointing nowhere. */
12572 status = cli_posix_symlink(cli, fname, sname);
12573 if (!NT_STATUS_IS_OK(status)) {
12574 printf("cli_posix_symlink of %s -> %s failed (%s)\n",
12577 nt_errstr(status));
12581 /* Now ensure that a Windows open doesn't hang. */
12582 status = cli_ntcreate(cli,
12585 FILE_READ_DATA|FILE_WRITE_DATA,
12587 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
12595 * We get either NT_STATUS_OBJECT_NAME_NOT_FOUND or
12596 * NT_STATUS_OBJECT_PATH_NOT_FOUND depending on if
12597 * we use O_NOFOLLOW on the server or not.
12599 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND) ||
12600 NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_PATH_NOT_FOUND))
12604 printf("cli_ntcreate of %s returned %s - should return"
12605 " either (%s) or (%s)\n",
12608 nt_errstr(NT_STATUS_OBJECT_NAME_NOT_FOUND),
12609 nt_errstr(NT_STATUS_OBJECT_PATH_NOT_FOUND));
12617 if (fnum != (uint16_t)-1) {
12618 cli_close(cli, fnum);
12619 fnum = (uint16_t)-1;
12622 cli_setatr(cli, sname, 0, 0);
12623 cli_posix_unlink(cli, sname);
12624 cli_setatr(cli, fname, 0, 0);
12625 cli_posix_unlink(cli, fname);
12627 if (!torture_close_connection(cli)) {
12631 TALLOC_FREE(frame);
12636 * Only testing minimal time strings, as the others
12637 * need (locale-dependent) guessing at what strftime does and
12638 * even may differ in builds.
12640 static bool timesubst_test(void)
12642 TALLOC_CTX *ctx = NULL;
12643 /* Sa 23. Dez 04:33:20 CET 2017 */
12644 const struct timeval tv = { 1514000000, 123 };
12645 const char* expect_minimal = "20171223_033320";
12646 const char* expect_minus = "20171223_033320_000123";
12648 char *env_tz, *orig_tz = NULL;
12649 bool result = true;
12651 ctx = talloc_new(NULL);
12653 env_tz = getenv("TZ");
12655 orig_tz = talloc_strdup(ctx, env_tz);
12657 setenv("TZ", "UTC", 1);
12659 s = minimal_timeval_string(ctx, &tv, false);
12661 if(!s || strcmp(s, expect_minimal)) {
12662 printf("minimal_timeval_string(ctx, tv, false) returned [%s], expected "
12663 "[%s]\n", s ? s : "<nil>", expect_minimal);
12667 s = minimal_timeval_string(ctx, &tv, true);
12668 if(!s || strcmp(s, expect_minus)) {
12669 printf("minimal_timeval_string(ctx, tv, true) returned [%s], expected "
12670 "[%s]\n", s ? s : "<nil>", expect_minus);
12676 setenv("TZ", orig_tz, 1);
12683 static bool run_local_substitute(int dummy)
12687 ok &= subst_test("%U", "bla", "", -1, -1, "bla");
12688 ok &= subst_test("%u%U", "bla", "", -1, -1, "blabla");
12689 ok &= subst_test("%g", "", "", -1, -1, "NO_GROUP");
12690 ok &= subst_test("%G", "", "", -1, -1, "NO_GROUP");
12691 ok &= subst_test("%g", "", "", -1, 0, gidtoname(0));
12692 ok &= subst_test("%G", "", "", -1, 0, gidtoname(0));
12693 ok &= subst_test("%D%u", "u", "dom", -1, 0, "domu");
12694 ok &= subst_test("%i %I", "", "", -1, -1, "0.0.0.0 0.0.0.0");
12695 ok &= subst_test("%j %J", "", "", -1, -1, "0_0_0_0 0_0_0_0");
12696 /* Substitution depends on current time, so better test the underlying
12697 formatting function. At least covers %t. */
12698 ok &= timesubst_test();
12700 /* Different captialization rules in sub_basic... */
12702 ok &= (strcmp(talloc_sub_basic(talloc_tos(), "BLA", "dom", "%U%D"),
12708 static bool run_local_base64(int dummy)
12713 for (i=1; i<2000; i++) {
12714 DATA_BLOB blob1, blob2;
12717 blob1.data = talloc_array(talloc_tos(), uint8_t, i);
12719 generate_random_buffer(blob1.data, blob1.length);
12721 b64 = base64_encode_data_blob(talloc_tos(), blob1);
12723 d_fprintf(stderr, "base64_encode_data_blob failed "
12724 "for %d bytes\n", i);
12727 blob2 = base64_decode_data_blob(b64);
12730 if (data_blob_cmp(&blob1, &blob2)) {
12731 d_fprintf(stderr, "data_blob_cmp failed for %d "
12735 TALLOC_FREE(blob1.data);
12736 data_blob_free(&blob2);
12741 static void parse_fn(const struct gencache_timeout *t,
12743 void *private_data)
12748 static bool run_local_gencache(int dummy)
12754 struct memcache *mem;
12757 mem = memcache_init(NULL, 0);
12759 d_printf("%s: memcache_init failed\n", __location__);
12762 memcache_set_global(mem);
12764 if (!gencache_set("foo", "bar", time(NULL) + 1000)) {
12765 d_printf("%s: gencache_set() failed\n", __location__);
12769 if (!gencache_get("foo", NULL, NULL, NULL)) {
12770 d_printf("%s: gencache_get() failed\n", __location__);
12774 for (i=0; i<1000000; i++) {
12775 gencache_parse("foo", parse_fn, NULL);
12778 if (!gencache_get("foo", talloc_tos(), &val, &tm)) {
12779 d_printf("%s: gencache_get() failed\n", __location__);
12784 if (!gencache_get("foo", talloc_tos(), &val, &tm)) {
12785 d_printf("%s: gencache_get() failed\n", __location__);
12789 if (strcmp(val, "bar") != 0) {
12790 d_printf("%s: gencache_get() returned %s, expected %s\n",
12791 __location__, val, "bar");
12798 if (!gencache_del("foo")) {
12799 d_printf("%s: gencache_del() failed\n", __location__);
12802 if (gencache_del("foo")) {
12803 d_printf("%s: second gencache_del() succeeded\n",
12808 if (gencache_get("foo", talloc_tos(), &val, &tm)) {
12809 d_printf("%s: gencache_get() on deleted entry "
12810 "succeeded\n", __location__);
12814 blob = data_blob_string_const_null("bar");
12815 tm = time(NULL) + 60;
12817 if (!gencache_set_data_blob("foo", blob, tm)) {
12818 d_printf("%s: gencache_set_data_blob() failed\n", __location__);
12822 if (!gencache_get_data_blob("foo", talloc_tos(), &blob, NULL, NULL)) {
12823 d_printf("%s: gencache_get_data_blob() failed\n", __location__);
12827 if (strcmp((const char *)blob.data, "bar") != 0) {
12828 d_printf("%s: gencache_get_data_blob() returned %s, expected %s\n",
12829 __location__, (const char *)blob.data, "bar");
12830 data_blob_free(&blob);
12834 data_blob_free(&blob);
12836 if (!gencache_del("foo")) {
12837 d_printf("%s: gencache_del() failed\n", __location__);
12840 if (gencache_del("foo")) {
12841 d_printf("%s: second gencache_del() succeeded\n",
12846 if (gencache_get_data_blob("foo", talloc_tos(), &blob, NULL, NULL)) {
12847 d_printf("%s: gencache_get_data_blob() on deleted entry "
12848 "succeeded\n", __location__);
12853 blob.data = (uint8_t *)&v;
12854 blob.length = sizeof(v);
12856 if (!gencache_set_data_blob("blob", blob, tm)) {
12857 d_printf("%s: gencache_set_data_blob() failed\n",
12861 if (gencache_get("blob", talloc_tos(), &val, &tm)) {
12862 d_printf("%s: gencache_get succeeded\n", __location__);
12869 static bool rbt_testval(struct db_context *db, const char *key,
12872 struct db_record *rec;
12873 TDB_DATA data = string_tdb_data(value);
12878 rec = dbwrap_fetch_locked(db, db, string_tdb_data(key));
12880 d_fprintf(stderr, "fetch_locked failed\n");
12883 status = dbwrap_record_store(rec, data, 0);
12884 if (!NT_STATUS_IS_OK(status)) {
12885 d_fprintf(stderr, "store failed: %s\n", nt_errstr(status));
12890 rec = dbwrap_fetch_locked(db, db, string_tdb_data(key));
12892 d_fprintf(stderr, "second fetch_locked failed\n");
12896 dbvalue = dbwrap_record_get_value(rec);
12897 if ((dbvalue.dsize != data.dsize)
12898 || (memcmp(dbvalue.dptr, data.dptr, data.dsize) != 0)) {
12899 d_fprintf(stderr, "Got wrong data back\n");
12909 static int local_rbtree_traverse_read(struct db_record *rec, void *private_data)
12911 int *count2 = (int *)private_data;
12916 static int local_rbtree_traverse_delete(struct db_record *rec, void *private_data)
12918 int *count2 = (int *)private_data;
12920 dbwrap_record_delete(rec);
12924 static bool run_local_rbtree(int dummy)
12926 struct db_context *db;
12933 db = db_open_rbt(NULL);
12936 d_fprintf(stderr, "db_open_rbt failed\n");
12940 for (i=0; i<1000; i++) {
12943 if (asprintf(&key, "key%ld", random()) == -1) {
12946 if (asprintf(&value, "value%ld", random()) == -1) {
12951 if (!rbt_testval(db, key, value)) {
12958 if (asprintf(&value, "value%ld", random()) == -1) {
12963 if (!rbt_testval(db, key, value)) {
12974 count = 0; count2 = 0;
12975 status = dbwrap_traverse_read(db, local_rbtree_traverse_read,
12977 printf("%s: read1: %d %d, %s\n", __func__, count, count2, nt_errstr(status));
12978 if ((count != count2) || (count != 1000)) {
12981 count = 0; count2 = 0;
12982 status = dbwrap_traverse(db, local_rbtree_traverse_delete,
12984 printf("%s: delete: %d %d, %s\n", __func__, count, count2, nt_errstr(status));
12985 if ((count != count2) || (count != 1000)) {
12988 count = 0; count2 = 0;
12989 status = dbwrap_traverse_read(db, local_rbtree_traverse_read,
12991 printf("%s: read2: %d %d, %s\n", __func__, count, count2, nt_errstr(status));
12992 if ((count != count2) || (count != 0)) {
13003 local test for character set functions
13005 This is a very simple test for the functionality in convert_string_error()
13007 static bool run_local_convert_string(int dummy)
13009 TALLOC_CTX *tmp_ctx = talloc_new(NULL);
13010 const char *test_strings[2] = { "March", "M\303\244rz" };
13014 for (i=0; i<2; i++) {
13015 const char *str = test_strings[i];
13016 int len = strlen(str);
13017 size_t converted_size;
13020 memset(dst, 'X', sizeof(dst));
13022 /* first try with real source length */
13023 ret = convert_string_error(CH_UNIX, CH_UTF8,
13028 d_fprintf(stderr, "Failed to convert '%s' to CH_DISPLAY\n", str);
13032 if (converted_size != len) {
13033 d_fprintf(stderr, "Converted size of '%s' should be %d - got %d\n",
13034 str, len, (int)converted_size);
13038 if (strncmp(str, dst, converted_size) != 0) {
13039 d_fprintf(stderr, "Expected '%s' to match '%s'\n", str, dst);
13043 if (strlen(str) != converted_size) {
13044 d_fprintf(stderr, "Expected '%s' length %d - got %d\n", str,
13045 (int)strlen(str), (int)converted_size);
13049 if (dst[converted_size] != 'X') {
13050 d_fprintf(stderr, "Expected no termination of '%s'\n", dst);
13054 /* now with srclen==-1, this causes the nul to be
13056 ret = convert_string_error(CH_UNIX, CH_UTF8,
13061 d_fprintf(stderr, "Failed to convert '%s' to CH_DISPLAY\n", str);
13065 if (converted_size != len+1) {
13066 d_fprintf(stderr, "Converted size of '%s' should be %d - got %d\n",
13067 str, len, (int)converted_size);
13071 if (strncmp(str, dst, converted_size) != 0) {
13072 d_fprintf(stderr, "Expected '%s' to match '%s'\n", str, dst);
13076 if (len+1 != converted_size) {
13077 d_fprintf(stderr, "Expected '%s' length %d - got %d\n", str,
13078 len+1, (int)converted_size);
13082 if (dst[converted_size] != 'X') {
13083 d_fprintf(stderr, "Expected no termination of '%s'\n", dst);
13090 TALLOC_FREE(tmp_ctx);
13093 TALLOC_FREE(tmp_ctx);
13097 static bool run_local_string_to_sid(int dummy) {
13098 struct dom_sid sid;
13100 if (string_to_sid(&sid, "S--1-5-32-545")) {
13101 printf("allowing S--1-5-32-545\n");
13104 if (string_to_sid(&sid, "S-1-5-32-+545")) {
13105 printf("allowing S-1-5-32-+545\n");
13108 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")) {
13109 printf("allowing S-1-2-3-4-5-6-7-8-9-0-1-2-3-4-5-6-7-8-9-0\n");
13112 if (string_to_sid(&sid, "S-1-5-32-545-abc")) {
13113 printf("allowing S-1-5-32-545-abc\n");
13116 if (string_to_sid(&sid, "S-300-5-32-545")) {
13117 printf("allowing S-300-5-32-545\n");
13120 if (string_to_sid(&sid, "S-1-0xfffffffffffffe-32-545")) {
13121 printf("allowing S-1-0xfffffffffffffe-32-545\n");
13124 if (string_to_sid(&sid, "S-1-0xffffffffffff-5294967297-545")) {
13125 printf("allowing S-1-0xffffffffffff-5294967297-545\n");
13128 if (!string_to_sid(&sid, "S-1-0xfffffffffffe-32-545")) {
13129 printf("could not parse S-1-0xfffffffffffe-32-545\n");
13132 if (!string_to_sid(&sid, "S-1-5-32-545")) {
13133 printf("could not parse S-1-5-32-545\n");
13136 if (!dom_sid_equal(&sid, &global_sid_Builtin_Users)) {
13137 struct dom_sid_buf buf;
13138 printf("mis-parsed S-1-5-32-545 as %s\n",
13139 dom_sid_str_buf(&sid, &buf));
13145 static bool sid_to_string_test(const char *expected) {
13148 struct dom_sid sid;
13150 if (!string_to_sid(&sid, expected)) {
13151 printf("could not parse %s\n", expected);
13155 str = dom_sid_string(NULL, &sid);
13156 if (strcmp(str, expected)) {
13157 printf("Comparison failed (%s != %s)\n", str, expected);
13164 static bool run_local_sid_to_string(int dummy) {
13165 if (!sid_to_string_test("S-1-0xffffffffffff-1-1-1-1-1-1-1-1-1-1-1-1"))
13167 if (!sid_to_string_test("S-1-545"))
13169 if (!sid_to_string_test("S-255-3840-1-1-1-1"))
13174 static bool run_local_binary_to_sid(int dummy) {
13176 struct dom_sid *sid = talloc(NULL, struct dom_sid);
13177 static const uint8_t good_binary_sid[] = {
13178 0x1, /* revision number */
13179 15, /* num auths */
13180 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, /* id_auth */
13181 0x1, 0x1, 0x1, 0x1, /* auth[0] */
13182 0x1, 0x1, 0x1, 0x1, /* auth[1] */
13183 0x1, 0x1, 0x1, 0x1, /* auth[2] */
13184 0x1, 0x1, 0x1, 0x1, /* auth[3] */
13185 0x1, 0x1, 0x1, 0x1, /* auth[4] */
13186 0x1, 0x1, 0x1, 0x1, /* auth[5] */
13187 0x1, 0x1, 0x1, 0x1, /* auth[6] */
13188 0x1, 0x1, 0x1, 0x1, /* auth[7] */
13189 0x1, 0x1, 0x1, 0x1, /* auth[8] */
13190 0x1, 0x1, 0x1, 0x1, /* auth[9] */
13191 0x1, 0x1, 0x1, 0x1, /* auth[10] */
13192 0x1, 0x1, 0x1, 0x1, /* auth[11] */
13193 0x1, 0x1, 0x1, 0x1, /* auth[12] */
13194 0x1, 0x1, 0x1, 0x1, /* auth[13] */
13195 0x1, 0x1, 0x1, 0x1, /* auth[14] */
13198 static const uint8_t long_binary_sid[] = {
13199 0x1, /* revision number */
13200 15, /* num auths */
13201 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, /* id_auth */
13202 0x1, 0x1, 0x1, 0x1, /* auth[0] */
13203 0x1, 0x1, 0x1, 0x1, /* auth[1] */
13204 0x1, 0x1, 0x1, 0x1, /* auth[2] */
13205 0x1, 0x1, 0x1, 0x1, /* auth[3] */
13206 0x1, 0x1, 0x1, 0x1, /* auth[4] */
13207 0x1, 0x1, 0x1, 0x1, /* auth[5] */
13208 0x1, 0x1, 0x1, 0x1, /* auth[6] */
13209 0x1, 0x1, 0x1, 0x1, /* auth[7] */
13210 0x1, 0x1, 0x1, 0x1, /* auth[8] */
13211 0x1, 0x1, 0x1, 0x1, /* auth[9] */
13212 0x1, 0x1, 0x1, 0x1, /* auth[10] */
13213 0x1, 0x1, 0x1, 0x1, /* auth[11] */
13214 0x1, 0x1, 0x1, 0x1, /* auth[12] */
13215 0x1, 0x1, 0x1, 0x1, /* auth[13] */
13216 0x1, 0x1, 0x1, 0x1, /* auth[14] */
13217 0x1, 0x1, 0x1, 0x1, /* auth[15] */
13218 0x1, 0x1, 0x1, 0x1, /* auth[16] */
13219 0x1, 0x1, 0x1, 0x1, /* auth[17] */
13222 static const uint8_t long_binary_sid2[] = {
13223 0x1, /* revision number */
13224 32, /* num auths */
13225 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, /* id_auth */
13226 0x1, 0x1, 0x1, 0x1, /* auth[0] */
13227 0x1, 0x1, 0x1, 0x1, /* auth[1] */
13228 0x1, 0x1, 0x1, 0x1, /* auth[2] */
13229 0x1, 0x1, 0x1, 0x1, /* auth[3] */
13230 0x1, 0x1, 0x1, 0x1, /* auth[4] */
13231 0x1, 0x1, 0x1, 0x1, /* auth[5] */
13232 0x1, 0x1, 0x1, 0x1, /* auth[6] */
13233 0x1, 0x1, 0x1, 0x1, /* auth[7] */
13234 0x1, 0x1, 0x1, 0x1, /* auth[8] */
13235 0x1, 0x1, 0x1, 0x1, /* auth[9] */
13236 0x1, 0x1, 0x1, 0x1, /* auth[10] */
13237 0x1, 0x1, 0x1, 0x1, /* auth[11] */
13238 0x1, 0x1, 0x1, 0x1, /* auth[12] */
13239 0x1, 0x1, 0x1, 0x1, /* auth[13] */
13240 0x1, 0x1, 0x1, 0x1, /* auth[14] */
13241 0x1, 0x1, 0x1, 0x1, /* auth[15] */
13242 0x1, 0x1, 0x1, 0x1, /* auth[16] */
13243 0x1, 0x1, 0x1, 0x1, /* auth[17] */
13244 0x1, 0x1, 0x1, 0x1, /* auth[18] */
13245 0x1, 0x1, 0x1, 0x1, /* auth[19] */
13246 0x1, 0x1, 0x1, 0x1, /* auth[20] */
13247 0x1, 0x1, 0x1, 0x1, /* auth[21] */
13248 0x1, 0x1, 0x1, 0x1, /* auth[22] */
13249 0x1, 0x1, 0x1, 0x1, /* auth[23] */
13250 0x1, 0x1, 0x1, 0x1, /* auth[24] */
13251 0x1, 0x1, 0x1, 0x1, /* auth[25] */
13252 0x1, 0x1, 0x1, 0x1, /* auth[26] */
13253 0x1, 0x1, 0x1, 0x1, /* auth[27] */
13254 0x1, 0x1, 0x1, 0x1, /* auth[28] */
13255 0x1, 0x1, 0x1, 0x1, /* auth[29] */
13256 0x1, 0x1, 0x1, 0x1, /* auth[30] */
13257 0x1, 0x1, 0x1, 0x1, /* auth[31] */
13260 ret = sid_parse(good_binary_sid, sizeof(good_binary_sid), sid);
13264 ret = sid_parse(long_binary_sid2, sizeof(long_binary_sid2), sid);
13268 ret = sid_parse(long_binary_sid, sizeof(long_binary_sid), sid);
13275 /* Split a path name into filename and stream name components. Canonicalise
13276 * such that an implicit $DATA token is always explicit.
13278 * The "specification" of this function can be found in the
13279 * run_local_stream_name() function in torture.c, I've tried those
13280 * combinations against a W2k3 server.
13283 static NTSTATUS split_ntfs_stream_name(TALLOC_CTX *mem_ctx, const char *fname,
13284 char **pbase, char **pstream)
13287 char *stream = NULL;
13288 char *sname; /* stream name */
13289 const char *stype; /* stream type */
13291 DEBUG(10, ("split_ntfs_stream_name called for [%s]\n", fname));
13293 sname = strchr_m(fname, ':');
13295 if (sname == NULL) {
13296 if (pbase != NULL) {
13297 base = talloc_strdup(mem_ctx, fname);
13298 NT_STATUS_HAVE_NO_MEMORY(base);
13303 if (pbase != NULL) {
13304 base = talloc_strndup(mem_ctx, fname, PTR_DIFF(sname, fname));
13305 NT_STATUS_HAVE_NO_MEMORY(base);
13310 stype = strchr_m(sname, ':');
13312 if (stype == NULL) {
13313 sname = talloc_strdup(mem_ctx, sname);
13317 if (strcasecmp_m(stype, ":$DATA") != 0) {
13319 * If there is an explicit stream type, so far we only
13320 * allow $DATA. Is there anything else allowed? -- vl
13322 DEBUG(10, ("[%s] is an invalid stream type\n", stype));
13324 return NT_STATUS_OBJECT_NAME_INVALID;
13326 sname = talloc_strndup(mem_ctx, sname, PTR_DIFF(stype, sname));
13330 if (sname == NULL) {
13332 return NT_STATUS_NO_MEMORY;
13335 if (sname[0] == '\0') {
13337 * no stream name, so no stream
13342 if (pstream != NULL) {
13343 stream = talloc_asprintf(mem_ctx, "%s:%s", sname, stype);
13344 if (stream == NULL) {
13345 TALLOC_FREE(sname);
13347 return NT_STATUS_NO_MEMORY;
13350 * upper-case the type field
13352 (void)strupper_m(strchr_m(stream, ':')+1);
13356 if (pbase != NULL) {
13359 if (pstream != NULL) {
13362 return NT_STATUS_OK;
13365 static bool test_stream_name(const char *fname, const char *expected_base,
13366 const char *expected_stream,
13367 NTSTATUS expected_status)
13371 char *stream = NULL;
13373 status = split_ntfs_stream_name(talloc_tos(), fname, &base, &stream);
13374 if (!NT_STATUS_EQUAL(status, expected_status)) {
13378 if (!NT_STATUS_IS_OK(status)) {
13382 if (base == NULL) goto error;
13384 if (strcmp(expected_base, base) != 0) goto error;
13386 if ((expected_stream != NULL) && (stream == NULL)) goto error;
13387 if ((expected_stream == NULL) && (stream != NULL)) goto error;
13389 if ((stream != NULL) && (strcmp(expected_stream, stream) != 0))
13393 TALLOC_FREE(stream);
13397 d_fprintf(stderr, "Do test_stream(%s, %s, %s, %s)\n",
13398 fname, expected_base ? expected_base : "<NULL>",
13399 expected_stream ? expected_stream : "<NULL>",
13400 nt_errstr(expected_status));
13401 d_fprintf(stderr, "-> base=%s, stream=%s, status=%s\n",
13402 base ? base : "<NULL>", stream ? stream : "<NULL>",
13403 nt_errstr(status));
13405 TALLOC_FREE(stream);
13409 static bool run_local_stream_name(int dummy)
13413 ret &= test_stream_name(
13414 "bla", "bla", NULL, NT_STATUS_OK);
13415 ret &= test_stream_name(
13416 "bla::$DATA", "bla", NULL, NT_STATUS_OK);
13417 ret &= test_stream_name(
13418 "bla:blub:", "bla", NULL, NT_STATUS_OBJECT_NAME_INVALID);
13419 ret &= test_stream_name(
13420 "bla::", NULL, NULL, NT_STATUS_OBJECT_NAME_INVALID);
13421 ret &= test_stream_name(
13422 "bla::123", "bla", NULL, NT_STATUS_OBJECT_NAME_INVALID);
13423 ret &= test_stream_name(
13424 "bla:$DATA", "bla", "$DATA:$DATA", NT_STATUS_OK);
13425 ret &= test_stream_name(
13426 "bla:x:$DATA", "bla", "x:$DATA", NT_STATUS_OK);
13427 ret &= test_stream_name(
13428 "bla:x", "bla", "x:$DATA", NT_STATUS_OK);
13433 static bool data_blob_equal(DATA_BLOB a, DATA_BLOB b)
13435 if (a.length != b.length) {
13436 printf("a.length=%d != b.length=%d\n",
13437 (int)a.length, (int)b.length);
13440 if (memcmp(a.data, b.data, a.length) != 0) {
13441 printf("a.data and b.data differ\n");
13447 static bool run_local_memcache(int dummy)
13449 struct memcache *cache;
13450 DATA_BLOB k1, k2, k3, k4, k5;
13454 TALLOC_CTX *mem_ctx;
13460 size_t size1, size2;
13463 mem_ctx = talloc_init("foo");
13464 if (mem_ctx == NULL) {
13468 /* STAT_CACHE TESTS */
13470 cache = memcache_init(NULL, sizeof(void *) == 8 ? 200 : 100);
13472 if (cache == NULL) {
13473 printf("memcache_init failed\n");
13477 d1 = data_blob_const("d1", 2);
13478 d3 = data_blob_const("d3", 2);
13480 k1 = data_blob_const("d1", 2);
13481 k2 = data_blob_const("d2", 2);
13482 k3 = data_blob_const("d3", 2);
13483 k4 = data_blob_const("d4", 2);
13484 k5 = data_blob_const("d5", 2);
13486 memcache_add(cache, STAT_CACHE, k1, d1);
13488 if (!memcache_lookup(cache, STAT_CACHE, k1, &v1)) {
13489 printf("could not find k1\n");
13492 if (!data_blob_equal(d1, v1)) {
13496 memcache_add(cache, STAT_CACHE, k1, d3);
13498 if (!memcache_lookup(cache, STAT_CACHE, k1, &v3)) {
13499 printf("could not find replaced k1\n");
13502 if (!data_blob_equal(d3, v3)) {
13506 TALLOC_FREE(cache);
13508 /* GETWD_CACHE TESTS */
13509 str1 = talloc_strdup(mem_ctx, "string1");
13510 if (str1 == NULL) {
13513 ptr2 = str1; /* Keep an alias for comparison. */
13515 str2 = talloc_strdup(mem_ctx, "string2");
13516 if (str2 == NULL) {
13520 cache = memcache_init(NULL, sizeof(void *) == 8 ? 200 : 100);
13521 if (cache == NULL) {
13522 printf("memcache_init failed\n");
13526 memcache_add_talloc(cache, GETWD_CACHE, k2, &str1);
13527 /* str1 == NULL now. */
13528 ptr1 = memcache_lookup_talloc(cache, GETWD_CACHE, k2);
13529 if (ptr1 == NULL) {
13530 printf("could not find k2\n");
13533 if (ptr1 != ptr2) {
13534 printf("fetch of k2 got wrong string\n");
13538 /* Add a blob to ensure k2 gets purged. */
13539 d3 = data_blob_talloc_zero(mem_ctx, 180);
13540 memcache_add(cache, STAT_CACHE, k3, d3);
13542 ptr2 = memcache_lookup_talloc(cache, GETWD_CACHE, k2);
13543 if (ptr2 != NULL) {
13544 printf("Did find k2, should have been purged\n");
13549 * Test that talloc size also is accounted in memcache and
13550 * causes purge of other object.
13553 str1 = talloc_zero_size(mem_ctx, 100);
13554 str2 = talloc_zero_size(mem_ctx, 100);
13556 memcache_add_talloc(cache, GETWD_CACHE, k4, &str1);
13557 memcache_add_talloc(cache, GETWD_CACHE, k5, &str1);
13559 ptr3 = memcache_lookup_talloc(cache, GETWD_CACHE, k4);
13560 if (ptr3 != NULL) {
13561 printf("Did find k4, should have been purged\n");
13566 * Test that adding a duplicate non-talloced
13567 * key/value on top of a talloced key/value takes account
13568 * of the talloc_freed value size.
13570 TALLOC_FREE(cache);
13571 TALLOC_FREE(mem_ctx);
13573 mem_ctx = talloc_init("key_replace");
13574 if (mem_ctx == NULL) {
13578 cache = memcache_init(NULL, sizeof(void *) == 8 ? 200 : 100);
13579 if (cache == NULL) {
13584 * Add a 100 byte talloced string. This will
13585 * store a (4 or 8 byte) pointer and record the
13586 * total talloced size.
13588 str1 = talloc_zero_size(mem_ctx, 100);
13589 memcache_add_talloc(cache, GETWD_CACHE, k4, &str1);
13591 * Now overwrite with a small talloced
13592 * value. This should fit in the existing size
13593 * and the total talloced size should be removed
13594 * from the cache size.
13596 str1 = talloc_zero_size(mem_ctx, 2);
13597 memcache_add_talloc(cache, GETWD_CACHE, k4, &str1);
13599 * Now store a 20 byte string. If the
13600 * total talloced size wasn't accounted for
13601 * and removed in the overwrite, then this
13604 str2 = talloc_zero_size(mem_ctx, 20);
13605 memcache_add_talloc(cache, GETWD_CACHE, k5, &str2);
13607 ptr3 = memcache_lookup_talloc(cache, GETWD_CACHE, k4);
13608 if (ptr3 == NULL) {
13609 printf("Did not find k4, should not have been purged\n");
13613 TALLOC_FREE(cache);
13614 TALLOC_FREE(mem_ctx);
13616 mem_ctx = talloc_init("foo");
13617 if (mem_ctx == NULL) {
13621 cache = memcache_init(NULL, 0);
13622 if (cache == NULL) {
13626 str1 = talloc_strdup(mem_ctx, "string1");
13627 if (str1 == NULL) {
13630 str2 = talloc_strdup(mem_ctx, "string2");
13631 if (str2 == NULL) {
13634 memcache_add_talloc(cache, SINGLETON_CACHE_TALLOC,
13635 data_blob_string_const("torture"), &str1);
13636 size1 = talloc_total_size(cache);
13638 memcache_add_talloc(cache, SINGLETON_CACHE_TALLOC,
13639 data_blob_string_const("torture"), &str2);
13640 size2 = talloc_total_size(cache);
13642 printf("size1=%d, size2=%d\n", (int)size1, (int)size2);
13644 if (size2 > size1) {
13645 printf("memcache leaks memory!\n");
13651 TALLOC_FREE(cache);
13655 static void wbclient_done(struct tevent_req *req)
13658 struct winbindd_response *wb_resp;
13659 int *i = (int *)tevent_req_callback_data_void(req);
13661 wbc_err = wb_trans_recv(req, req, &wb_resp);
13664 d_printf("wb_trans_recv %d returned %s\n", *i, wbcErrorString(wbc_err));
13667 static bool run_wbclient_multi_ping(int dummy)
13669 struct tevent_context *ev;
13670 struct wb_context **wb_ctx;
13671 struct winbindd_request wb_req;
13672 bool result = false;
13675 BlockSignals(True, SIGPIPE);
13677 ev = tevent_context_init(talloc_tos());
13682 wb_ctx = talloc_array(ev, struct wb_context *, torture_nprocs);
13683 if (wb_ctx == NULL) {
13687 ZERO_STRUCT(wb_req);
13688 wb_req.cmd = WINBINDD_PING;
13690 d_printf("torture_nprocs=%d, numops=%d\n", (int)torture_nprocs, (int)torture_numops);
13692 for (i=0; i<torture_nprocs; i++) {
13693 wb_ctx[i] = wb_context_init(ev, NULL);
13694 if (wb_ctx[i] == NULL) {
13697 for (j=0; j<torture_numops; j++) {
13698 struct tevent_req *req;
13699 req = wb_trans_send(ev, ev, wb_ctx[i],
13700 (j % 2) == 0, &wb_req);
13704 tevent_req_set_callback(req, wbclient_done, &i);
13710 while (i < torture_nprocs * torture_numops) {
13711 tevent_loop_once(ev);
13720 static bool dbtrans_inc(struct db_context *db)
13722 struct db_record *rec;
13728 rec = dbwrap_fetch_locked(db, db, string_term_tdb_data("transtest"));
13730 printf(__location__ "fetch_lock failed\n");
13734 value = dbwrap_record_get_value(rec);
13736 if (value.dsize != sizeof(uint32_t)) {
13737 printf(__location__ "value.dsize = %d\n",
13742 memcpy(&val, value.dptr, sizeof(val));
13745 status = dbwrap_record_store(
13746 rec, make_tdb_data((uint8_t *)&val, sizeof(val)), 0);
13747 if (!NT_STATUS_IS_OK(status)) {
13748 printf(__location__ "store failed: %s\n",
13749 nt_errstr(status));
13759 static bool run_local_dbtrans(int dummy)
13761 struct db_context *db;
13762 struct db_record *rec;
13768 db = db_open(talloc_tos(), "transtest.tdb", 0, TDB_DEFAULT,
13769 O_RDWR|O_CREAT, 0600, DBWRAP_LOCK_ORDER_1,
13772 printf("Could not open transtest.db\n");
13776 res = dbwrap_transaction_start(db);
13778 printf(__location__ "transaction_start failed\n");
13782 rec = dbwrap_fetch_locked(db, db, string_term_tdb_data("transtest"));
13784 printf(__location__ "fetch_lock failed\n");
13788 value = dbwrap_record_get_value(rec);
13790 if (value.dptr == NULL) {
13792 status = dbwrap_record_store(
13793 rec, make_tdb_data((uint8_t *)&initial,
13796 if (!NT_STATUS_IS_OK(status)) {
13797 printf(__location__ "store returned %s\n",
13798 nt_errstr(status));
13805 res = dbwrap_transaction_commit(db);
13807 printf(__location__ "transaction_commit failed\n");
13812 uint32_t val, val2;
13815 res = dbwrap_transaction_start(db);
13817 printf(__location__ "transaction_start failed\n");
13821 status = dbwrap_fetch_uint32_bystring(db, "transtest", &val);
13822 if (!NT_STATUS_IS_OK(status)) {
13823 printf(__location__ "dbwrap_fetch_uint32 failed: %s\n",
13824 nt_errstr(status));
13828 for (i=0; i<10; i++) {
13829 if (!dbtrans_inc(db)) {
13834 status = dbwrap_fetch_uint32_bystring(db, "transtest", &val2);
13835 if (!NT_STATUS_IS_OK(status)) {
13836 printf(__location__ "dbwrap_fetch_uint32 failed: %s\n",
13837 nt_errstr(status));
13841 if (val2 != val + 10) {
13842 printf(__location__ "val=%d, val2=%d\n",
13843 (int)val, (int)val2);
13847 printf("val2=%d\r", val2);
13849 res = dbwrap_transaction_commit(db);
13851 printf(__location__ "transaction_commit failed\n");
13861 * Just a dummy test to be run under a debugger. There's no real way
13862 * to inspect the tevent_poll specific function from outside of
13866 static bool run_local_tevent_poll(int dummy)
13868 struct tevent_context *ev;
13869 struct tevent_fd *fd1, *fd2;
13870 bool result = false;
13872 ev = tevent_context_init_byname(NULL, "poll");
13874 d_fprintf(stderr, "tevent_context_init_byname failed\n");
13878 fd1 = tevent_add_fd(ev, ev, 2, 0, NULL, NULL);
13880 d_fprintf(stderr, "tevent_add_fd failed\n");
13883 fd2 = tevent_add_fd(ev, ev, 3, 0, NULL, NULL);
13885 d_fprintf(stderr, "tevent_add_fd failed\n");
13890 fd2 = tevent_add_fd(ev, ev, 1, 0, NULL, NULL);
13892 d_fprintf(stderr, "tevent_add_fd failed\n");
13902 static bool run_local_hex_encode_buf(int dummy)
13908 for (i=0; i<sizeof(src); i++) {
13911 hex_encode_buf(buf, src, sizeof(src));
13912 if (strcmp(buf, "0001020304050607") != 0) {
13915 hex_encode_buf(buf, NULL, 0);
13916 if (buf[0] != '\0') {
13922 static const char *remove_duplicate_addrs2_test_strings_vector[] = {
13944 "1001:1111:1111:1000:0:1111:1111:1111",
13953 static const char *remove_duplicate_addrs2_test_strings_result[] = {
13967 "1001:1111:1111:1000:0:1111:1111:1111"
13970 static bool run_local_remove_duplicate_addrs2(int dummy)
13972 struct ip_service test_vector[28];
13975 /* Construct the sockaddr_storage test vector. */
13976 for (i = 0; i < 28; i++) {
13977 struct addrinfo hints;
13978 struct addrinfo *res = NULL;
13981 memset(&hints, '\0', sizeof(hints));
13982 hints.ai_flags = AI_NUMERICHOST;
13983 ret = getaddrinfo(remove_duplicate_addrs2_test_strings_vector[i],
13988 fprintf(stderr, "getaddrinfo failed on [%s]\n",
13989 remove_duplicate_addrs2_test_strings_vector[i]);
13992 memset(&test_vector[i], '\0', sizeof(test_vector[i]));
13993 memcpy(&test_vector[i].ss,
13999 count = remove_duplicate_addrs2(test_vector, i);
14002 fprintf(stderr, "count wrong (%d) should be 14\n",
14007 for (i = 0; i < count; i++) {
14008 char addr[INET6_ADDRSTRLEN];
14010 print_sockaddr(addr, sizeof(addr), &test_vector[i].ss);
14012 if (strcmp(addr, remove_duplicate_addrs2_test_strings_result[i]) != 0) {
14013 fprintf(stderr, "mismatch on [%d] [%s] [%s]\n",
14016 remove_duplicate_addrs2_test_strings_result[i]);
14021 printf("run_local_remove_duplicate_addrs2: success\n");
14025 static bool run_local_tdb_opener(int dummy)
14031 t = tdb_open("test.tdb", 1000, TDB_CLEAR_IF_FIRST,
14032 O_RDWR|O_CREAT, 0755);
14034 perror("tdb_open failed");
14045 static bool run_local_tdb_writer(int dummy)
14051 t = tdb_open("test.tdb", 1000, 0, O_RDWR|O_CREAT, 0755);
14053 perror("tdb_open failed");
14057 val.dptr = (uint8_t *)&v;
14058 val.dsize = sizeof(v);
14064 ret = tdb_store(t, val, val, 0);
14066 printf("%s\n", tdb_errorstr(t));
14071 data = tdb_fetch(t, val);
14072 if (data.dptr != NULL) {
14073 SAFE_FREE(data.dptr);
14079 static bool run_local_canonicalize_path(int dummy)
14081 const char *src[] = {
14088 ".././././../../../boo",
14100 "/foo/bar/../baz/",
14101 "////////////////",
14102 "/////////./././././.",
14103 "/./.././../.boo/../baz",
14104 "/a/component/path",
14105 "/a/component/path/",
14106 "/a/component/path/..",
14107 "/a/component/../path/",
14108 "///a/./././///component/../////path/",
14111 const char *dst[] = {
14134 "/a/component/path",
14135 "/a/component/path",
14143 for (i = 0; src[i] != NULL; i++) {
14144 char *d = canonicalize_absolute_path(talloc_tos(), src[i]);
14146 perror("talloc fail\n");
14149 if (strcmp(d, dst[i]) != 0) {
14151 "canonicalize mismatch %s -> %s != %s",
14152 src[i], d, dst[i]);
14160 static bool run_ign_bad_negprot(int dummy)
14162 struct tevent_context *ev;
14163 struct tevent_req *req;
14164 struct smbXcli_conn *conn;
14165 struct sockaddr_storage ss;
14170 printf("starting ignore bad negprot\n");
14172 ok = resolve_name(host, &ss, 0x20, true);
14174 d_fprintf(stderr, "Could not resolve name %s\n", host);
14178 status = open_socket_out(&ss, 445, 10000, &fd);
14179 if (!NT_STATUS_IS_OK(status)) {
14180 d_fprintf(stderr, "open_socket_out failed: %s\n",
14181 nt_errstr(status));
14185 conn = smbXcli_conn_create(talloc_tos(), fd, host, SMB_SIGNING_OFF, 0,
14187 if (conn == NULL) {
14188 d_fprintf(stderr, "smbXcli_conn_create failed\n");
14192 status = smbXcli_negprot(conn, 0, PROTOCOL_CORE, PROTOCOL_CORE);
14193 if (NT_STATUS_IS_OK(status)) {
14194 d_fprintf(stderr, "smbXcli_negprot succeeded!\n");
14198 ev = samba_tevent_context_init(talloc_tos());
14200 d_fprintf(stderr, "samba_tevent_context_init failed\n");
14204 req = smb1cli_session_setup_nt1_send(
14205 ev, ev, conn, 0, getpid(), NULL, 65503, 2, 1, 0, "", "",
14206 data_blob_null, data_blob_null, 0x40,
14207 "Windows 2000 2195", "Windows 2000 5.0");
14209 d_fprintf(stderr, "smb1cli_session_setup_nt1_send failed\n");
14213 ok = tevent_req_poll_ntstatus(req, ev, &status);
14215 d_fprintf(stderr, "tevent_req_poll failed\n");
14219 status = smb1cli_session_setup_nt1_recv(req, NULL, NULL, NULL, NULL,
14221 if (!NT_STATUS_EQUAL(status, NT_STATUS_CONNECTION_RESET)) {
14222 d_fprintf(stderr, "smb1cli_session_setup_nt1_recv returned "
14223 "%s, expected NT_STATUS_CONNECTION_RESET\n",
14224 nt_errstr(status));
14230 printf("starting ignore bad negprot\n");
14235 static double create_procs(bool (*fn)(int), bool *result)
14238 volatile pid_t *child_status;
14239 volatile bool *child_status_out;
14242 struct timeval start;
14246 child_status = (volatile pid_t *)anonymous_shared_allocate(sizeof(pid_t)*torture_nprocs);
14247 if (!child_status) {
14248 printf("Failed to setup shared memory\n");
14252 child_status_out = (volatile bool *)anonymous_shared_allocate(sizeof(bool)*torture_nprocs);
14253 if (!child_status_out) {
14254 printf("Failed to setup result status shared memory\n");
14258 for (i = 0; i < torture_nprocs; i++) {
14259 child_status[i] = 0;
14260 child_status_out[i] = True;
14263 start = timeval_current();
14265 for (i=0;i<torture_nprocs;i++) {
14268 pid_t mypid = getpid();
14269 sys_srandom(((int)mypid) ^ ((int)time(NULL)));
14271 slprintf(myname,sizeof(myname),"CLIENT%d", i);
14274 if (torture_open_connection(¤t_cli, i)) break;
14275 if (tries-- == 0) {
14276 printf("pid %d failed to start\n", (int)getpid());
14282 child_status[i] = getpid();
14284 while (child_status[i] && timeval_elapsed(&start) < 5) smb_msleep(2);
14286 child_status_out[i] = fn(i);
14293 for (i=0;i<torture_nprocs;i++) {
14294 if (child_status[i]) synccount++;
14296 if (synccount == torture_nprocs) break;
14298 } while (timeval_elapsed(&start) < 30);
14300 if (synccount != torture_nprocs) {
14301 printf("FAILED TO START %d CLIENTS (started %d)\n", torture_nprocs, synccount);
14303 return timeval_elapsed(&start);
14306 /* start the client load */
14307 start = timeval_current();
14309 for (i=0;i<torture_nprocs;i++) {
14310 child_status[i] = 0;
14313 printf("%d clients started\n", torture_nprocs);
14315 for (i=0;i<torture_nprocs;i++) {
14316 while (waitpid(0, &status, 0) == -1 && errno == EINTR) /* noop */ ;
14321 for (i=0;i<torture_nprocs;i++) {
14322 if (!child_status_out[i]) {
14326 return timeval_elapsed(&start);
14329 #define FLAG_MULTIPROC 1
14335 } torture_ops[] = {
14338 .fn = run_fdpasstest,
14342 .fn = run_locktest1,
14346 .fn = run_locktest2,
14350 .fn = run_locktest3,
14354 .fn = run_locktest4,
14358 .fn = run_locktest5,
14362 .fn = run_locktest6,
14366 .fn = run_locktest7,
14370 .fn = run_locktest8,
14374 .fn = run_locktest9a,
14378 .fn = run_locktest9b,
14382 .fn = run_locktest10,
14386 .fn = run_locktest11,
14390 .fn = run_locktest12,
14394 .fn = run_locktest13,
14398 .fn = run_unlinktest,
14402 .fn = run_browsetest,
14406 .fn = run_attrtest,
14410 .fn = run_trans2test,
14414 .fn = run_maxfidtest,
14415 .flags = FLAG_MULTIPROC,
14420 .flags = FLAG_MULTIPROC,
14423 .name = "RANDOMIPC",
14424 .fn = run_randomipc,
14427 .name = "NEGNOWAIT",
14428 .fn = run_negprot_nowait,
14450 #ifdef HAVE_KERNEL_OPLOCKS_LINUX
14462 .fn = run_dirtest1,
14465 .name = "DIR-CREATETIME",
14466 .fn = run_dir_createtime,
14470 .fn = torture_denytest1,
14474 .fn = torture_denytest2,
14478 .fn = run_tcon_test,
14482 .fn = run_tcon_devtype_test,
14486 .fn = run_readwritetest,
14490 .fn = run_readwritemulti,
14491 .flags = FLAG_MULTIPROC
14495 .fn = run_readwritelarge,
14498 .name = "RW-SIGNING",
14499 .fn = run_readwritelarge_signtest,
14503 .fn = run_opentest,
14507 .fn = run_simple_posix_open_test,
14510 .name = "POSIX-APPEND",
14511 .fn = run_posix_append,
14514 .name = "POSIX-SYMLINK-ACL",
14515 .fn = run_acl_symlink_test,
14518 .name = "POSIX-SYMLINK-EA",
14519 .fn = run_ea_symlink_test,
14522 .name = "POSIX-STREAM-DELETE",
14523 .fn = run_posix_stream_delete,
14526 .name = "POSIX-OFD-LOCK",
14527 .fn = run_posix_ofd_lock_test,
14530 .name = "POSIX-BLOCKING-LOCK",
14531 .fn = run_posix_blocking_lock,
14534 .name = "POSIX-MKDIR",
14535 .fn = run_posix_mkdir_test,
14538 .name = "POSIX-ACL-OPLOCK",
14539 .fn = run_posix_acl_oplock_test,
14542 .name = "POSIX-ACL-SHAREROOT",
14543 .fn = run_posix_acl_shareroot_test,
14546 .name = "WINDOWS-BAD-SYMLINK",
14547 .fn = run_symlink_open_test,
14550 .name = "CASE-INSENSITIVE-CREATE",
14551 .fn = run_case_insensitive_create,
14554 .name = "ASYNC-ECHO",
14555 .fn = run_async_echo,
14558 .name = "UID-REGRESSION-TEST",
14559 .fn = run_uid_regression_test,
14562 .name = "SHORTNAME-TEST",
14563 .fn = run_shortname_test,
14566 .name = "ADDRCHANGE",
14567 .fn = run_addrchange,
14571 .name = "OPENATTR",
14572 .fn = run_openattrtest,
14584 .name = "RENAME-ACCESS",
14585 .fn = run_rename_access,
14588 .name = "OWNER-RIGHTS",
14589 .fn = run_owner_rights,
14593 .fn = run_deletetest,
14596 .name = "DELETE-STREAM",
14597 .fn = run_delete_stream,
14600 .name = "DELETE-PRINT",
14601 .fn = run_delete_print_test,
14604 .name = "WILDDELETE",
14605 .fn = run_wild_deletetest,
14608 .name = "DELETE-LN",
14609 .fn = run_deletetest_ln,
14612 .name = "PROPERTIES",
14613 .fn = run_properties,
14617 .fn = torture_mangle,
14624 .name = "MANGLE-ILLEGAL",
14625 .fn = run_mangle_illegal,
14632 .name = "TRANS2SCAN",
14633 .fn = torture_trans2_scan,
14636 .name = "NTTRANSSCAN",
14637 .fn = torture_nttrans_scan,
14641 .fn = torture_utable,
14644 .name = "CASETABLE",
14645 .fn = torture_casetable,
14648 .name = "ERRMAPEXTRACT",
14649 .fn = run_error_map_extract,
14652 .name = "PIPE_NUMBER",
14653 .fn = run_pipe_number,
14657 .fn = run_tcon2_test,
14661 .fn = torture_ioctl_test,
14665 .fn = torture_chkpath_test,
14669 .fn = run_fdsesstest,
14676 .name = "SESSSETUP_BENCH",
14677 .fn = run_sesssetup_bench,
14692 .name = "WINDOWS-WRITE",
14693 .fn = run_windows_write,
14696 .name = "LARGE_READX",
14697 .fn = run_large_readx,
14700 .name = "MSDFS-ATTRIBUTE",
14701 .fn = run_msdfs_attribute,
14704 .name = "NTTRANS-CREATE",
14705 .fn = run_nttrans_create,
14708 .name = "NTTRANS-FSCTL",
14709 .fn = run_nttrans_fsctl,
14712 .name = "CLI_ECHO",
14713 .fn = run_cli_echo,
14716 .name = "CLI_SPLICE",
14717 .fn = run_cli_splice,
14724 .name = "STREAMERROR",
14725 .fn = run_streamerror,
14728 .name = "NOTIFY-BENCH",
14729 .fn = run_notify_bench,
14732 .name = "NOTIFY-BENCH2",
14733 .fn = run_notify_bench2,
14736 .name = "NOTIFY-BENCH3",
14737 .fn = run_notify_bench3,
14740 .name = "BAD-NBT-SESSION",
14741 .fn = run_bad_nbt_session,
14744 .name = "IGN-BAD-NEGPROT",
14745 .fn = run_ign_bad_negprot,
14748 .name = "SMB-ANY-CONNECT",
14749 .fn = run_smb_any_connect,
14752 .name = "NOTIFY-ONLINE",
14753 .fn = run_notify_online,
14756 .name = "SMB2-BASIC",
14757 .fn = run_smb2_basic,
14760 .name = "SMB2-NEGPROT",
14761 .fn = run_smb2_negprot,
14764 .name = "SMB2-ANONYMOUS",
14765 .fn = run_smb2_anonymous,
14768 .name = "SMB2-SESSION-RECONNECT",
14769 .fn = run_smb2_session_reconnect,
14772 .name = "SMB2-TCON-DEPENDENCE",
14773 .fn = run_smb2_tcon_dependence,
14776 .name = "SMB2-MULTI-CHANNEL",
14777 .fn = run_smb2_multi_channel,
14780 .name = "SMB2-SESSION-REAUTH",
14781 .fn = run_smb2_session_reauth,
14784 .name = "SMB2-FTRUNCATE",
14785 .fn = run_smb2_ftruncate,
14788 .name = "SMB2-DIR-FSYNC",
14789 .fn = run_smb2_dir_fsync,
14792 .name = "SMB2-PATH-SLASH",
14793 .fn = run_smb2_path_slash,
14796 .name = "SMB1-SYSTEM-SECURITY",
14797 .fn = run_smb1_system_security,
14800 .name = "SMB2-SACL",
14801 .fn = run_smb2_sacl,
14804 .name = "SMB2-QUOTA1",
14805 .fn = run_smb2_quota1,
14808 .name = "CLEANUP1",
14809 .fn = run_cleanup1,
14812 .name = "CLEANUP2",
14813 .fn = run_cleanup2,
14816 .name = "CLEANUP4",
14817 .fn = run_cleanup4,
14820 .name = "OPLOCK-CANCEL",
14821 .fn = run_oplock_cancel,
14828 .name = "LOCAL-SUBSTITUTE",
14829 .fn = run_local_substitute,
14832 .name = "LOCAL-GENCACHE",
14833 .fn = run_local_gencache,
14836 .name = "LOCAL-DBWRAP-WATCH1",
14837 .fn = run_dbwrap_watch1,
14840 .name = "LOCAL-DBWRAP-WATCH2",
14841 .fn = run_dbwrap_watch2,
14844 .name = "LOCAL-DBWRAP-WATCH3",
14845 .fn = run_dbwrap_watch3,
14848 .name = "LOCAL-DBWRAP-WATCH4",
14849 .fn = run_dbwrap_watch4,
14852 .name = "LOCAL-DBWRAP-DO-LOCKED1",
14853 .fn = run_dbwrap_do_locked1,
14856 .name = "LOCAL-MESSAGING-READ1",
14857 .fn = run_messaging_read1,
14860 .name = "LOCAL-MESSAGING-READ2",
14861 .fn = run_messaging_read2,
14864 .name = "LOCAL-MESSAGING-READ3",
14865 .fn = run_messaging_read3,
14868 .name = "LOCAL-MESSAGING-READ4",
14869 .fn = run_messaging_read4,
14872 .name = "LOCAL-MESSAGING-FDPASS1",
14873 .fn = run_messaging_fdpass1,
14876 .name = "LOCAL-MESSAGING-FDPASS2",
14877 .fn = run_messaging_fdpass2,
14880 .name = "LOCAL-MESSAGING-FDPASS2a",
14881 .fn = run_messaging_fdpass2a,
14884 .name = "LOCAL-MESSAGING-FDPASS2b",
14885 .fn = run_messaging_fdpass2b,
14888 .name = "LOCAL-MESSAGING-SEND-ALL",
14889 .fn = run_messaging_send_all,
14892 .name = "LOCAL-BASE64",
14893 .fn = run_local_base64,
14896 .name = "LOCAL-RBTREE",
14897 .fn = run_local_rbtree,
14900 .name = "LOCAL-MEMCACHE",
14901 .fn = run_local_memcache,
14904 .name = "LOCAL-STREAM-NAME",
14905 .fn = run_local_stream_name,
14908 .name = "WBCLIENT-MULTI-PING",
14909 .fn = run_wbclient_multi_ping,
14912 .name = "LOCAL-string_to_sid",
14913 .fn = run_local_string_to_sid,
14916 .name = "LOCAL-sid_to_string",
14917 .fn = run_local_sid_to_string,
14920 .name = "LOCAL-binary_to_sid",
14921 .fn = run_local_binary_to_sid,
14924 .name = "LOCAL-DBTRANS",
14925 .fn = run_local_dbtrans,
14928 .name = "LOCAL-TEVENT-POLL",
14929 .fn = run_local_tevent_poll,
14932 .name = "LOCAL-CONVERT-STRING",
14933 .fn = run_local_convert_string,
14936 .name = "LOCAL-CONV-AUTH-INFO",
14937 .fn = run_local_conv_auth_info,
14940 .name = "LOCAL-hex_encode_buf",
14941 .fn = run_local_hex_encode_buf,
14944 .name = "LOCAL-IDMAP-TDB-COMMON",
14945 .fn = run_idmap_tdb_common_test,
14948 .name = "LOCAL-remove_duplicate_addrs2",
14949 .fn = run_local_remove_duplicate_addrs2,
14952 .name = "local-tdb-opener",
14953 .fn = run_local_tdb_opener,
14956 .name = "local-tdb-writer",
14957 .fn = run_local_tdb_writer,
14960 .name = "LOCAL-DBWRAP-CTDB1",
14961 .fn = run_local_dbwrap_ctdb1,
14964 .name = "LOCAL-BENCH-PTHREADPOOL",
14965 .fn = run_bench_pthreadpool,
14968 .name = "LOCAL-PTHREADPOOL-TEVENT",
14969 .fn = run_pthreadpool_tevent,
14972 .name = "LOCAL-G-LOCK1",
14976 .name = "LOCAL-G-LOCK2",
14980 .name = "LOCAL-G-LOCK3",
14984 .name = "LOCAL-G-LOCK4",
14988 .name = "LOCAL-G-LOCK4A",
14989 .fn = run_g_lock4a,
14992 .name = "LOCAL-G-LOCK5",
14996 .name = "LOCAL-G-LOCK6",
15000 .name = "LOCAL-G-LOCK7",
15004 .name = "LOCAL-G-LOCK8",
15008 .name = "LOCAL-G-LOCK-PING-PONG",
15009 .fn = run_g_lock_ping_pong,
15012 .name = "LOCAL-CANONICALIZE-PATH",
15013 .fn = run_local_canonicalize_path,
15016 .name = "LOCAL-NAMEMAP-CACHE1",
15017 .fn = run_local_namemap_cache1,
15020 .name = "LOCAL-IDMAP-CACHE1",
15021 .fn = run_local_idmap_cache1,
15024 .name = "qpathinfo-bufsize",
15025 .fn = run_qpathinfo_bufsize,
15028 .name = "hide-new-files-timeout",
15029 .fn = run_hidenewfiles,
15031 #ifdef CLUSTER_SUPPORT
15033 .name = "ctdbd-conn1",
15034 .fn = run_ctdbd_conn1,
15038 .name = "readdir-timestamp",
15039 .fn = run_readdir_timestamp,
15046 /****************************************************************************
15047 run a specified test or "ALL"
15048 ****************************************************************************/
15049 static bool run_test(const char *name)
15052 bool result = True;
15053 bool found = False;
15056 if (strequal(name,"ALL")) {
15057 for (i=0;torture_ops[i].name;i++) {
15058 run_test(torture_ops[i].name);
15063 for (i=0;torture_ops[i].name;i++) {
15064 fstr_sprintf(randomfname, "\\XX%x",
15065 (unsigned)random());
15067 if (strequal(name, torture_ops[i].name)) {
15069 printf("Running %s\n", name);
15070 if (torture_ops[i].flags & FLAG_MULTIPROC) {
15071 t = create_procs(torture_ops[i].fn, &result);
15074 printf("TEST %s FAILED!\n", name);
15077 struct timeval start;
15078 start = timeval_current();
15079 if (!torture_ops[i].fn(0)) {
15081 printf("TEST %s FAILED!\n", name);
15083 t = timeval_elapsed(&start);
15085 printf("%s took %g secs\n\n", name, t);
15090 printf("Did not find a test named %s\n", name);
15098 static void usage(void)
15102 printf("WARNING samba4 test suite is much more complete nowadays.\n");
15103 printf("Please use samba4 torture.\n\n");
15105 printf("Usage: smbtorture //server/share <options> TEST1 TEST2 ...\n");
15107 printf("\t-d debuglevel\n");
15108 printf("\t-U user%%pass\n");
15109 printf("\t-k use kerberos\n");
15110 printf("\t-N numprocs\n");
15111 printf("\t-n my_netbios_name\n");
15112 printf("\t-W workgroup\n");
15113 printf("\t-o num_operations\n");
15114 printf("\t-O socket_options\n");
15115 printf("\t-m maximum protocol\n");
15116 printf("\t-L use oplocks\n");
15117 printf("\t-c CLIENT.TXT specify client load file for NBENCH\n");
15118 printf("\t-A showall\n");
15119 printf("\t-p port\n");
15120 printf("\t-s seed\n");
15121 printf("\t-b unclist_filename specify multiple shares for multiple connections\n");
15122 printf("\t-f filename filename to test\n");
15123 printf("\t-e encrypt\n");
15126 printf("tests are:");
15127 for (i=0;torture_ops[i].name;i++) {
15128 printf(" %s", torture_ops[i].name);
15132 printf("default test is ALL\n");
15137 /****************************************************************************
15139 ****************************************************************************/
15140 int main(int argc,char *argv[])
15146 bool correct = True;
15147 TALLOC_CTX *frame = talloc_stackframe();
15148 int seed = time(NULL);
15150 #ifdef HAVE_SETBUFFER
15151 setbuffer(stdout, NULL, 0);
15154 setup_logging("smbtorture", DEBUG_STDOUT);
15159 if (is_default_dyn_CONFIGFILE()) {
15160 if(getenv("SMB_CONF_PATH")) {
15161 set_dyn_CONFIGFILE(getenv("SMB_CONF_PATH"));
15164 lp_load_global(get_dyn_CONFIGFILE());
15171 for(p = argv[1]; *p; p++)
15175 if (strncmp(argv[1], "//", 2)) {
15179 fstrcpy(host, &argv[1][2]);
15180 p = strchr_m(&host[2],'/');
15185 fstrcpy(share, p+1);
15187 fstrcpy(myname, get_myname(talloc_tos()));
15189 fprintf(stderr, "Failed to get my hostname.\n");
15193 if (*username == 0 && getenv("LOGNAME")) {
15194 fstrcpy(username,getenv("LOGNAME"));
15200 fstrcpy(workgroup, lp_workgroup());
15202 while ((opt = getopt(argc, argv, "p:hW:U:n:N:O:o:m:Ll:d:Aec:ks:b:B:f:"))
15206 port_to_use = atoi(optarg);
15209 seed = atoi(optarg);
15212 fstrcpy(workgroup,optarg);
15215 lp_set_cmdline("client max protocol", optarg);
15218 torture_nprocs = atoi(optarg);
15221 torture_numops = atoi(optarg);
15224 lp_set_cmdline("log level", optarg);
15230 use_oplocks = True;
15233 local_path = optarg;
15236 torture_showall = True;
15239 fstrcpy(myname, optarg);
15242 client_txt = optarg;
15249 use_kerberos = True;
15251 d_printf("No kerberos support compiled in\n");
15257 fstrcpy(username,optarg);
15258 p = strchr_m(username,'%');
15261 fstrcpy(password, p+1);
15266 fstrcpy(multishare_conn_fname, optarg);
15267 use_multishare_conn = True;
15270 torture_blocksize = atoi(optarg);
15273 test_filename = SMB_STRDUP(optarg);
15276 printf("Unknown option %c (%d)\n", (char)opt, opt);
15281 d_printf("using seed %d\n", seed);
15285 if(use_kerberos && !gotuser) gotpass = True;
15288 char pwd[256] = {0};
15291 rc = samba_getpass("Password:", pwd, sizeof(pwd), false, false);
15293 fstrcpy(password, pwd);
15298 printf("host=%s share=%s user=%s myname=%s\n",
15299 host, share, username, myname);
15301 torture_creds = cli_session_creds_init(frame,
15307 false, /* fallback_after_kerberos */
15308 false, /* use_ccache */
15309 false); /* password_is_nt_hash */
15310 if (torture_creds == NULL) {
15311 d_printf("cli_session_creds_init() failed.\n");
15315 if (argc == optind) {
15316 correct = run_test("ALL");
15318 for (i=optind;i<argc;i++) {
15319 if (!run_test(argv[i])) {
15325 TALLOC_FREE(frame);