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 "tldap_tls_connect.h"
31 #include "../librpc/gen_ndr/svcctl.h"
32 #include "../lib/util/memcache.h"
33 #include "nsswitch/winbind_client.h"
34 #include "dbwrap/dbwrap.h"
35 #include "dbwrap/dbwrap_open.h"
36 #include "dbwrap/dbwrap_rbt.h"
37 #include "async_smb.h"
38 #include "libsmb/libsmb.h"
39 #include "libsmb/clirap.h"
41 #include "libsmb/nmblib.h"
42 #include "../lib/util/tevent_ntstatus.h"
44 #include "../libcli/smb/read_smb.h"
45 #include "../libcli/smb/smbXcli_base.h"
46 #include "lib/util/sys_rw_data.h"
47 #include "lib/util/base64.h"
48 #include "lib/util/time.h"
49 #include "lib/gencache.h"
50 #include "lib/util/sys_rw.h"
51 #include "lib/util/asn1.h"
52 #include "lib/util/util_file.h"
53 #include "lib/param/param.h"
54 #include "auth/gensec/gensec.h"
55 #include "lib/util/string_wrappers.h"
56 #include "source3/lib/substitute.h"
58 #include "source4/lib/tls/tls.h"
61 #include <gnutls/gnutls.h>
62 #include <gnutls/crypto.h>
67 fstring host
, workgroup
, share
, password
, username
, myname
;
68 struct cli_credentials
*torture_creds
;
69 static const char *sockops
="TCP_NODELAY";
71 static int port_to_use
=0;
72 int torture_numops
=100;
73 int torture_blocksize
=1024*1024;
74 static int procnum
; /* records process count number when forking */
75 static struct cli_state
*current_cli
;
76 static fstring randomfname
;
77 static bool use_oplocks
;
78 static bool use_level_II_oplocks
;
79 static const char *client_txt
= "client_oplocks.txt";
80 static bool disable_spnego
;
81 static bool use_kerberos
;
82 static bool force_dos_errors
;
83 static fstring multishare_conn_fname
;
84 static bool use_multishare_conn
= False
;
85 static bool do_encrypt
;
86 static const char *local_path
= NULL
;
87 static enum smb_signing_setting signing_state
= SMB_SIGNING_DEFAULT
;
90 bool torture_showall
= False
;
92 static double create_procs(bool (*fn
)(int), bool *result
);
94 /********************************************************************
95 Ensure a connection is encrypted.
96 ********************************************************************/
98 static bool force_cli_encryption(struct cli_state
*c
,
99 const char *sharename
)
101 uint16_t major
, minor
;
102 uint32_t caplow
, caphigh
;
105 if (!SERVER_HAS_UNIX_CIFS(c
)) {
106 d_printf("Encryption required and "
107 "server that doesn't support "
108 "UNIX extensions - failing connect\n");
112 status
= cli_unix_extensions_version(c
, &major
, &minor
, &caplow
,
114 if (!NT_STATUS_IS_OK(status
)) {
115 d_printf("Encryption required and "
116 "can't get UNIX CIFS extensions "
117 "version from server: %s\n", nt_errstr(status
));
121 if (!(caplow
& CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP
)) {
122 d_printf("Encryption required and "
123 "share %s doesn't support "
124 "encryption.\n", sharename
);
128 status
= cli_smb1_setup_encryption(c
, torture_creds
);
129 if (!NT_STATUS_IS_OK(status
)) {
130 d_printf("Encryption required and "
131 "setup failed with error %s.\n",
140 static struct cli_state
*open_nbt_connection(void)
146 if (disable_spnego
) {
147 flags
|= CLI_FULL_CONNECTION_DONT_SPNEGO
;
151 flags
|= CLI_FULL_CONNECTION_OPLOCKS
;
154 if (use_level_II_oplocks
) {
155 flags
|= CLI_FULL_CONNECTION_LEVEL_II_OPLOCKS
;
158 if (force_dos_errors
) {
159 flags
|= CLI_FULL_CONNECTION_FORCE_DOS_ERRORS
;
162 status
= cli_connect_nb(NULL
,
171 if (!NT_STATUS_IS_OK(status
)) {
172 printf("Failed to connect with %s. Error %s\n", host
, nt_errstr(status
) );
176 cli_set_timeout(c
, 120000); /* set a really long timeout (2 minutes) */
181 /****************************************************************************
182 Send a corrupt session request. See rfc1002.txt 4.3 and 4.3.2.
183 ****************************************************************************/
185 static bool cli_bad_session_request(int fd
,
186 struct nmb_name
*calling
, struct nmb_name
*called
)
195 uint8_t message_type
;
197 struct tevent_context
*ev
;
198 struct tevent_req
*req
;
200 frame
= talloc_stackframe();
202 iov
[0].iov_base
= len_buf
;
203 iov
[0].iov_len
= sizeof(len_buf
);
205 /* put in the destination name */
207 iov
[1].iov_base
= name_mangle(talloc_tos(), called
->name
,
209 if (iov
[1].iov_base
== NULL
) {
212 iov
[1].iov_len
= name_len((unsigned char *)iov
[1].iov_base
,
213 talloc_get_size(iov
[1].iov_base
));
217 iov
[2].iov_base
= name_mangle(talloc_tos(), calling
->name
,
219 if (iov
[2].iov_base
== NULL
) {
222 iov
[2].iov_len
= name_len((unsigned char *)iov
[2].iov_base
,
223 talloc_get_size(iov
[2].iov_base
));
225 /* Deliberately corrupt the name len (first byte) */
226 *((uint8_t *)iov
[2].iov_base
) = 100;
228 /* send a session request (RFC 1002) */
229 /* setup the packet length
230 * Remove four bytes from the length count, since the length
231 * field in the NBT Session Service header counts the number
232 * of bytes which follow. The cli_send_smb() function knows
233 * about this and accounts for those four bytes.
237 _smb_setlen(len_buf
, iov
[1].iov_len
+ iov
[2].iov_len
);
238 SCVAL(len_buf
,0,0x81);
240 len
= write_data_iov(fd
, iov
, 3);
245 ev
= samba_tevent_context_init(frame
);
249 req
= read_smb_send(frame
, ev
, fd
);
253 if (!tevent_req_poll(req
, ev
)) {
256 len
= read_smb_recv(req
, talloc_tos(), &inbuf
, &err
);
263 message_type
= CVAL(inbuf
, 0);
264 if (message_type
!= 0x83) {
265 d_fprintf(stderr
, "Expected msg type 0x83, got 0x%2.2x\n",
270 if (smb_len(inbuf
) != 1) {
271 d_fprintf(stderr
, "Expected smb_len 1, got %d\n",
272 (int)smb_len(inbuf
));
276 error
= CVAL(inbuf
, 4);
278 d_fprintf(stderr
, "Expected error 0x82, got %d\n",
289 /* Insert a NULL at the first separator of the given path and return a pointer
290 * to the remainder of the string.
293 terminate_path_at_separator(char * path
)
301 if ((p
= strchr_m(path
, '/'))) {
306 if ((p
= strchr_m(path
, '\\'))) {
316 parse a //server/share type UNC name
318 bool smbcli_parse_unc(const char *unc_name
, TALLOC_CTX
*mem_ctx
,
319 char **hostname
, char **sharename
)
323 *hostname
= *sharename
= NULL
;
325 if (strncmp(unc_name
, "\\\\", 2) &&
326 strncmp(unc_name
, "//", 2)) {
330 *hostname
= talloc_strdup(mem_ctx
, &unc_name
[2]);
331 p
= terminate_path_at_separator(*hostname
);
334 *sharename
= talloc_strdup(mem_ctx
, p
);
335 terminate_path_at_separator(*sharename
);
338 if (*hostname
&& *sharename
) {
342 TALLOC_FREE(*hostname
);
343 TALLOC_FREE(*sharename
);
347 static bool torture_open_connection_share(struct cli_state
**c
,
348 const char *hostname
,
349 const char *sharename
,
354 status
= cli_full_connection_creds(NULL
,
364 if (!NT_STATUS_IS_OK(status
)) {
365 printf("failed to open share connection: //%s/%s port:%d - %s\n",
366 hostname
, sharename
, port_to_use
, nt_errstr(status
));
370 cli_set_timeout(*c
, 120000); /* set a really long timeout (2 minutes) */
373 return force_cli_encryption(*c
,
379 bool torture_open_connection_flags(struct cli_state
**c
, int conn_index
, int flags
)
381 char **unc_list
= NULL
;
382 int num_unc_names
= 0;
385 if (use_multishare_conn
==True
) {
387 unc_list
= file_lines_load(multishare_conn_fname
, &num_unc_names
, 0, NULL
);
388 if (!unc_list
|| num_unc_names
<= 0) {
389 printf("Failed to load unc names list from '%s'\n", multishare_conn_fname
);
393 if (!smbcli_parse_unc(unc_list
[conn_index
% num_unc_names
],
395 printf("Failed to parse UNC name %s\n",
396 unc_list
[conn_index
% num_unc_names
]);
397 TALLOC_FREE(unc_list
);
401 result
= torture_open_connection_share(c
, h
, s
, flags
);
403 /* h, s were copied earlier */
404 TALLOC_FREE(unc_list
);
408 return torture_open_connection_share(c
, host
, share
, flags
);
411 bool torture_open_connection(struct cli_state
**c
, int conn_index
)
413 int flags
= CLI_FULL_CONNECTION_FORCE_SMB1
;
416 flags
|= CLI_FULL_CONNECTION_OPLOCKS
;
418 if (use_level_II_oplocks
) {
419 flags
|= CLI_FULL_CONNECTION_LEVEL_II_OPLOCKS
;
422 return torture_open_connection_flags(c
, conn_index
, flags
);
425 bool torture_init_connection(struct cli_state
**pcli
)
427 struct cli_state
*cli
;
429 cli
= open_nbt_connection();
438 bool torture_cli_session_setup2(struct cli_state
*cli
, uint16_t *new_vuid
)
440 uint16_t old_vuid
= cli_state_get_uid(cli
);
444 cli_state_set_uid(cli
, 0);
445 status
= cli_session_setup_creds(cli
, torture_creds
);
446 ret
= NT_STATUS_IS_OK(status
);
447 *new_vuid
= cli_state_get_uid(cli
);
448 cli_state_set_uid(cli
, old_vuid
);
453 bool torture_close_connection(struct cli_state
*c
)
458 status
= cli_tdis(c
);
459 if (!NT_STATUS_IS_OK(status
)) {
460 printf("tdis failed (%s)\n", nt_errstr(status
));
469 void torture_conn_set_sockopt(struct cli_state
*cli
)
471 smbXcli_conn_set_sockopt(cli
->conn
, sockops
);
474 static NTSTATUS
torture_delete_fn(struct file_info
*finfo
,
479 char *filename
= NULL
;
480 char *dirname
= NULL
;
482 TALLOC_CTX
*frame
= talloc_stackframe();
483 struct cli_state
*cli
= (struct cli_state
*)state
;
485 if (ISDOT(finfo
->name
) || ISDOTDOT(finfo
->name
)) {
490 dirname
= talloc_strdup(frame
, pattern
);
491 if (dirname
== NULL
) {
493 return NT_STATUS_NO_MEMORY
;
495 p
= strrchr_m(dirname
, '\\');
497 /* Remove the terminating '\' */
500 if (dirname
[0] != '\0') {
501 filename
= talloc_asprintf(frame
,
506 filename
= talloc_asprintf(frame
,
510 if (filename
== NULL
) {
512 return NT_STATUS_NO_MEMORY
;
514 if (finfo
->attr
& FILE_ATTRIBUTE_DIRECTORY
) {
515 char *subdirname
= talloc_asprintf(frame
,
518 if (subdirname
== NULL
) {
520 return NT_STATUS_NO_MEMORY
;
522 status
= cli_list(cli
,
524 FILE_ATTRIBUTE_DIRECTORY
|
525 FILE_ATTRIBUTE_HIDDEN
|
526 FILE_ATTRIBUTE_SYSTEM
,
529 if (!NT_STATUS_IS_OK(status
)) {
530 printf("torture_delete_fn: cli_list "
531 "of %s failed (%s)\n",
537 status
= cli_rmdir(cli
, filename
);
539 status
= cli_unlink(cli
,
541 FILE_ATTRIBUTE_SYSTEM
|
542 FILE_ATTRIBUTE_HIDDEN
);
544 if (!NT_STATUS_IS_OK(status
)) {
545 if (finfo
->attr
& FILE_ATTRIBUTE_DIRECTORY
) {
546 printf("torture_delete_fn: cli_rmdir"
547 " of %s failed (%s)\n",
551 printf("torture_delete_fn: cli_unlink"
552 " of %s failed (%s)\n",
561 void torture_deltree(struct cli_state
*cli
, const char *dname
)
566 /* It might be a file */
567 (void)cli_unlink(cli
,
569 FILE_ATTRIBUTE_SYSTEM
|
570 FILE_ATTRIBUTE_HIDDEN
);
572 mask
= talloc_asprintf(cli
,
576 printf("torture_deltree: talloc_asprintf failed\n");
580 status
= cli_list(cli
,
582 FILE_ATTRIBUTE_DIRECTORY
|
583 FILE_ATTRIBUTE_HIDDEN
|
584 FILE_ATTRIBUTE_SYSTEM
,
587 if (!NT_STATUS_IS_OK(status
)) {
588 printf("torture_deltree: cli_list of %s failed (%s)\n",
593 status
= cli_rmdir(cli
, dname
);
594 if (!NT_STATUS_IS_OK(status
)) {
595 printf("torture_deltree: cli_rmdir of %s failed (%s)\n",
601 /* check if the server produced the expected dos or nt error code */
602 static bool check_both_error(int line
, NTSTATUS status
,
603 uint8_t eclass
, uint32_t ecode
, NTSTATUS nterr
)
605 if (NT_STATUS_IS_DOS(status
)) {
609 /* Check DOS error */
610 cclass
= NT_STATUS_DOS_CLASS(status
);
611 num
= NT_STATUS_DOS_CODE(status
);
613 if (eclass
!= cclass
|| ecode
!= num
) {
614 printf("unexpected error code class=%d code=%d\n",
615 (int)cclass
, (int)num
);
616 printf(" expected %d/%d %s (line=%d)\n",
617 (int)eclass
, (int)ecode
, nt_errstr(nterr
), line
);
622 if (!NT_STATUS_EQUAL(nterr
, status
)) {
623 printf("unexpected error code %s\n",
625 printf(" expected %s (line=%d)\n",
626 nt_errstr(nterr
), line
);
635 /* check if the server produced the expected error code */
636 static bool check_error(int line
, NTSTATUS status
,
637 uint8_t eclass
, uint32_t ecode
, NTSTATUS nterr
)
639 if (NT_STATUS_IS_DOS(status
)) {
643 /* Check DOS error */
645 cclass
= NT_STATUS_DOS_CLASS(status
);
646 num
= NT_STATUS_DOS_CODE(status
);
648 if (eclass
!= cclass
|| ecode
!= num
) {
649 printf("unexpected error code class=%d code=%d\n",
650 (int)cclass
, (int)num
);
651 printf(" expected %d/%d %s (line=%d)\n",
652 (int)eclass
, (int)ecode
, nt_errstr(nterr
),
660 if (NT_STATUS_V(nterr
) != NT_STATUS_V(status
)) {
661 printf("unexpected error code %s\n",
663 printf(" expected %s (line=%d)\n", nt_errstr(nterr
),
672 NTSTATUS
cli_qpathinfo1(struct cli_state
*cli
,
680 int timezone
= smb1cli_conn_server_time_zone(cli
->conn
);
681 time_t (*date_fn
)(const void *buf
, int serverzone
) = NULL
;
682 uint8_t *rdata
= NULL
;
686 status
= cli_qpathinfo(talloc_tos(),
694 if (!NT_STATUS_IS_OK(status
)) {
698 date_fn
= make_unix_date
;
700 date_fn
= make_unix_date2
;
704 *change_time
= date_fn(rdata
+ 0, timezone
);
707 *access_time
= date_fn(rdata
+ 4, timezone
);
710 *write_time
= date_fn(rdata
+ 8, timezone
);
713 *size
= PULL_LE_U32(rdata
, 12);
716 *pattr
= PULL_LE_U16(rdata
, l1_attrFile
);
721 static bool wait_lock(struct cli_state
*c
, int fnum
, uint32_t offset
, uint32_t len
)
725 status
= cli_lock32(c
, fnum
, offset
, len
, -1, WRITE_LOCK
);
727 while (!NT_STATUS_IS_OK(status
)) {
728 if (!check_both_error(__LINE__
, status
, ERRDOS
,
729 ERRlock
, NT_STATUS_LOCK_NOT_GRANTED
)) {
733 status
= cli_lock32(c
, fnum
, offset
, len
, -1, WRITE_LOCK
);
740 static bool rw_torture(struct cli_state
*c
)
742 const char *lockfname
= "\\torture.lck";
746 pid_t pid2
, pid
= getpid();
753 memset(buf
, '\0', sizeof(buf
));
755 status
= cli_openx(c
, lockfname
, O_RDWR
| O_CREAT
| O_EXCL
,
757 if (!NT_STATUS_IS_OK(status
)) {
758 status
= cli_openx(c
, lockfname
, O_RDWR
, DENY_NONE
, &fnum2
);
760 if (!NT_STATUS_IS_OK(status
)) {
761 printf("open of %s failed (%s)\n",
762 lockfname
, nt_errstr(status
));
766 for (i
=0;i
<torture_numops
;i
++) {
767 unsigned n
= (unsigned)sys_random()%10;
770 printf("%d\r", i
); fflush(stdout
);
772 slprintf(fname
, sizeof(fstring
) - 1, "\\torture.%u", n
);
774 if (!wait_lock(c
, fnum2
, n
*sizeof(int), sizeof(int))) {
778 status
= cli_openx(c
, fname
, O_RDWR
| O_CREAT
| O_TRUNC
,
780 if (!NT_STATUS_IS_OK(status
)) {
781 printf("open failed (%s)\n", nt_errstr(status
));
786 status
= cli_writeall(c
, fnum
, 0, (uint8_t *)&pid
, 0,
788 if (!NT_STATUS_IS_OK(status
)) {
789 printf("write failed (%s)\n", nt_errstr(status
));
794 status
= cli_writeall(c
, fnum
, 0, (uint8_t *)buf
,
795 sizeof(pid
)+(j
*sizeof(buf
)),
797 if (!NT_STATUS_IS_OK(status
)) {
798 printf("write failed (%s)\n",
806 status
= cli_read(c
, fnum
, (char *)&pid2
, 0, sizeof(pid
),
808 if (!NT_STATUS_IS_OK(status
)) {
809 printf("read failed (%s)\n", nt_errstr(status
));
811 } else if (nread
!= sizeof(pid
)) {
812 printf("read/write compare failed: "
813 "recv %ld req %ld\n", (unsigned long)nread
,
814 (unsigned long)sizeof(pid
));
819 printf("data corruption!\n");
823 status
= cli_close(c
, fnum
);
824 if (!NT_STATUS_IS_OK(status
)) {
825 printf("close failed (%s)\n", nt_errstr(status
));
829 status
= cli_unlink(c
, fname
, FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
);
830 if (!NT_STATUS_IS_OK(status
)) {
831 printf("unlink failed (%s)\n", nt_errstr(status
));
835 status
= cli_unlock(c
, fnum2
, n
*sizeof(int), sizeof(int));
836 if (!NT_STATUS_IS_OK(status
)) {
837 printf("unlock failed (%s)\n", nt_errstr(status
));
843 cli_unlink(c
, lockfname
, FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
);
850 static bool run_torture(int dummy
)
852 struct cli_state
*cli
;
857 smbXcli_conn_set_sockopt(cli
->conn
, sockops
);
859 ret
= rw_torture(cli
);
861 if (!torture_close_connection(cli
)) {
868 static bool rw_torture3(struct cli_state
*c
, char *lockfname
)
870 uint16_t fnum
= (uint16_t)-1;
875 unsigned countprev
= 0;
878 NTSTATUS status
= NT_STATUS_OK
;
881 for (i
= 0; i
< sizeof(buf
); i
+= sizeof(uint32_t))
883 SIVAL(buf
, i
, sys_random());
890 FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
);
891 if (!NT_STATUS_IS_OK(status
)) {
892 printf("unlink failed (%s) (normal, this file should "
893 "not exist)\n", nt_errstr(status
));
896 status
= cli_openx(c
, lockfname
, O_RDWR
| O_CREAT
| O_EXCL
,
898 if (!NT_STATUS_IS_OK(status
)) {
899 printf("first open read/write of %s failed (%s)\n",
900 lockfname
, nt_errstr(status
));
906 for (i
= 0; i
< 500 && fnum
== (uint16_t)-1; i
++)
908 status
= cli_openx(c
, lockfname
, O_RDONLY
,
910 if (NT_STATUS_IS_OK(status
)) {
915 if (!NT_STATUS_IS_OK(status
)) {
916 printf("second open read-only of %s failed (%s)\n",
917 lockfname
, nt_errstr(status
));
923 for (count
= 0; count
< sizeof(buf
); count
+= sent
)
925 if (count
>= countprev
) {
926 printf("%d %8d\r", i
, count
);
929 countprev
+= (sizeof(buf
) / 20);
934 sent
= ((unsigned)sys_random()%(20))+ 1;
935 if (sent
> sizeof(buf
) - count
)
937 sent
= sizeof(buf
) - count
;
940 status
= cli_writeall(c
, fnum
, 0, (uint8_t *)buf
+count
,
942 if (!NT_STATUS_IS_OK(status
)) {
943 printf("write failed (%s)\n",
950 status
= cli_read(c
, fnum
, buf_rd
+count
, count
,
951 sizeof(buf
)-count
, &sent
);
952 if(!NT_STATUS_IS_OK(status
)) {
953 printf("read failed offset:%d size:%ld (%s)\n",
954 count
, (unsigned long)sizeof(buf
)-count
,
958 } else if (sent
> 0) {
959 if (memcmp(buf_rd
+count
, buf
+count
, sent
) != 0)
961 printf("read/write compare failed\n");
962 printf("offset: %d req %ld recvd %ld\n", count
, (unsigned long)sizeof(buf
)-count
, (unsigned long)sent
);
971 status
= cli_close(c
, fnum
);
972 if (!NT_STATUS_IS_OK(status
)) {
973 printf("close failed (%s)\n", nt_errstr(status
));
980 static bool rw_torture2(struct cli_state
*c1
, struct cli_state
*c2
)
982 const char *lockfname
= "\\torture2.lck";
992 status
= cli_unlink(c1
, lockfname
, FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
);
993 if (!NT_STATUS_IS_OK(status
)) {
994 printf("unlink failed (%s) (normal, this file should not exist)\n", nt_errstr(status
));
997 status
= cli_openx(c1
, lockfname
, O_RDWR
| O_CREAT
| O_EXCL
,
999 if (!NT_STATUS_IS_OK(status
)) {
1000 printf("first open read/write of %s failed (%s)\n",
1001 lockfname
, nt_errstr(status
));
1005 status
= cli_openx(c2
, lockfname
, O_RDONLY
, DENY_NONE
, &fnum2
);
1006 if (!NT_STATUS_IS_OK(status
)) {
1007 printf("second open read-only of %s failed (%s)\n",
1008 lockfname
, nt_errstr(status
));
1009 cli_close(c1
, fnum1
);
1013 for (i
= 0; i
< torture_numops
; i
++)
1015 size_t buf_size
= ((unsigned)sys_random()%(sizeof(buf
)-1))+ 1;
1017 printf("%d\r", i
); fflush(stdout
);
1020 generate_random_buffer((unsigned char *)buf
, buf_size
);
1022 status
= cli_writeall(c1
, fnum1
, 0, (uint8_t *)buf
, 0,
1024 if (!NT_STATUS_IS_OK(status
)) {
1025 printf("write failed (%s)\n", nt_errstr(status
));
1030 status
= cli_read(c2
, fnum2
, buf_rd
, 0, buf_size
, &bytes_read
);
1031 if(!NT_STATUS_IS_OK(status
)) {
1032 printf("read failed (%s)\n", nt_errstr(status
));
1035 } else if (bytes_read
!= buf_size
) {
1036 printf("read failed\n");
1037 printf("read %ld, expected %ld\n",
1038 (unsigned long)bytes_read
,
1039 (unsigned long)buf_size
);
1044 if (memcmp(buf_rd
, buf
, buf_size
) != 0)
1046 printf("read/write compare failed\n");
1052 status
= cli_close(c2
, fnum2
);
1053 if (!NT_STATUS_IS_OK(status
)) {
1054 printf("close failed (%s)\n", nt_errstr(status
));
1058 status
= cli_close(c1
, fnum1
);
1059 if (!NT_STATUS_IS_OK(status
)) {
1060 printf("close failed (%s)\n", nt_errstr(status
));
1064 status
= cli_unlink(c1
, lockfname
, FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
);
1065 if (!NT_STATUS_IS_OK(status
)) {
1066 printf("unlink failed (%s)\n", nt_errstr(status
));
1073 static bool run_readwritetest(int dummy
)
1075 struct cli_state
*cli1
, *cli2
;
1076 bool test1
, test2
= False
;
1078 if (!torture_open_connection(&cli1
, 0) || !torture_open_connection(&cli2
, 1)) {
1081 smbXcli_conn_set_sockopt(cli1
->conn
, sockops
);
1082 smbXcli_conn_set_sockopt(cli2
->conn
, sockops
);
1084 printf("starting readwritetest\n");
1086 test1
= rw_torture2(cli1
, cli2
);
1087 printf("Passed readwritetest v1: %s\n", BOOLSTR(test1
));
1090 test2
= rw_torture2(cli1
, cli1
);
1091 printf("Passed readwritetest v2: %s\n", BOOLSTR(test2
));
1094 if (!torture_close_connection(cli1
)) {
1098 if (!torture_close_connection(cli2
)) {
1102 return (test1
&& test2
);
1105 static bool run_readwritemulti(int dummy
)
1107 struct cli_state
*cli
;
1112 smbXcli_conn_set_sockopt(cli
->conn
, sockops
);
1114 printf("run_readwritemulti: fname %s\n", randomfname
);
1115 test
= rw_torture3(cli
, randomfname
);
1117 if (!torture_close_connection(cli
)) {
1124 static bool run_readwritelarge_internal(void)
1126 static struct cli_state
*cli1
;
1128 const char *lockfname
= "\\large.dat";
1131 bool correct
= True
;
1134 if (!torture_open_connection(&cli1
, 0)) {
1137 smbXcli_conn_set_sockopt(cli1
->conn
, sockops
);
1138 memset(buf
,'\0',sizeof(buf
));
1140 printf("starting readwritelarge_internal\n");
1142 cli_unlink(cli1
, lockfname
, FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
);
1144 status
= cli_openx(cli1
, lockfname
, O_RDWR
| O_CREAT
| O_EXCL
,
1146 if (!NT_STATUS_IS_OK(status
)) {
1147 printf("open read/write of %s failed (%s)\n", lockfname
, nt_errstr(status
));
1151 cli_writeall(cli1
, fnum1
, 0, (uint8_t *)buf
, 0, sizeof(buf
), NULL
);
1153 status
= cli_qfileinfo_basic(cli1
, fnum1
, NULL
, &fsize
, NULL
, NULL
,
1155 if (!NT_STATUS_IS_OK(status
)) {
1156 printf("qfileinfo failed (%s)\n", nt_errstr(status
));
1160 if (fsize
== sizeof(buf
))
1161 printf("readwritelarge_internal test 1 succeeded (size = %lx)\n",
1162 (unsigned long)fsize
);
1164 printf("readwritelarge_internal test 1 failed (size = %lx)\n",
1165 (unsigned long)fsize
);
1169 status
= cli_close(cli1
, fnum1
);
1170 if (!NT_STATUS_IS_OK(status
)) {
1171 printf("close failed (%s)\n", nt_errstr(status
));
1175 status
= cli_unlink(cli1
, lockfname
, FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
);
1176 if (!NT_STATUS_IS_OK(status
)) {
1177 printf("unlink failed (%s)\n", nt_errstr(status
));
1181 status
= cli_openx(cli1
, lockfname
, O_RDWR
| O_CREAT
| O_EXCL
,
1183 if (!NT_STATUS_IS_OK(status
)) {
1184 printf("open read/write of %s failed (%s)\n", lockfname
, nt_errstr(status
));
1188 cli_smbwrite(cli1
, fnum1
, buf
, 0, sizeof(buf
), NULL
);
1190 status
= cli_qfileinfo_basic(cli1
, fnum1
, NULL
, &fsize
, NULL
, NULL
,
1192 if (!NT_STATUS_IS_OK(status
)) {
1193 printf("qfileinfo failed (%s)\n", nt_errstr(status
));
1197 if (fsize
== sizeof(buf
))
1198 printf("readwritelarge_internal test 2 succeeded (size = %lx)\n",
1199 (unsigned long)fsize
);
1201 printf("readwritelarge_internal test 2 failed (size = %lx)\n",
1202 (unsigned long)fsize
);
1206 status
= cli_close(cli1
, fnum1
);
1207 if (!NT_STATUS_IS_OK(status
)) {
1208 printf("close failed (%s)\n", nt_errstr(status
));
1212 if (!torture_close_connection(cli1
)) {
1218 static bool run_readwritelarge(int dummy
)
1220 return run_readwritelarge_internal();
1223 static bool run_readwritelarge_signtest(int dummy
)
1226 signing_state
= SMB_SIGNING_REQUIRED
;
1227 ret
= run_readwritelarge_internal();
1228 signing_state
= SMB_SIGNING_DEFAULT
;
1235 #define ival(s) strtol(s, NULL, 0)
1237 /* run a test that simulates an approximate netbench client load */
1238 static bool run_netbench(int client
)
1240 struct cli_state
*cli
;
1245 const char *params
[20];
1246 bool correct
= True
;
1252 smbXcli_conn_set_sockopt(cli
->conn
, sockops
);
1256 slprintf(cname
,sizeof(cname
)-1, "client%d", client
);
1258 f
= fopen(client_txt
, "r");
1265 while (fgets(line
, sizeof(line
)-1, f
)) {
1269 line
[strlen(line
)-1] = 0;
1271 /* printf("[%d] %s\n", line_count, line); */
1273 all_string_sub(line
,"client1", cname
, sizeof(line
));
1275 /* parse the command parameters */
1276 params
[0] = strtok_r(line
, " ", &saveptr
);
1278 while (params
[i
]) params
[++i
] = strtok_r(NULL
, " ", &saveptr
);
1282 if (i
< 2) continue;
1284 if (!strncmp(params
[0],"SMB", 3)) {
1285 printf("ERROR: You are using a dbench 1 load file\n");
1289 if (!strcmp(params
[0],"NTCreateX")) {
1290 nb_createx(params
[1], ival(params
[2]), ival(params
[3]),
1292 } else if (!strcmp(params
[0],"Close")) {
1293 nb_close(ival(params
[1]));
1294 } else if (!strcmp(params
[0],"Rename")) {
1295 nb_rename(params
[1], params
[2]);
1296 } else if (!strcmp(params
[0],"Unlink")) {
1297 nb_unlink(params
[1]);
1298 } else if (!strcmp(params
[0],"Deltree")) {
1299 nb_deltree(params
[1]);
1300 } else if (!strcmp(params
[0],"Rmdir")) {
1301 nb_rmdir(params
[1]);
1302 } else if (!strcmp(params
[0],"QUERY_PATH_INFORMATION")) {
1303 nb_qpathinfo(params
[1]);
1304 } else if (!strcmp(params
[0],"QUERY_FILE_INFORMATION")) {
1305 nb_qfileinfo(ival(params
[1]));
1306 } else if (!strcmp(params
[0],"QUERY_FS_INFORMATION")) {
1307 nb_qfsinfo(ival(params
[1]));
1308 } else if (!strcmp(params
[0],"FIND_FIRST")) {
1309 nb_findfirst(params
[1]);
1310 } else if (!strcmp(params
[0],"WriteX")) {
1311 nb_writex(ival(params
[1]),
1312 ival(params
[2]), ival(params
[3]), ival(params
[4]));
1313 } else if (!strcmp(params
[0],"ReadX")) {
1314 nb_readx(ival(params
[1]),
1315 ival(params
[2]), ival(params
[3]), ival(params
[4]));
1316 } else if (!strcmp(params
[0],"Flush")) {
1317 nb_flush(ival(params
[1]));
1319 printf("Unknown operation %s\n", params
[0]);
1327 if (!torture_close_connection(cli
)) {
1335 /* run a test that simulates an approximate netbench client load */
1336 static bool run_nbench(int dummy
)
1339 bool correct
= True
;
1341 nbio_shmem(torture_nprocs
);
1345 signal(SIGALRM
, nb_alarm
);
1347 t
= create_procs(run_netbench
, &correct
);
1350 printf("\nThroughput %g MB/sec\n",
1351 1.0e-6 * nbio_total() / t
);
1357 This test checks for two things:
1359 1) correct support for retaining locks over a close (ie. the server
1360 must not use posix semantics)
1361 2) support for lock timeouts
1363 static bool run_locktest1(int dummy
)
1365 struct cli_state
*cli1
, *cli2
;
1366 const char *fname
= "\\lockt1.lck";
1367 uint16_t fnum1
, fnum2
, fnum3
;
1369 unsigned lock_timeout
;
1372 if (!torture_open_connection(&cli1
, 0) || !torture_open_connection(&cli2
, 1)) {
1375 smbXcli_conn_set_sockopt(cli1
->conn
, sockops
);
1376 smbXcli_conn_set_sockopt(cli2
->conn
, sockops
);
1378 printf("starting locktest1\n");
1380 cli_unlink(cli1
, fname
, FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
);
1382 status
= cli_openx(cli1
, fname
, O_RDWR
|O_CREAT
|O_EXCL
, DENY_NONE
,
1384 if (!NT_STATUS_IS_OK(status
)) {
1385 printf("open of %s failed (%s)\n", fname
, nt_errstr(status
));
1389 status
= cli_openx(cli1
, fname
, O_RDWR
, DENY_NONE
, &fnum2
);
1390 if (!NT_STATUS_IS_OK(status
)) {
1391 printf("open2 of %s failed (%s)\n", fname
, nt_errstr(status
));
1395 status
= cli_openx(cli2
, fname
, O_RDWR
, DENY_NONE
, &fnum3
);
1396 if (!NT_STATUS_IS_OK(status
)) {
1397 printf("open3 of %s failed (%s)\n", fname
, nt_errstr(status
));
1401 status
= cli_lock32(cli1
, fnum1
, 0, 4, 0, WRITE_LOCK
);
1402 if (!NT_STATUS_IS_OK(status
)) {
1403 printf("lock1 failed (%s)\n", nt_errstr(status
));
1407 status
= cli_lock32(cli2
, fnum3
, 0, 4, 0, WRITE_LOCK
);
1408 if (NT_STATUS_IS_OK(status
)) {
1409 printf("lock2 succeeded! This is a locking bug\n");
1412 if (!check_both_error(__LINE__
, status
, ERRDOS
, ERRlock
,
1413 NT_STATUS_LOCK_NOT_GRANTED
)) {
1418 lock_timeout
= (1 + (random() % 20));
1419 printf("Testing lock timeout with timeout=%u\n", lock_timeout
);
1421 status
= cli_lock32(cli2
, fnum3
, 0, 4, lock_timeout
* 1000, WRITE_LOCK
);
1422 if (NT_STATUS_IS_OK(status
)) {
1423 printf("lock3 succeeded! This is a locking bug\n");
1426 if (!check_both_error(__LINE__
, status
, ERRDOS
, ERRlock
,
1427 NT_STATUS_FILE_LOCK_CONFLICT
)) {
1433 if (ABS(t2
- t1
) < lock_timeout
-1) {
1434 printf("error: This server appears not to support timed lock requests\n");
1437 printf("server slept for %u seconds for a %u second timeout\n",
1438 (unsigned int)(t2
-t1
), lock_timeout
);
1440 status
= cli_close(cli1
, fnum2
);
1441 if (!NT_STATUS_IS_OK(status
)) {
1442 printf("close1 failed (%s)\n", nt_errstr(status
));
1446 status
= cli_lock32(cli2
, fnum3
, 0, 4, 0, WRITE_LOCK
);
1447 if (NT_STATUS_IS_OK(status
)) {
1448 printf("lock4 succeeded! This is a locking bug\n");
1451 if (!check_both_error(__LINE__
, status
, ERRDOS
, ERRlock
,
1452 NT_STATUS_FILE_LOCK_CONFLICT
)) {
1457 status
= cli_close(cli1
, fnum1
);
1458 if (!NT_STATUS_IS_OK(status
)) {
1459 printf("close2 failed (%s)\n", nt_errstr(status
));
1463 status
= cli_close(cli2
, fnum3
);
1464 if (!NT_STATUS_IS_OK(status
)) {
1465 printf("close3 failed (%s)\n", nt_errstr(status
));
1469 status
= cli_unlink(cli1
, fname
, FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
);
1470 if (!NT_STATUS_IS_OK(status
)) {
1471 printf("unlink failed (%s)\n", nt_errstr(status
));
1476 if (!torture_close_connection(cli1
)) {
1480 if (!torture_close_connection(cli2
)) {
1484 printf("Passed locktest1\n");
1489 this checks to see if a secondary tconx can use open files from an
1492 static bool run_tcon_test(int dummy
)
1494 static struct cli_state
*cli
;
1495 const char *fname
= "\\tcontest.tmp";
1497 uint32_t cnum1
, cnum2
, cnum3
;
1498 struct smbXcli_tcon
*orig_tcon
= NULL
;
1499 char *orig_share
= NULL
;
1500 uint16_t vuid1
, vuid2
;
1505 memset(buf
, '\0', sizeof(buf
));
1507 if (!torture_open_connection(&cli
, 0)) {
1510 smbXcli_conn_set_sockopt(cli
->conn
, sockops
);
1512 printf("starting tcontest\n");
1514 cli_unlink(cli
, fname
, FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
);
1516 status
= cli_openx(cli
, fname
, O_RDWR
|O_CREAT
|O_EXCL
, DENY_NONE
, &fnum1
);
1517 if (!NT_STATUS_IS_OK(status
)) {
1518 printf("open of %s failed (%s)\n", fname
, nt_errstr(status
));
1522 cnum1
= cli_state_get_tid(cli
);
1523 vuid1
= cli_state_get_uid(cli
);
1525 status
= cli_writeall(cli
, fnum1
, 0, (uint8_t *)buf
, 130, 4, NULL
);
1526 if (!NT_STATUS_IS_OK(status
)) {
1527 printf("initial write failed (%s)", nt_errstr(status
));
1531 cli_state_save_tcon_share(cli
, &orig_tcon
, &orig_share
);
1533 status
= cli_tree_connect_creds(cli
, share
, "?????", torture_creds
);
1534 if (!NT_STATUS_IS_OK(status
)) {
1535 printf("%s refused 2nd tree connect (%s)\n", host
,
1537 cli_state_restore_tcon_share(cli
, orig_tcon
, orig_share
);
1542 cnum2
= cli_state_get_tid(cli
);
1543 cnum3
= MAX(cnum1
, cnum2
) + 1; /* any invalid number */
1544 vuid2
= cli_state_get_uid(cli
) + 1;
1546 /* try a write with the wrong tid */
1547 cli_state_set_tid(cli
, cnum2
);
1549 status
= cli_writeall(cli
, fnum1
, 0, (uint8_t *)buf
, 130, 4, NULL
);
1550 if (NT_STATUS_IS_OK(status
)) {
1551 printf("* server allows write with wrong TID\n");
1554 printf("server fails write with wrong TID : %s\n",
1559 /* try a write with an invalid tid */
1560 cli_state_set_tid(cli
, cnum3
);
1562 status
= cli_writeall(cli
, fnum1
, 0, (uint8_t *)buf
, 130, 4, NULL
);
1563 if (NT_STATUS_IS_OK(status
)) {
1564 printf("* server allows write with invalid TID\n");
1567 printf("server fails write with invalid TID : %s\n",
1571 /* try a write with an invalid vuid */
1572 cli_state_set_uid(cli
, vuid2
);
1573 cli_state_set_tid(cli
, cnum1
);
1575 status
= cli_writeall(cli
, fnum1
, 0, (uint8_t *)buf
, 130, 4, NULL
);
1576 if (NT_STATUS_IS_OK(status
)) {
1577 printf("* server allows write with invalid VUID\n");
1580 printf("server fails write with invalid VUID : %s\n",
1584 cli_state_set_tid(cli
, cnum1
);
1585 cli_state_set_uid(cli
, vuid1
);
1587 status
= cli_close(cli
, fnum1
);
1588 if (!NT_STATUS_IS_OK(status
)) {
1589 printf("close failed (%s)\n", nt_errstr(status
));
1590 cli_state_restore_tcon_share(cli
, orig_tcon
, orig_share
);
1595 cli_state_set_tid(cli
, cnum2
);
1597 status
= cli_tdis(cli
);
1598 if (!NT_STATUS_IS_OK(status
)) {
1599 printf("secondary tdis failed (%s)\n", nt_errstr(status
));
1600 cli_state_restore_tcon_share(cli
, orig_tcon
, orig_share
);
1605 cli_state_restore_tcon_share(cli
, orig_tcon
, orig_share
);
1607 cli_state_set_tid(cli
, cnum1
);
1609 if (!torture_close_connection(cli
)) {
1618 checks for old style tcon support
1620 static bool run_tcon2_test(int dummy
)
1622 static struct cli_state
*cli
;
1623 uint16_t cnum
, max_xmit
;
1627 if (!torture_open_connection(&cli
, 0)) {
1630 smbXcli_conn_set_sockopt(cli
->conn
, sockops
);
1632 printf("starting tcon2 test\n");
1634 if (asprintf(&service
, "\\\\%s\\%s", host
, share
) == -1) {
1638 status
= cli_raw_tcon(cli
, service
, password
, "?????", &max_xmit
, &cnum
);
1642 if (!NT_STATUS_IS_OK(status
)) {
1643 printf("tcon2 failed : %s\n", nt_errstr(status
));
1645 printf("tcon OK : max_xmit=%d cnum=%d\n",
1646 (int)max_xmit
, (int)cnum
);
1649 if (!torture_close_connection(cli
)) {
1653 printf("Passed tcon2 test\n");
1657 static bool tcon_devtest(struct cli_state
*cli
,
1658 const char *myshare
, const char *devtype
,
1659 const char *return_devtype
,
1660 NTSTATUS expected_error
)
1665 status
= cli_tree_connect_creds(cli
, myshare
, devtype
, torture_creds
);
1667 if (NT_STATUS_IS_OK(expected_error
)) {
1668 if (NT_STATUS_IS_OK(status
)) {
1669 if (return_devtype
!= NULL
&&
1670 strequal(cli
->dev
, return_devtype
)) {
1673 printf("tconX to share %s with type %s "
1674 "succeeded but returned the wrong "
1675 "device type (got [%s] but should have got [%s])\n",
1676 myshare
, devtype
, cli
->dev
, return_devtype
);
1680 printf("tconX to share %s with type %s "
1681 "should have succeeded but failed\n",
1687 if (NT_STATUS_IS_OK(status
)) {
1688 printf("tconx to share %s with type %s "
1689 "should have failed but succeeded\n",
1693 if (NT_STATUS_EQUAL(status
, expected_error
)) {
1696 printf("Returned unexpected error\n");
1705 checks for correct tconX support
1707 static bool run_tcon_devtype_test(int dummy
)
1709 static struct cli_state
*cli1
= NULL
;
1710 int flags
= CLI_FULL_CONNECTION_FORCE_SMB1
;
1714 status
= cli_full_connection_creds(NULL
,
1721 NULL
, /* service_type */
1725 if (!NT_STATUS_IS_OK(status
)) {
1726 printf("could not open connection\n");
1730 if (!tcon_devtest(cli1
, "IPC$", "A:", NULL
, NT_STATUS_BAD_DEVICE_TYPE
))
1733 if (!tcon_devtest(cli1
, "IPC$", "?????", "IPC", NT_STATUS_OK
))
1736 if (!tcon_devtest(cli1
, "IPC$", "LPT:", NULL
, NT_STATUS_BAD_DEVICE_TYPE
))
1739 if (!tcon_devtest(cli1
, "IPC$", "IPC", "IPC", NT_STATUS_OK
))
1742 if (!tcon_devtest(cli1
, "IPC$", "FOOBA", NULL
, NT_STATUS_BAD_DEVICE_TYPE
))
1745 if (!tcon_devtest(cli1
, share
, "A:", "A:", NT_STATUS_OK
))
1748 if (!tcon_devtest(cli1
, share
, "?????", "A:", NT_STATUS_OK
))
1751 if (!tcon_devtest(cli1
, share
, "LPT:", NULL
, NT_STATUS_BAD_DEVICE_TYPE
))
1754 if (!tcon_devtest(cli1
, share
, "IPC", NULL
, NT_STATUS_BAD_DEVICE_TYPE
))
1757 if (!tcon_devtest(cli1
, share
, "FOOBA", NULL
, NT_STATUS_BAD_DEVICE_TYPE
))
1763 printf("Passed tcondevtest\n");
1770 This test checks that
1772 1) the server supports multiple locking contexts on the one SMB
1773 connection, distinguished by PID.
1775 2) the server correctly fails overlapping locks made by the same PID (this
1776 goes against POSIX behaviour, which is why it is tricky to implement)
1778 3) the server denies unlock requests by an incorrect client PID
1780 static bool run_locktest2(int dummy
)
1782 static struct cli_state
*cli
;
1783 const char *fname
= "\\lockt2.lck";
1784 uint16_t fnum1
, fnum2
, fnum3
;
1785 bool correct
= True
;
1788 if (!torture_open_connection(&cli
, 0)) {
1792 smbXcli_conn_set_sockopt(cli
->conn
, sockops
);
1794 printf("starting locktest2\n");
1796 cli_unlink(cli
, fname
, FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
);
1800 status
= cli_openx(cli
, fname
, O_RDWR
|O_CREAT
|O_EXCL
, DENY_NONE
, &fnum1
);
1801 if (!NT_STATUS_IS_OK(status
)) {
1802 printf("open of %s failed (%s)\n", fname
, nt_errstr(status
));
1806 status
= cli_openx(cli
, fname
, O_RDWR
, DENY_NONE
, &fnum2
);
1807 if (!NT_STATUS_IS_OK(status
)) {
1808 printf("open2 of %s failed (%s)\n", fname
, nt_errstr(status
));
1814 status
= cli_openx(cli
, fname
, O_RDWR
, DENY_NONE
, &fnum3
);
1815 if (!NT_STATUS_IS_OK(status
)) {
1816 printf("open3 of %s failed (%s)\n", fname
, nt_errstr(status
));
1822 status
= cli_lock32(cli
, fnum1
, 0, 4, 0, WRITE_LOCK
);
1823 if (!NT_STATUS_IS_OK(status
)) {
1824 printf("lock1 failed (%s)\n", nt_errstr(status
));
1828 status
= cli_lock32(cli
, fnum1
, 0, 4, 0, WRITE_LOCK
);
1829 if (NT_STATUS_IS_OK(status
)) {
1830 printf("WRITE lock1 succeeded! This is a locking bug\n");
1833 if (!check_both_error(__LINE__
, status
, ERRDOS
, ERRlock
,
1834 NT_STATUS_LOCK_NOT_GRANTED
)) {
1839 status
= cli_lock32(cli
, fnum2
, 0, 4, 0, WRITE_LOCK
);
1840 if (NT_STATUS_IS_OK(status
)) {
1841 printf("WRITE lock2 succeeded! This is a locking bug\n");
1844 if (!check_both_error(__LINE__
, status
, ERRDOS
, ERRlock
,
1845 NT_STATUS_LOCK_NOT_GRANTED
)) {
1850 status
= cli_lock32(cli
, fnum2
, 0, 4, 0, READ_LOCK
);
1851 if (NT_STATUS_IS_OK(status
)) {
1852 printf("READ lock2 succeeded! This is a locking bug\n");
1855 if (!check_both_error(__LINE__
, status
, ERRDOS
, ERRlock
,
1856 NT_STATUS_FILE_LOCK_CONFLICT
)) {
1861 status
= cli_lock32(cli
, fnum1
, 100, 4, 0, WRITE_LOCK
);
1862 if (!NT_STATUS_IS_OK(status
)) {
1863 printf("lock at 100 failed (%s)\n", nt_errstr(status
));
1866 if (NT_STATUS_IS_OK(cli_unlock(cli
, fnum1
, 100, 4))) {
1867 printf("unlock at 100 succeeded! This is a locking bug\n");
1871 status
= cli_unlock(cli
, fnum1
, 0, 4);
1872 if (NT_STATUS_IS_OK(status
)) {
1873 printf("unlock1 succeeded! This is a locking bug\n");
1876 if (!check_both_error(__LINE__
, status
, ERRDOS
, ERRlock
,
1877 NT_STATUS_RANGE_NOT_LOCKED
)) {
1882 status
= cli_unlock(cli
, fnum1
, 0, 8);
1883 if (NT_STATUS_IS_OK(status
)) {
1884 printf("unlock2 succeeded! This is a locking bug\n");
1887 if (!check_both_error(__LINE__
, status
, ERRDOS
, ERRlock
,
1888 NT_STATUS_RANGE_NOT_LOCKED
)) {
1893 status
= cli_lock32(cli
, fnum3
, 0, 4, 0, WRITE_LOCK
);
1894 if (NT_STATUS_IS_OK(status
)) {
1895 printf("lock3 succeeded! This is a locking bug\n");
1898 if (!check_both_error(__LINE__
, status
, ERRDOS
, ERRlock
,
1899 NT_STATUS_LOCK_NOT_GRANTED
)) {
1906 status
= cli_close(cli
, fnum1
);
1907 if (!NT_STATUS_IS_OK(status
)) {
1908 printf("close1 failed (%s)\n", nt_errstr(status
));
1912 status
= cli_close(cli
, fnum2
);
1913 if (!NT_STATUS_IS_OK(status
)) {
1914 printf("close2 failed (%s)\n", nt_errstr(status
));
1918 status
= cli_close(cli
, fnum3
);
1919 if (!NT_STATUS_IS_OK(status
)) {
1920 printf("close3 failed (%s)\n", nt_errstr(status
));
1924 if (!torture_close_connection(cli
)) {
1928 printf("locktest2 finished\n");
1935 This test checks that
1937 1) the server supports the full offset range in lock requests
1939 static bool run_locktest3(int dummy
)
1941 static struct cli_state
*cli1
, *cli2
;
1942 const char *fname
= "\\lockt3.lck";
1943 uint16_t fnum1
, fnum2
;
1946 bool correct
= True
;
1949 #define NEXT_OFFSET offset += (~(uint32_t)0) / torture_numops
1951 if (!torture_open_connection(&cli1
, 0) || !torture_open_connection(&cli2
, 1)) {
1954 smbXcli_conn_set_sockopt(cli1
->conn
, sockops
);
1955 smbXcli_conn_set_sockopt(cli2
->conn
, sockops
);
1957 printf("starting locktest3\n");
1959 cli_unlink(cli1
, fname
, FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
);
1961 status
= cli_openx(cli1
, fname
, O_RDWR
|O_CREAT
|O_EXCL
, DENY_NONE
,
1963 if (!NT_STATUS_IS_OK(status
)) {
1964 printf("open of %s failed (%s)\n", fname
, nt_errstr(status
));
1968 status
= cli_openx(cli2
, fname
, O_RDWR
, DENY_NONE
, &fnum2
);
1969 if (!NT_STATUS_IS_OK(status
)) {
1970 printf("open2 of %s failed (%s)\n", fname
, nt_errstr(status
));
1974 for (offset
=i
=0;i
<torture_numops
;i
++) {
1977 status
= cli_lock32(cli1
, fnum1
, offset
-1, 1, 0, WRITE_LOCK
);
1978 if (!NT_STATUS_IS_OK(status
)) {
1979 printf("lock1 %d failed (%s)\n",
1985 status
= cli_lock32(cli2
, fnum2
, offset
-2, 1, 0, WRITE_LOCK
);
1986 if (!NT_STATUS_IS_OK(status
)) {
1987 printf("lock2 %d failed (%s)\n",
1994 for (offset
=i
=0;i
<torture_numops
;i
++) {
1997 status
= cli_lock32(cli1
, fnum1
, offset
-2, 1, 0, WRITE_LOCK
);
1998 if (NT_STATUS_IS_OK(status
)) {
1999 printf("error: lock1 %d succeeded!\n", i
);
2003 status
= cli_lock32(cli2
, fnum2
, offset
-1, 1, 0, WRITE_LOCK
);
2004 if (NT_STATUS_IS_OK(status
)) {
2005 printf("error: lock2 %d succeeded!\n", i
);
2009 status
= cli_lock32(cli1
, fnum1
, offset
-1, 1, 0, WRITE_LOCK
);
2010 if (NT_STATUS_IS_OK(status
)) {
2011 printf("error: lock3 %d succeeded!\n", i
);
2015 status
= cli_lock32(cli2
, fnum2
, offset
-2, 1, 0, WRITE_LOCK
);
2016 if (NT_STATUS_IS_OK(status
)) {
2017 printf("error: lock4 %d succeeded!\n", i
);
2022 for (offset
=i
=0;i
<torture_numops
;i
++) {
2025 status
= cli_unlock(cli1
, fnum1
, offset
-1, 1);
2026 if (!NT_STATUS_IS_OK(status
)) {
2027 printf("unlock1 %d failed (%s)\n",
2033 status
= cli_unlock(cli2
, fnum2
, offset
-2, 1);
2034 if (!NT_STATUS_IS_OK(status
)) {
2035 printf("unlock2 %d failed (%s)\n",
2042 status
= cli_close(cli1
, fnum1
);
2043 if (!NT_STATUS_IS_OK(status
)) {
2044 printf("close1 failed (%s)\n", nt_errstr(status
));
2048 status
= cli_close(cli2
, fnum2
);
2049 if (!NT_STATUS_IS_OK(status
)) {
2050 printf("close2 failed (%s)\n", nt_errstr(status
));
2054 status
= cli_unlink(cli1
, fname
, FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
);
2055 if (!NT_STATUS_IS_OK(status
)) {
2056 printf("unlink failed (%s)\n", nt_errstr(status
));
2060 if (!torture_close_connection(cli1
)) {
2064 if (!torture_close_connection(cli2
)) {
2068 printf("finished locktest3\n");
2073 static bool test_cli_read(struct cli_state
*cli
, uint16_t fnum
,
2074 char *buf
, off_t offset
, size_t size
,
2075 size_t *nread
, size_t expect
)
2080 status
= cli_read(cli
, fnum
, buf
, offset
, size
, &l_nread
);
2082 if(!NT_STATUS_IS_OK(status
)) {
2084 } else if (l_nread
!= expect
) {
2095 #define EXPECTED(ret, v) if ((ret) != (v)) { \
2096 printf("** "); correct = False; \
2100 looks at overlapping locks
2102 static bool run_locktest4(int dummy
)
2104 static struct cli_state
*cli1
, *cli2
;
2105 const char *fname
= "\\lockt4.lck";
2106 uint16_t fnum1
, fnum2
, f
;
2109 bool correct
= True
;
2112 if (!torture_open_connection(&cli1
, 0) || !torture_open_connection(&cli2
, 1)) {
2116 smbXcli_conn_set_sockopt(cli1
->conn
, sockops
);
2117 smbXcli_conn_set_sockopt(cli2
->conn
, sockops
);
2119 printf("starting locktest4\n");
2121 cli_unlink(cli1
, fname
, FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
);
2123 cli_openx(cli1
, fname
, O_RDWR
|O_CREAT
|O_EXCL
, DENY_NONE
, &fnum1
);
2124 cli_openx(cli2
, fname
, O_RDWR
, DENY_NONE
, &fnum2
);
2126 memset(buf
, 0, sizeof(buf
));
2128 status
= cli_writeall(cli1
, fnum1
, 0, (uint8_t *)buf
, 0, sizeof(buf
),
2130 if (!NT_STATUS_IS_OK(status
)) {
2131 printf("Failed to create file: %s\n", nt_errstr(status
));
2136 ret
= NT_STATUS_IS_OK(cli_lock32(cli1
, fnum1
, 0, 4, 0, WRITE_LOCK
)) &&
2137 NT_STATUS_IS_OK(cli_lock32(cli1
, fnum1
, 2, 4, 0, WRITE_LOCK
));
2138 EXPECTED(ret
, False
);
2139 printf("the same process %s set overlapping write locks\n", ret
?"can":"cannot");
2141 ret
= NT_STATUS_IS_OK(cli_lock32(cli1
, fnum1
, 10, 4, 0, READ_LOCK
)) &&
2142 NT_STATUS_IS_OK(cli_lock32(cli1
, fnum1
, 12, 4, 0, READ_LOCK
));
2143 EXPECTED(ret
, True
);
2144 printf("the same process %s set overlapping read locks\n", ret
?"can":"cannot");
2146 ret
= NT_STATUS_IS_OK(cli_lock32(cli1
, fnum1
, 20, 4, 0, WRITE_LOCK
)) &&
2147 NT_STATUS_IS_OK(cli_lock32(cli2
, fnum2
, 22, 4, 0, WRITE_LOCK
));
2148 EXPECTED(ret
, False
);
2149 printf("a different connection %s set overlapping write locks\n", ret
?"can":"cannot");
2151 ret
= NT_STATUS_IS_OK(cli_lock32(cli1
, fnum1
, 30, 4, 0, READ_LOCK
)) &&
2152 NT_STATUS_IS_OK(cli_lock32(cli2
, fnum2
, 32, 4, 0, READ_LOCK
));
2153 EXPECTED(ret
, True
);
2154 printf("a different connection %s set overlapping read locks\n", ret
?"can":"cannot");
2156 ret
= (cli_setpid(cli1
, 1),
2157 NT_STATUS_IS_OK(cli_lock32(cli1
, fnum1
, 40, 4, 0, WRITE_LOCK
))) &&
2158 (cli_setpid(cli1
, 2),
2159 NT_STATUS_IS_OK(cli_lock32(cli1
, fnum1
, 42, 4, 0, WRITE_LOCK
)));
2160 EXPECTED(ret
, False
);
2161 printf("a different pid %s set overlapping write locks\n", ret
?"can":"cannot");
2163 ret
= (cli_setpid(cli1
, 1),
2164 NT_STATUS_IS_OK(cli_lock32(cli1
, fnum1
, 50, 4, 0, READ_LOCK
))) &&
2165 (cli_setpid(cli1
, 2),
2166 NT_STATUS_IS_OK(cli_lock32(cli1
, fnum1
, 52, 4, 0, READ_LOCK
)));
2167 EXPECTED(ret
, True
);
2168 printf("a different pid %s set overlapping read locks\n", ret
?"can":"cannot");
2170 ret
= NT_STATUS_IS_OK(cli_lock32(cli1
, fnum1
, 60, 4, 0, READ_LOCK
)) &&
2171 NT_STATUS_IS_OK(cli_lock32(cli1
, fnum1
, 60, 4, 0, READ_LOCK
));
2172 EXPECTED(ret
, True
);
2173 printf("the same process %s set the same read lock twice\n", ret
?"can":"cannot");
2175 ret
= NT_STATUS_IS_OK(cli_lock32(cli1
, fnum1
, 70, 4, 0, WRITE_LOCK
)) &&
2176 NT_STATUS_IS_OK(cli_lock32(cli1
, fnum1
, 70, 4, 0, WRITE_LOCK
));
2177 EXPECTED(ret
, False
);
2178 printf("the same process %s set the same write lock twice\n", ret
?"can":"cannot");
2180 ret
= NT_STATUS_IS_OK(cli_lock32(cli1
, fnum1
, 80, 4, 0, READ_LOCK
)) &&
2181 NT_STATUS_IS_OK(cli_lock32(cli1
, fnum1
, 80, 4, 0, WRITE_LOCK
));
2182 EXPECTED(ret
, False
);
2183 printf("the same process %s overlay a read lock with a write lock\n", ret
?"can":"cannot");
2185 ret
= NT_STATUS_IS_OK(cli_lock32(cli1
, fnum1
, 90, 4, 0, WRITE_LOCK
)) &&
2186 NT_STATUS_IS_OK(cli_lock32(cli1
, fnum1
, 90, 4, 0, READ_LOCK
));
2187 EXPECTED(ret
, True
);
2188 printf("the same process %s overlay a write lock with a read lock\n", ret
?"can":"cannot");
2190 ret
= (cli_setpid(cli1
, 1),
2191 NT_STATUS_IS_OK(cli_lock32(cli1
, fnum1
, 100, 4, 0, WRITE_LOCK
))) &&
2192 (cli_setpid(cli1
, 2),
2193 NT_STATUS_IS_OK(cli_lock32(cli1
, fnum1
, 100, 4, 0, READ_LOCK
)));
2194 EXPECTED(ret
, False
);
2195 printf("a different pid %s overlay a write lock with a read lock\n", ret
?"can":"cannot");
2197 ret
= NT_STATUS_IS_OK(cli_lock32(cli1
, fnum1
, 110, 4, 0, READ_LOCK
)) &&
2198 NT_STATUS_IS_OK(cli_lock32(cli1
, fnum1
, 112, 4, 0, READ_LOCK
)) &&
2199 NT_STATUS_IS_OK(cli_unlock(cli1
, fnum1
, 110, 6));
2200 EXPECTED(ret
, False
);
2201 printf("the same process %s coalesce read locks\n", ret
?"can":"cannot");
2204 ret
= NT_STATUS_IS_OK(cli_lock32(cli1
, fnum1
, 120, 4, 0, WRITE_LOCK
)) &&
2205 test_cli_read(cli2
, fnum2
, buf
, 120, 4, NULL
, 4);
2206 EXPECTED(ret
, False
);
2207 printf("this server %s strict write locking\n", ret
?"doesn't do":"does");
2209 status
= cli_lock32(cli1
, fnum1
, 130, 4, 0, READ_LOCK
);
2210 ret
= NT_STATUS_IS_OK(status
);
2212 status
= cli_writeall(cli2
, fnum2
, 0, (uint8_t *)buf
, 130, 4,
2214 ret
= NT_STATUS_IS_OK(status
);
2216 EXPECTED(ret
, False
);
2217 printf("this server %s strict read locking\n", ret
?"doesn't do":"does");
2220 ret
= NT_STATUS_IS_OK(cli_lock32(cli1
, fnum1
, 140, 4, 0, READ_LOCK
)) &&
2221 NT_STATUS_IS_OK(cli_lock32(cli1
, fnum1
, 140, 4, 0, READ_LOCK
)) &&
2222 NT_STATUS_IS_OK(cli_unlock(cli1
, fnum1
, 140, 4)) &&
2223 NT_STATUS_IS_OK(cli_unlock(cli1
, fnum1
, 140, 4));
2224 EXPECTED(ret
, True
);
2225 printf("this server %s do recursive read locking\n", ret
?"does":"doesn't");
2228 ret
= NT_STATUS_IS_OK(cli_lock32(cli1
, fnum1
, 150, 4, 0, WRITE_LOCK
)) &&
2229 NT_STATUS_IS_OK(cli_lock32(cli1
, fnum1
, 150, 4, 0, READ_LOCK
)) &&
2230 NT_STATUS_IS_OK(cli_unlock(cli1
, fnum1
, 150, 4)) &&
2231 test_cli_read(cli2
, fnum2
, buf
, 150, 4, NULL
, 4) &&
2232 !(NT_STATUS_IS_OK(cli_writeall(cli2
, fnum2
, 0, (uint8_t *)buf
,
2234 NT_STATUS_IS_OK(cli_unlock(cli1
, fnum1
, 150, 4));
2235 EXPECTED(ret
, True
);
2236 printf("this server %s do recursive lock overlays\n", ret
?"does":"doesn't");
2238 ret
= NT_STATUS_IS_OK(cli_lock32(cli1
, fnum1
, 160, 4, 0, READ_LOCK
)) &&
2239 NT_STATUS_IS_OK(cli_unlock(cli1
, fnum1
, 160, 4)) &&
2240 NT_STATUS_IS_OK(cli_writeall(cli2
, fnum2
, 0, (uint8_t *)buf
,
2242 test_cli_read(cli2
, fnum2
, buf
, 160, 4, NULL
, 4);
2243 EXPECTED(ret
, True
);
2244 printf("the same process %s remove a read lock using write locking\n", ret
?"can":"cannot");
2246 ret
= NT_STATUS_IS_OK(cli_lock32(cli1
, fnum1
, 170, 4, 0, WRITE_LOCK
)) &&
2247 NT_STATUS_IS_OK(cli_unlock(cli1
, fnum1
, 170, 4)) &&
2248 NT_STATUS_IS_OK(cli_writeall(cli2
, fnum2
, 0, (uint8_t *)buf
,
2250 test_cli_read(cli2
, fnum2
, buf
, 170, 4, NULL
, 4);
2251 EXPECTED(ret
, True
);
2252 printf("the same process %s remove a write lock using read locking\n", ret
?"can":"cannot");
2254 ret
= NT_STATUS_IS_OK(cli_lock32(cli1
, fnum1
, 190, 4, 0, WRITE_LOCK
)) &&
2255 NT_STATUS_IS_OK(cli_lock32(cli1
, fnum1
, 190, 4, 0, READ_LOCK
)) &&
2256 NT_STATUS_IS_OK(cli_unlock(cli1
, fnum1
, 190, 4)) &&
2257 !NT_STATUS_IS_OK(cli_writeall(cli2
, fnum2
, 0, (uint8_t *)buf
,
2259 test_cli_read(cli2
, fnum2
, buf
, 190, 4, NULL
, 4);
2260 EXPECTED(ret
, True
);
2261 printf("the same process %s remove the first lock first\n", ret
?"does":"doesn't");
2263 cli_close(cli1
, fnum1
);
2264 cli_close(cli2
, fnum2
);
2265 cli_openx(cli1
, fname
, O_RDWR
, DENY_NONE
, &fnum1
);
2266 cli_openx(cli1
, fname
, O_RDWR
, DENY_NONE
, &f
);
2267 ret
= NT_STATUS_IS_OK(cli_lock32(cli1
, fnum1
, 0, 8, 0, READ_LOCK
)) &&
2268 NT_STATUS_IS_OK(cli_lock32(cli1
, f
, 0, 1, 0, READ_LOCK
)) &&
2269 NT_STATUS_IS_OK(cli_close(cli1
, fnum1
)) &&
2270 NT_STATUS_IS_OK(cli_openx(cli1
, fname
, O_RDWR
, DENY_NONE
, &fnum1
)) &&
2271 NT_STATUS_IS_OK(cli_lock32(cli1
, fnum1
, 7, 1, 0, WRITE_LOCK
));
2273 cli_close(cli1
, fnum1
);
2274 EXPECTED(ret
, True
);
2275 printf("the server %s have the NT byte range lock bug\n", !ret
?"does":"doesn't");
2278 cli_close(cli1
, fnum1
);
2279 cli_close(cli2
, fnum2
);
2280 cli_unlink(cli1
, fname
, FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
);
2281 torture_close_connection(cli1
);
2282 torture_close_connection(cli2
);
2284 printf("finished locktest4\n");
2289 looks at lock upgrade/downgrade.
2291 static bool run_locktest5(int dummy
)
2293 static struct cli_state
*cli1
, *cli2
;
2294 const char *fname
= "\\lockt5.lck";
2295 uint16_t fnum1
, fnum2
, fnum3
;
2298 bool correct
= True
;
2301 if (!torture_open_connection(&cli1
, 0) || !torture_open_connection(&cli2
, 1)) {
2305 smbXcli_conn_set_sockopt(cli1
->conn
, sockops
);
2306 smbXcli_conn_set_sockopt(cli2
->conn
, sockops
);
2308 printf("starting locktest5\n");
2310 cli_unlink(cli1
, fname
, FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
);
2312 cli_openx(cli1
, fname
, O_RDWR
|O_CREAT
|O_EXCL
, DENY_NONE
, &fnum1
);
2313 cli_openx(cli2
, fname
, O_RDWR
, DENY_NONE
, &fnum2
);
2314 cli_openx(cli1
, fname
, O_RDWR
, DENY_NONE
, &fnum3
);
2316 memset(buf
, 0, sizeof(buf
));
2318 status
= cli_writeall(cli1
, fnum1
, 0, (uint8_t *)buf
, 0, sizeof(buf
),
2320 if (!NT_STATUS_IS_OK(status
)) {
2321 printf("Failed to create file: %s\n", nt_errstr(status
));
2326 /* Check for NT bug... */
2327 ret
= NT_STATUS_IS_OK(cli_lock32(cli1
, fnum1
, 0, 8, 0, READ_LOCK
)) &&
2328 NT_STATUS_IS_OK(cli_lock32(cli1
, fnum3
, 0, 1, 0, READ_LOCK
));
2329 cli_close(cli1
, fnum1
);
2330 cli_openx(cli1
, fname
, O_RDWR
, DENY_NONE
, &fnum1
);
2331 status
= cli_lock32(cli1
, fnum1
, 7, 1, 0, WRITE_LOCK
);
2332 ret
= NT_STATUS_IS_OK(status
);
2333 EXPECTED(ret
, True
);
2334 printf("this server %s the NT locking bug\n", ret
? "doesn't have" : "has");
2335 cli_close(cli1
, fnum1
);
2336 cli_openx(cli1
, fname
, O_RDWR
, DENY_NONE
, &fnum1
);
2337 cli_unlock(cli1
, fnum3
, 0, 1);
2339 ret
= NT_STATUS_IS_OK(cli_lock32(cli1
, fnum1
, 0, 4, 0, WRITE_LOCK
)) &&
2340 NT_STATUS_IS_OK(cli_lock32(cli1
, fnum1
, 1, 1, 0, READ_LOCK
));
2341 EXPECTED(ret
, True
);
2342 printf("the same process %s overlay a write with a read lock\n", ret
?"can":"cannot");
2344 status
= cli_lock32(cli2
, fnum2
, 0, 4, 0, READ_LOCK
);
2345 ret
= NT_STATUS_IS_OK(status
);
2346 EXPECTED(ret
, False
);
2348 printf("a different process %s get a read lock on the first process lock stack\n", ret
?"can":"cannot");
2350 /* Unlock the process 2 lock. */
2351 cli_unlock(cli2
, fnum2
, 0, 4);
2353 status
= cli_lock32(cli1
, fnum3
, 0, 4, 0, READ_LOCK
);
2354 ret
= NT_STATUS_IS_OK(status
);
2355 EXPECTED(ret
, False
);
2357 printf("the same process on a different fnum %s get a read lock\n", ret
?"can":"cannot");
2359 /* Unlock the process 1 fnum3 lock. */
2360 cli_unlock(cli1
, fnum3
, 0, 4);
2362 /* Stack 2 more locks here. */
2363 ret
= NT_STATUS_IS_OK(cli_lock32(cli1
, fnum1
, 0, 4, 0, READ_LOCK
)) &&
2364 NT_STATUS_IS_OK(cli_lock32(cli1
, fnum1
, 0, 4, 0, READ_LOCK
));
2366 EXPECTED(ret
, True
);
2367 printf("the same process %s stack read locks\n", ret
?"can":"cannot");
2369 /* Unlock the first process lock, then check this was the WRITE lock that was
2372 ret
= NT_STATUS_IS_OK(cli_unlock(cli1
, fnum1
, 0, 4)) &&
2373 NT_STATUS_IS_OK(cli_lock32(cli2
, fnum2
, 0, 4, 0, READ_LOCK
));
2375 EXPECTED(ret
, True
);
2376 printf("the first unlock removes the %s lock\n", ret
?"WRITE":"READ");
2378 /* Unlock the process 2 lock. */
2379 cli_unlock(cli2
, fnum2
, 0, 4);
2381 /* We should have 3 stacked locks here. Ensure we need to do 3 unlocks. */
2383 ret
= NT_STATUS_IS_OK(cli_unlock(cli1
, fnum1
, 1, 1)) &&
2384 NT_STATUS_IS_OK(cli_unlock(cli1
, fnum1
, 0, 4)) &&
2385 NT_STATUS_IS_OK(cli_unlock(cli1
, fnum1
, 0, 4));
2387 EXPECTED(ret
, True
);
2388 printf("the same process %s unlock the stack of 4 locks\n", ret
?"can":"cannot");
2390 /* Ensure the next unlock fails. */
2391 ret
= NT_STATUS_IS_OK(cli_unlock(cli1
, fnum1
, 0, 4));
2392 EXPECTED(ret
, False
);
2393 printf("the same process %s count the lock stack\n", !ret
?"can":"cannot");
2395 /* Ensure connection 2 can get a write lock. */
2396 status
= cli_lock32(cli2
, fnum2
, 0, 4, 0, WRITE_LOCK
);
2397 ret
= NT_STATUS_IS_OK(status
);
2398 EXPECTED(ret
, True
);
2400 printf("a different process %s get a write lock on the unlocked stack\n", ret
?"can":"cannot");
2404 cli_close(cli1
, fnum1
);
2405 cli_close(cli2
, fnum2
);
2406 cli_unlink(cli1
, fname
, FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
);
2407 if (!torture_close_connection(cli1
)) {
2410 if (!torture_close_connection(cli2
)) {
2414 printf("finished locktest5\n");
2420 tries the unusual lockingX locktype bits
2422 static bool run_locktest6(int dummy
)
2424 static struct cli_state
*cli
;
2425 const char *fname
[1] = { "\\lock6.txt" };
2430 if (!torture_open_connection(&cli
, 0)) {
2434 smbXcli_conn_set_sockopt(cli
->conn
, sockops
);
2436 printf("starting locktest6\n");
2439 printf("Testing %s\n", fname
[i
]);
2441 cli_unlink(cli
, fname
[i
], FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
);
2443 cli_openx(cli
, fname
[i
], O_RDWR
|O_CREAT
|O_EXCL
, DENY_NONE
, &fnum
);
2444 status
= cli_locktype(cli
, fnum
, 0, 8, 0, LOCKING_ANDX_CHANGE_LOCKTYPE
);
2445 cli_close(cli
, fnum
);
2446 printf("CHANGE_LOCKTYPE gave %s\n", nt_errstr(status
));
2448 cli_openx(cli
, fname
[i
], O_RDWR
, DENY_NONE
, &fnum
);
2449 status
= cli_locktype(cli
, fnum
, 0, 8, 0, LOCKING_ANDX_CANCEL_LOCK
);
2450 cli_close(cli
, fnum
);
2451 printf("CANCEL_LOCK gave %s\n", nt_errstr(status
));
2453 cli_unlink(cli
, fname
[i
], FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
);
2456 torture_close_connection(cli
);
2458 printf("finished locktest6\n");
2462 static bool run_locktest7(int dummy
)
2464 struct cli_state
*cli1
;
2465 const char *fname
= "\\lockt7.lck";
2468 bool correct
= False
;
2472 if (!torture_open_connection(&cli1
, 0)) {
2476 smbXcli_conn_set_sockopt(cli1
->conn
, sockops
);
2478 printf("starting locktest7\n");
2480 cli_unlink(cli1
, fname
, FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
);
2482 cli_openx(cli1
, fname
, O_RDWR
|O_CREAT
|O_EXCL
, DENY_NONE
, &fnum1
);
2484 memset(buf
, 0, sizeof(buf
));
2486 status
= cli_writeall(cli1
, fnum1
, 0, (uint8_t *)buf
, 0, sizeof(buf
),
2488 if (!NT_STATUS_IS_OK(status
)) {
2489 printf("Failed to create file: %s\n", nt_errstr(status
));
2493 cli_setpid(cli1
, 1);
2495 status
= cli_lock32(cli1
, fnum1
, 130, 4, 0, READ_LOCK
);
2496 if (!NT_STATUS_IS_OK(status
)) {
2497 printf("Unable to apply read lock on range 130:4, "
2498 "error was %s\n", nt_errstr(status
));
2501 printf("pid1 successfully locked range 130:4 for READ\n");
2504 status
= cli_read(cli1
, fnum1
, buf
, 130, 4, &nread
);
2505 if (!NT_STATUS_IS_OK(status
)) {
2506 printf("pid1 unable to read the range 130:4, error was %s\n",
2509 } else if (nread
!= 4) {
2510 printf("pid1 unable to read the range 130:4, "
2511 "recv %ld req %d\n", (unsigned long)nread
, 4);
2514 printf("pid1 successfully read the range 130:4\n");
2517 status
= cli_writeall(cli1
, fnum1
, 0, (uint8_t *)buf
, 130, 4, NULL
);
2518 if (!NT_STATUS_IS_OK(status
)) {
2519 printf("pid1 unable to write to the range 130:4, error was "
2520 "%s\n", nt_errstr(status
));
2521 if (!NT_STATUS_EQUAL(status
, NT_STATUS_FILE_LOCK_CONFLICT
)) {
2522 printf("Incorrect error (should be NT_STATUS_FILE_LOCK_CONFLICT)\n");
2526 printf("pid1 successfully wrote to the range 130:4 (should be denied)\n");
2530 cli_setpid(cli1
, 2);
2532 status
= cli_read(cli1
, fnum1
, buf
, 130, 4, &nread
);
2533 if (!NT_STATUS_IS_OK(status
)) {
2534 printf("pid2 unable to read the range 130:4, error was %s\n",
2537 } else if (nread
!= 4) {
2538 printf("pid2 unable to read the range 130:4, "
2539 "recv %ld req %d\n", (unsigned long)nread
, 4);
2542 printf("pid2 successfully read the range 130:4\n");
2545 status
= cli_writeall(cli1
, fnum1
, 0, (uint8_t *)buf
, 130, 4, NULL
);
2546 if (!NT_STATUS_IS_OK(status
)) {
2547 printf("pid2 unable to write to the range 130:4, error was "
2548 "%s\n", nt_errstr(status
));
2549 if (!NT_STATUS_EQUAL(status
, NT_STATUS_FILE_LOCK_CONFLICT
)) {
2550 printf("Incorrect error (should be NT_STATUS_FILE_LOCK_CONFLICT)\n");
2554 printf("pid2 successfully wrote to the range 130:4 (should be denied)\n");
2558 cli_setpid(cli1
, 1);
2559 cli_unlock(cli1
, fnum1
, 130, 4);
2561 status
= cli_lock32(cli1
, fnum1
, 130, 4, 0, WRITE_LOCK
);
2562 if (!NT_STATUS_IS_OK(status
)) {
2563 printf("Unable to apply write lock on range 130:4, error was %s\n", nt_errstr(status
));
2566 printf("pid1 successfully locked range 130:4 for WRITE\n");
2569 status
= cli_read(cli1
, fnum1
, buf
, 130, 4, &nread
);
2570 if (!NT_STATUS_IS_OK(status
)) {
2571 printf("pid1 unable to read the range 130:4, error was %s\n",
2574 } else if (nread
!= 4) {
2575 printf("pid1 unable to read the range 130:4, "
2576 "recv %ld req %d\n", (unsigned long)nread
, 4);
2579 printf("pid1 successfully read the range 130:4\n");
2582 status
= cli_writeall(cli1
, fnum1
, 0, (uint8_t *)buf
, 130, 4, NULL
);
2583 if (!NT_STATUS_IS_OK(status
)) {
2584 printf("pid1 unable to write to the range 130:4, error was "
2585 "%s\n", nt_errstr(status
));
2588 printf("pid1 successfully wrote to the range 130:4\n");
2591 cli_setpid(cli1
, 2);
2593 status
= cli_read(cli1
, fnum1
, buf
, 130, 4, &nread
);
2594 if (!NT_STATUS_IS_OK(status
)) {
2595 printf("pid2 unable to read the range 130:4, error was "
2596 "%s\n", nt_errstr(status
));
2597 if (!NT_STATUS_EQUAL(status
, NT_STATUS_FILE_LOCK_CONFLICT
)) {
2598 printf("Incorrect error (should be NT_STATUS_FILE_LOCK_CONFLICT)\n");
2602 printf("pid2 successfully read the range 130:4 (should be denied) recv %ld\n",
2603 (unsigned long)nread
);
2607 status
= cli_writeall(cli1
, fnum1
, 0, (uint8_t *)buf
, 130, 4, NULL
);
2608 if (!NT_STATUS_IS_OK(status
)) {
2609 printf("pid2 unable to write to the range 130:4, error was "
2610 "%s\n", nt_errstr(status
));
2611 if (!NT_STATUS_EQUAL(status
, NT_STATUS_FILE_LOCK_CONFLICT
)) {
2612 printf("Incorrect error (should be NT_STATUS_FILE_LOCK_CONFLICT)\n");
2616 printf("pid2 successfully wrote to the range 130:4 (should be denied)\n");
2620 cli_unlock(cli1
, fnum1
, 130, 0);
2624 cli_close(cli1
, fnum1
);
2625 cli_unlink(cli1
, fname
, FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
);
2626 torture_close_connection(cli1
);
2628 printf("finished locktest7\n");
2633 * This demonstrates a problem with our use of GPFS share modes: A file
2634 * descriptor sitting in the pending close queue holding a GPFS share mode
2635 * blocks opening a file another time. Happens with Word 2007 temp files.
2636 * With "posix locking = yes" and "gpfs:sharemodes = yes" enabled, the third
2637 * open is denied with NT_STATUS_SHARING_VIOLATION.
2640 static bool run_locktest8(int dummy
)
2642 struct cli_state
*cli1
;
2643 const char *fname
= "\\lockt8.lck";
2644 uint16_t fnum1
, fnum2
;
2646 bool correct
= False
;
2649 if (!torture_open_connection(&cli1
, 0)) {
2653 smbXcli_conn_set_sockopt(cli1
->conn
, sockops
);
2655 printf("starting locktest8\n");
2657 cli_unlink(cli1
, fname
, FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
);
2659 status
= cli_openx(cli1
, fname
, O_RDWR
|O_CREAT
|O_EXCL
, DENY_WRITE
,
2661 if (!NT_STATUS_IS_OK(status
)) {
2662 d_fprintf(stderr
, "cli_openx returned %s\n", nt_errstr(status
));
2666 memset(buf
, 0, sizeof(buf
));
2668 status
= cli_openx(cli1
, fname
, O_RDONLY
, DENY_NONE
, &fnum2
);
2669 if (!NT_STATUS_IS_OK(status
)) {
2670 d_fprintf(stderr
, "cli_openx second time returned %s\n",
2675 status
= cli_lock32(cli1
, fnum2
, 1, 1, 0, READ_LOCK
);
2676 if (!NT_STATUS_IS_OK(status
)) {
2677 printf("Unable to apply read lock on range 1:1, error was "
2678 "%s\n", nt_errstr(status
));
2682 status
= cli_close(cli1
, fnum1
);
2683 if (!NT_STATUS_IS_OK(status
)) {
2684 d_fprintf(stderr
, "cli_close(fnum1) %s\n", nt_errstr(status
));
2688 status
= cli_openx(cli1
, fname
, O_RDWR
, DENY_NONE
, &fnum1
);
2689 if (!NT_STATUS_IS_OK(status
)) {
2690 d_fprintf(stderr
, "cli_openx third time returned %s\n",
2698 cli_close(cli1
, fnum1
);
2699 cli_close(cli1
, fnum2
);
2700 cli_unlink(cli1
, fname
, FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
);
2701 torture_close_connection(cli1
);
2703 printf("finished locktest8\n");
2708 * This test is designed to be run in conjunction with
2709 * external NFS or POSIX locks taken in the filesystem.
2710 * It checks that the smbd server will block until the
2711 * lock is released and then acquire it. JRA.
2714 static bool got_alarm
;
2715 static struct cli_state
*alarm_cli
;
2717 static void alarm_handler(int dummy
)
2722 static void alarm_handler_parent(int dummy
)
2724 smbXcli_conn_disconnect(alarm_cli
->conn
, NT_STATUS_LOCAL_DISCONNECT
);
2727 static void do_local_lock(const char *fname
, int read_fd
, int write_fd
)
2732 const char *local_pathname
= NULL
;
2735 local_pathname
= talloc_asprintf(talloc_tos(),
2736 "%s/%s", local_path
, fname
);
2737 if (!local_pathname
) {
2738 printf("child: alloc fail\n");
2742 unlink(local_pathname
);
2743 fd
= open(local_pathname
, O_RDWR
|O_CREAT
, 0666);
2745 printf("child: open of %s failed %s.\n",
2746 local_pathname
, strerror(errno
));
2750 /* Now take a fcntl lock. */
2751 lock
.l_type
= F_WRLCK
;
2752 lock
.l_whence
= SEEK_SET
;
2755 lock
.l_pid
= getpid();
2757 ret
= fcntl(fd
,F_SETLK
,&lock
);
2759 printf("child: failed to get lock 0:4 on file %s. Error %s\n",
2760 local_pathname
, strerror(errno
));
2763 printf("child: got lock 0:4 on file %s.\n",
2768 CatchSignal(SIGALRM
, alarm_handler
);
2770 /* Signal the parent. */
2771 if (write(write_fd
, &c
, 1) != 1) {
2772 printf("child: start signal fail %s.\n",
2779 /* Wait for the parent to be ready. */
2780 if (read(read_fd
, &c
, 1) != 1) {
2781 printf("child: reply signal fail %s.\n",
2789 printf("child: released lock 0:4 on file %s.\n",
2795 static bool _run_locktest9X(const char *fname
, int timeout
)
2797 struct cli_state
*cli1
;
2798 char *fpath
= talloc_asprintf(talloc_tos(), "\\%s", fname
);
2800 bool correct
= False
;
2801 int pipe_in
[2], pipe_out
[2];
2805 struct timeval start
;
2809 printf("starting locktest9X: %s\n", fname
);
2811 if (local_path
== NULL
) {
2812 d_fprintf(stderr
, "locktest9X must be given a local path via -l <localpath>\n");
2816 if (pipe(pipe_in
) == -1 || pipe(pipe_out
) == -1) {
2821 if (child_pid
== -1) {
2825 if (child_pid
== 0) {
2827 do_local_lock(fname
, pipe_out
[0], pipe_in
[1]);
2837 ret
= read(pipe_in
[0], &c
, 1);
2839 d_fprintf(stderr
, "failed to read start signal from child. %s\n",
2844 if (!torture_open_connection(&cli1
, 0)) {
2848 smbXcli_conn_set_sockopt(cli1
->conn
, sockops
);
2850 status
= cli_openx(cli1
, fpath
, O_RDWR
, DENY_NONE
,
2852 if (!NT_STATUS_IS_OK(status
)) {
2853 d_fprintf(stderr
, "cli_openx returned %s\n", nt_errstr(status
));
2857 /* Ensure the child has the lock. */
2858 status
= cli_lock32(cli1
, fnum
, 0, 4, 0, WRITE_LOCK
);
2859 if (NT_STATUS_IS_OK(status
)) {
2860 d_fprintf(stderr
, "Got the lock on range 0:4 - this should not happen !\n");
2863 d_printf("Child has the lock.\n");
2866 /* Tell the child to wait 5 seconds then exit. */
2867 ret
= write(pipe_out
[1], &c
, 1);
2869 d_fprintf(stderr
, "failed to send exit signal to child. %s\n",
2874 /* Wait 20 seconds for the lock. */
2876 CatchSignal(SIGALRM
, alarm_handler_parent
);
2879 start
= timeval_current();
2881 status
= cli_lock32(cli1
, fnum
, 0, 4, timeout
, WRITE_LOCK
);
2882 if (!NT_STATUS_IS_OK(status
)) {
2883 d_fprintf(stderr
, "Unable to apply write lock on range 0:4, error was "
2884 "%s\n", nt_errstr(status
));
2889 seconds
= timeval_elapsed(&start
);
2891 printf("Parent got the lock after %.2f seconds.\n",
2894 status
= cli_close(cli1
, fnum
);
2895 if (!NT_STATUS_IS_OK(status
)) {
2896 d_fprintf(stderr
, "cli_close(fnum1) %s\n", nt_errstr(status
));
2903 cli_close(cli1
, fnum
);
2904 torture_close_connection(cli1
);
2908 printf("finished locktest9X: %s\n", fname
);
2912 static bool run_locktest9a(int dummy
)
2914 return _run_locktest9X("lock9a.dat", -1);
2917 static bool run_locktest9b(int dummy
)
2919 return _run_locktest9X("lock9b.dat", 10000);
2922 struct locktest10_state
{
2927 static void locktest10_lockingx_done(struct tevent_req
*subreq
);
2928 static void locktest10_read_andx_done(struct tevent_req
*subreq
);
2930 static bool run_locktest10(int dummy
)
2932 struct tevent_context
*ev
= NULL
;
2933 struct cli_state
*cli1
= NULL
;
2934 struct cli_state
*cli2
= NULL
;
2935 struct smb1_lock_element lck
= { 0 };
2936 struct tevent_req
*reqs
[2] = { NULL
};
2937 struct tevent_req
*smbreqs
[2] = { NULL
};
2938 const char fname
[] = "\\lockt10.lck";
2939 uint16_t fnum1
, fnum2
;
2943 struct locktest10_state state
= { .ok
= true };
2946 printf("starting locktest10\n");
2948 ev
= samba_tevent_context_init(NULL
);
2950 d_fprintf(stderr
, "samba_tevent_context_init failed\n");
2954 ok
= torture_open_connection(&cli1
, 0);
2958 smbXcli_conn_set_sockopt(cli1
->conn
, sockops
);
2960 ok
= torture_open_connection(&cli2
, 1);
2964 smbXcli_conn_set_sockopt(cli2
->conn
, sockops
);
2966 status
= cli_openx(cli1
, fname
, O_CREAT
|O_RDWR
, DENY_NONE
, &fnum1
);
2967 if (!NT_STATUS_IS_OK(status
)) {
2969 "cli_openx failed: %s\n",
2974 status
= cli_writeall(cli1
, fnum1
, 0, &data
, 0, sizeof(data
), NULL
);
2975 if (!NT_STATUS_IS_OK(status
)) {
2977 "cli_writeall failed: %s\n",
2982 status
= cli_openx(cli2
, fname
, O_CREAT
|O_RDWR
, DENY_NONE
, &fnum2
);
2983 if (!NT_STATUS_IS_OK(status
)) {
2985 "cli_openx failed: %s\n",
2990 status
= cli_locktype(
2991 cli2
, fnum2
, 0, 1, 0, LOCKING_ANDX_EXCLUSIVE_LOCK
);
2992 if (!NT_STATUS_IS_OK(status
)) {
2994 "cli_locktype failed: %s\n",
2999 lck
= (struct smb1_lock_element
) {
3000 .pid
= cli_getpid(cli1
), .offset
= 0, .length
= 1,
3003 reqs
[0] = cli_lockingx_create(
3005 ev
, /* tevent_context */
3008 LOCKING_ANDX_EXCLUSIVE_LOCK
, /* typeoflock */
3009 0, /* newoplocklevel */
3011 0, /* num_unlocks */
3015 &smbreqs
[0]); /* psmbreq */
3016 if (reqs
[0] == NULL
) {
3017 d_fprintf(stderr
, "cli_lockingx_create failed\n");
3020 tevent_req_set_callback(reqs
[0], locktest10_lockingx_done
, &state
);
3022 reqs
[1] = cli_read_andx_create(
3029 &smbreqs
[1]); /* psmbreq */
3030 if (reqs
[1] == NULL
) {
3031 d_fprintf(stderr
, "cli_read_andx_create failed\n");
3034 tevent_req_set_callback(reqs
[1], locktest10_read_andx_done
, &state
);
3036 status
= smb1cli_req_chain_submit(smbreqs
, ARRAY_SIZE(smbreqs
));
3037 if (!NT_STATUS_IS_OK(status
)) {
3039 "smb1cli_req_chain_submit failed: %s\n",
3044 while (!state
.done
) {
3045 tevent_loop_once(ev
);
3048 torture_close_connection(cli1
);
3057 static void locktest10_lockingx_done(struct tevent_req
*subreq
)
3059 struct locktest10_state
*state
= tevent_req_callback_data_void(subreq
);
3062 status
= cli_lockingx_recv(subreq
);
3063 TALLOC_FREE(subreq
);
3065 if (!NT_STATUS_EQUAL(status
, NT_STATUS_FILE_LOCK_CONFLICT
)) {
3066 d_printf("cli_lockingx returned %s\n", nt_errstr(status
));
3071 static void locktest10_read_andx_done(struct tevent_req
*subreq
)
3073 struct locktest10_state
*state
= tevent_req_callback_data_void(subreq
);
3074 ssize_t received
= -1;
3075 uint8_t *rcvbuf
= NULL
;
3078 status
= cli_read_andx_recv(subreq
, &received
, &rcvbuf
);
3080 if (!NT_STATUS_EQUAL(status
, NT_STATUS_REQUEST_ABORTED
)) {
3081 d_printf("cli_read_andx returned %s\n", nt_errstr(status
));
3086 TALLOC_FREE(subreq
);
3089 static bool run_locktest11(int dummy
)
3091 struct cli_state
*cli1
;
3092 const char *fname
= "\\lockt11.lck";
3097 if (!torture_open_connection(&cli1
, 0)) {
3101 smbXcli_conn_set_sockopt(cli1
->conn
, sockops
);
3103 cli_unlink(cli1
, fname
, FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
);
3105 status
= cli_openx(cli1
, fname
, O_CREAT
|O_RDWR
, DENY_NONE
, &fnum
);
3106 if (!NT_STATUS_IS_OK(status
)) {
3108 "cli_openx returned %s\n",
3114 * Test that LOCKING_ANDX_CANCEL_LOCK without any locks
3115 * returns NT_STATUS_OK
3118 status
= cli_lockingx(
3121 LOCKING_ANDX_CANCEL_LOCK
, /* typeoflock */
3122 0, /* newoplocklevel */
3124 0, /* num_unlocks */
3129 if (!NT_STATUS_IS_OK(status
)) {
3130 d_printf("cli_lockingX returned %s\n", nt_errstr(status
));
3136 cli_close(cli1
, fnum
);
3137 cli_unlink(cli1
, fname
, FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
);
3142 struct deferred_close_state
{
3143 struct tevent_context
*ev
;
3144 struct cli_state
*cli
;
3148 static void deferred_close_waited(struct tevent_req
*subreq
);
3149 static void deferred_close_done(struct tevent_req
*subreq
);
3151 static struct tevent_req
*deferred_close_send(
3152 TALLOC_CTX
*mem_ctx
,
3153 struct tevent_context
*ev
,
3155 struct cli_state
*cli
,
3158 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
3159 struct deferred_close_state
*state
= NULL
;
3160 struct timeval wakeup_time
= timeval_current_ofs(wait_secs
, 0);
3162 req
= tevent_req_create(
3163 mem_ctx
, &state
, struct deferred_close_state
);
3171 subreq
= tevent_wakeup_send(state
, state
->ev
, wakeup_time
);
3172 if (tevent_req_nomem(subreq
, req
)) {
3173 return tevent_req_post(req
, ev
);
3175 tevent_req_set_callback(subreq
, deferred_close_waited
, req
);
3179 static void deferred_close_waited(struct tevent_req
*subreq
)
3181 struct tevent_req
*req
= tevent_req_callback_data(
3182 subreq
, struct tevent_req
);
3183 struct deferred_close_state
*state
= tevent_req_data(
3184 req
, struct deferred_close_state
);
3187 ok
= tevent_wakeup_recv(subreq
);
3188 TALLOC_FREE(subreq
);
3190 tevent_req_oom(req
);
3194 subreq
= cli_close_send(state
, state
->ev
, state
->cli
, state
->fnum
, 0);
3195 if (tevent_req_nomem(subreq
, req
)) {
3198 tevent_req_set_callback(subreq
, deferred_close_done
, req
);
3201 static void deferred_close_done(struct tevent_req
*subreq
)
3203 NTSTATUS status
= cli_close_recv(subreq
);
3204 tevent_req_simple_finish_ntstatus(subreq
, status
);
3207 static NTSTATUS
deferred_close_recv(struct tevent_req
*req
)
3209 return tevent_req_simple_recv_ntstatus(req
);
3212 struct lockread_state
{
3213 struct smb1_lock_element lck
;
3214 struct tevent_req
*reqs
[2];
3215 struct tevent_req
*smbreqs
[2];
3216 NTSTATUS lock_status
;
3217 NTSTATUS read_status
;
3221 static void lockread_lockingx_done(struct tevent_req
*subreq
);
3222 static void lockread_read_andx_done(struct tevent_req
*subreq
);
3224 static struct tevent_req
*lockread_send(
3225 TALLOC_CTX
*mem_ctx
,
3226 struct tevent_context
*ev
,
3227 struct cli_state
*cli
,
3230 struct tevent_req
*req
= NULL
;
3231 struct lockread_state
*state
= NULL
;
3234 req
= tevent_req_create(mem_ctx
, &state
, struct lockread_state
);
3239 state
->lck
= (struct smb1_lock_element
) {
3240 .pid
= cli_getpid(cli
), .offset
= 0, .length
= 1,
3243 state
->reqs
[0] = cli_lockingx_create(
3245 ev
, /* tevent_context */
3248 LOCKING_ANDX_EXCLUSIVE_LOCK
, /* typeoflock */
3249 0, /* newoplocklevel */
3250 10000, /* timeout */
3251 0, /* num_unlocks */
3254 &state
->lck
, /* locks */
3255 &state
->smbreqs
[0]); /* psmbreq */
3256 if (tevent_req_nomem(state
->reqs
[0], req
)) {
3257 return tevent_req_post(req
, ev
);
3259 tevent_req_set_callback(
3260 state
->reqs
[0], lockread_lockingx_done
, req
);
3262 state
->reqs
[1] = cli_read_andx_create(
3269 &state
->smbreqs
[1]); /* psmbreq */
3270 if (tevent_req_nomem(state
->reqs
[1], req
)) {
3271 return tevent_req_post(req
, ev
);
3273 tevent_req_set_callback(
3274 state
->reqs
[1], lockread_read_andx_done
, req
);
3276 status
= smb1cli_req_chain_submit(state
->smbreqs
, 2);
3277 if (tevent_req_nterror(req
, status
)) {
3278 return tevent_req_post(req
, ev
);
3283 static void lockread_lockingx_done(struct tevent_req
*subreq
)
3285 struct tevent_req
*req
= tevent_req_callback_data(
3286 subreq
, struct tevent_req
);
3287 struct lockread_state
*state
= tevent_req_data(
3288 req
, struct lockread_state
);
3289 state
->lock_status
= cli_lockingx_recv(subreq
);
3290 TALLOC_FREE(subreq
);
3292 "lockingx returned %s\n",
3293 nt_errstr(state
->lock_status
));
3296 static void lockread_read_andx_done(struct tevent_req
*subreq
)
3298 struct tevent_req
*req
= tevent_req_callback_data(
3299 subreq
, struct tevent_req
);
3300 struct lockread_state
*state
= tevent_req_data(
3301 req
, struct lockread_state
);
3302 ssize_t received
= -1;
3303 uint8_t *rcvbuf
= NULL
;
3305 state
->read_status
= cli_read_andx_recv(subreq
, &received
, &rcvbuf
);
3308 "read returned %s\n",
3309 nt_errstr(state
->read_status
));
3311 if (!NT_STATUS_IS_OK(state
->read_status
)) {
3312 TALLOC_FREE(subreq
);
3313 tevent_req_done(req
);
3318 state
->readbuf
= talloc_memdup(state
, rcvbuf
, received
);
3319 TALLOC_FREE(subreq
);
3320 if (tevent_req_nomem(state
->readbuf
, req
)) {
3324 TALLOC_FREE(subreq
);
3325 tevent_req_done(req
);
3328 static NTSTATUS
lockread_recv(
3329 struct tevent_req
*req
,
3330 NTSTATUS
*lock_status
,
3331 NTSTATUS
*read_status
,
3332 TALLOC_CTX
*mem_ctx
,
3335 struct lockread_state
*state
= tevent_req_data(
3336 req
, struct lockread_state
);
3339 if (tevent_req_is_nterror(req
, &status
)) {
3343 *lock_status
= state
->lock_status
;
3344 *read_status
= state
->read_status
;
3345 if (state
->readbuf
!= NULL
) {
3346 *read_buf
= talloc_move(mem_ctx
, &state
->readbuf
);
3351 return NT_STATUS_OK
;
3354 struct lock12_state
{
3358 static void lock12_closed(struct tevent_req
*subreq
);
3359 static void lock12_read(struct tevent_req
*subreq
);
3361 static struct tevent_req
*lock12_send(
3362 TALLOC_CTX
*mem_ctx
,
3363 struct tevent_context
*ev
,
3364 struct cli_state
*cli
,
3368 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
3369 struct lock12_state
*state
= NULL
;
3371 req
= tevent_req_create(mem_ctx
, &state
, struct lock12_state
);
3376 subreq
= deferred_close_send(state
, ev
, 1, cli
, fnum1
);
3377 if (tevent_req_nomem(subreq
, req
)) {
3378 return tevent_req_post(req
, ev
);
3380 tevent_req_set_callback(subreq
, lock12_closed
, req
);
3382 subreq
= lockread_send(state
, ev
, cli
, fnum2
);
3383 if (tevent_req_nomem(subreq
, req
)) {
3384 return tevent_req_post(req
, ev
);
3386 tevent_req_set_callback(subreq
, lock12_read
, req
);
3391 static void lock12_closed(struct tevent_req
*subreq
)
3393 struct tevent_req
*req
= tevent_req_callback_data(
3394 subreq
, struct tevent_req
);
3397 status
= deferred_close_recv(subreq
);
3398 TALLOC_FREE(subreq
);
3399 DBG_DEBUG("close returned %s\n", nt_errstr(status
));
3400 if (tevent_req_nterror(req
, status
)) {
3405 static void lock12_read(struct tevent_req
*subreq
)
3407 struct tevent_req
*req
= tevent_req_callback_data(
3408 subreq
, struct tevent_req
);
3409 struct lock12_state
*state
= tevent_req_data(
3410 req
, struct lock12_state
);
3411 NTSTATUS status
, lock_status
, read_status
;
3412 uint8_t *buf
= NULL
;
3414 status
= lockread_recv(
3415 subreq
, &lock_status
, &read_status
, state
, &buf
);
3416 TALLOC_FREE(subreq
);
3417 if (tevent_req_nterror(req
, status
) ||
3418 tevent_req_nterror(req
, lock_status
) ||
3419 tevent_req_nterror(req
, read_status
)) {
3422 tevent_req_done(req
);
3425 static NTSTATUS
lock12_recv(struct tevent_req
*req
)
3430 if (tevent_req_is_nterror(req
, &status
)) {
3433 return NT_STATUS_OK
;
3436 static bool run_locktest12(int dummy
)
3438 struct tevent_context
*ev
= NULL
;
3439 struct tevent_req
*req
= NULL
;
3440 struct cli_state
*cli
= NULL
;
3441 const char fname
[] = "\\lockt12.lck";
3442 uint16_t fnum1
, fnum2
;
3448 printf("starting locktest12\n");
3450 ev
= samba_tevent_context_init(NULL
);
3452 d_fprintf(stderr
, "samba_tevent_context_init failed\n");
3456 ok
= torture_open_connection(&cli
, 0);
3460 smbXcli_conn_set_sockopt(cli
->conn
, sockops
);
3462 status
= cli_openx(cli
, fname
, O_CREAT
|O_RDWR
, DENY_NONE
, &fnum1
);
3463 if (!NT_STATUS_IS_OK(status
)) {
3465 "cli_openx failed: %s\n",
3470 status
= cli_openx(cli
, fname
, O_CREAT
|O_RDWR
, DENY_NONE
, &fnum2
);
3471 if (!NT_STATUS_IS_OK(status
)) {
3473 "cli_openx failed: %s\n",
3478 status
= cli_writeall(cli
, fnum1
, 0, &data
, 0, sizeof(data
), NULL
);
3479 if (!NT_STATUS_IS_OK(status
)) {
3481 "cli_writeall failed: %s\n",
3486 status
= cli_locktype(
3487 cli
, fnum1
, 0, 1, 0, LOCKING_ANDX_EXCLUSIVE_LOCK
);
3488 if (!NT_STATUS_IS_OK(status
)) {
3490 "cli_locktype failed: %s\n",
3495 req
= lock12_send(ev
, ev
, cli
, fnum1
, fnum2
);
3497 d_fprintf(stderr
, "lock12_send failed\n");
3501 ok
= tevent_req_poll_ntstatus(req
, ev
, &status
);
3503 d_fprintf(stderr
, "tevent_req_poll_ntstatus failed\n");
3507 if (!NT_STATUS_IS_OK(status
)) {
3509 "tevent_req_poll_ntstatus returned %s\n",
3514 status
= lock12_recv(req
);
3515 if (!NT_STATUS_IS_OK(status
)) {
3516 d_fprintf(stderr
, "lock12 returned %s\n", nt_errstr(status
));
3523 torture_close_connection(cli
);
3528 struct lock_ntcancel_state
{
3529 struct timeval start
;
3530 struct smb1_lock_element lck
;
3531 struct tevent_req
*subreq
;
3534 static void lock_ntcancel_waited(struct tevent_req
*subreq
);
3535 static void lock_ntcancel_done(struct tevent_req
*subreq
);
3537 static struct tevent_req
*lock_ntcancel_send(
3538 TALLOC_CTX
*mem_ctx
,
3539 struct tevent_context
*ev
,
3540 struct cli_state
*cli
,
3543 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
3544 struct lock_ntcancel_state
*state
= NULL
;
3546 req
= tevent_req_create(mem_ctx
, &state
, struct lock_ntcancel_state
);
3550 state
->lck
= (struct smb1_lock_element
) {
3551 .pid
= cli_getpid(cli
), .offset
= 0, .length
= 1,
3553 state
->start
= timeval_current();
3555 state
->subreq
= cli_lockingx_send(
3556 state
, /* mem_ctx */
3557 ev
, /* tevent_context */
3560 LOCKING_ANDX_EXCLUSIVE_LOCK
, /* typeoflock */
3561 0, /* newoplocklevel */
3562 10000, /* timeout */
3563 0, /* num_unlocks */
3566 &state
->lck
); /* locks */
3567 if (tevent_req_nomem(state
->subreq
, req
)) {
3568 return tevent_req_post(req
, ev
);
3570 tevent_req_set_callback(state
->subreq
, lock_ntcancel_done
, req
);
3572 subreq
= tevent_wakeup_send(state
, ev
, timeval_current_ofs(1, 0));
3573 if (tevent_req_nomem(subreq
, req
)) {
3574 return tevent_req_post(req
, ev
);
3576 tevent_req_set_callback(subreq
, lock_ntcancel_waited
, req
);
3580 static void lock_ntcancel_waited(struct tevent_req
*subreq
)
3582 struct tevent_req
*req
= tevent_req_callback_data(
3583 subreq
, struct tevent_req
);
3584 struct lock_ntcancel_state
*state
= tevent_req_data(
3585 req
, struct lock_ntcancel_state
);
3588 ok
= tevent_wakeup_recv(subreq
);
3589 TALLOC_FREE(subreq
);
3591 tevent_req_oom(req
);
3595 ok
= tevent_req_cancel(state
->subreq
);
3597 d_fprintf(stderr
, "Could not cancel subreq\n");
3598 tevent_req_oom(req
);
3603 static void lock_ntcancel_done(struct tevent_req
*subreq
)
3605 struct tevent_req
*req
= tevent_req_callback_data(
3606 subreq
, struct tevent_req
);
3607 struct lock_ntcancel_state
*state
= tevent_req_data(
3608 req
, struct lock_ntcancel_state
);
3612 status
= cli_lockingx_recv(subreq
);
3613 TALLOC_FREE(subreq
);
3615 if (!NT_STATUS_EQUAL(status
, NT_STATUS_FILE_LOCK_CONFLICT
)) {
3616 d_printf("cli_lockingx returned %s\n", nt_errstr(status
));
3617 tevent_req_nterror(req
, NT_STATUS_UNSUCCESSFUL
);
3621 elapsed
= timeval_elapsed(&state
->start
);
3624 d_printf("cli_lockingx was too slow, cancel did not work\n");
3625 tevent_req_nterror(req
, NT_STATUS_UNSUCCESSFUL
);
3629 tevent_req_done(req
);
3632 static NTSTATUS
lock_ntcancel_recv(struct tevent_req
*req
)
3634 return tevent_req_simple_recv_ntstatus(req
);
3637 static bool run_locktest13(int dummy
)
3639 struct tevent_context
*ev
= NULL
;
3640 struct tevent_req
*req
= NULL
;
3641 struct cli_state
*cli
= NULL
;
3642 const char fname
[] = "\\lockt13.lck";
3643 uint16_t fnum1
, fnum2
;
3649 printf("starting locktest13\n");
3651 ev
= samba_tevent_context_init(NULL
);
3653 d_fprintf(stderr
, "samba_tevent_context_init failed\n");
3657 ok
= torture_open_connection(&cli
, 0);
3661 smbXcli_conn_set_sockopt(cli
->conn
, sockops
);
3663 status
= cli_openx(cli
, fname
, O_CREAT
|O_RDWR
, DENY_NONE
, &fnum1
);
3664 if (!NT_STATUS_IS_OK(status
)) {
3666 "cli_openx failed: %s\n",
3671 status
= cli_openx(cli
, fname
, O_CREAT
|O_RDWR
, DENY_NONE
, &fnum2
);
3672 if (!NT_STATUS_IS_OK(status
)) {
3674 "cli_openx failed: %s\n",
3679 status
= cli_writeall(cli
, fnum1
, 0, &data
, 0, sizeof(data
), NULL
);
3680 if (!NT_STATUS_IS_OK(status
)) {
3682 "cli_writeall failed: %s\n",
3687 status
= cli_locktype(
3688 cli
, fnum1
, 0, 1, 0, LOCKING_ANDX_EXCLUSIVE_LOCK
);
3689 if (!NT_STATUS_IS_OK(status
)) {
3691 "cli_locktype failed: %s\n",
3696 req
= lock_ntcancel_send(ev
, ev
, cli
, fnum2
);
3698 d_fprintf(stderr
, "lock_ntcancel_send failed\n");
3702 ok
= tevent_req_poll_ntstatus(req
, ev
, &status
);
3704 d_fprintf(stderr
, "tevent_req_poll_ntstatus failed\n");
3708 if (!NT_STATUS_IS_OK(status
)) {
3710 "tevent_req_poll_ntstatus returned %s\n",
3715 status
= lock_ntcancel_recv(req
);
3716 if (!NT_STATUS_IS_OK(status
)) {
3718 "lock_ntcancel returned %s\n",
3726 torture_close_connection(cli
);
3732 test whether fnums and tids open on one VC are available on another (a major
3735 static bool run_fdpasstest(int dummy
)
3737 struct cli_state
*cli1
, *cli2
;
3738 const char *fname
= "\\fdpass.tst";
3743 if (!torture_open_connection(&cli1
, 0) || !torture_open_connection(&cli2
, 1)) {
3746 smbXcli_conn_set_sockopt(cli1
->conn
, sockops
);
3747 smbXcli_conn_set_sockopt(cli2
->conn
, sockops
);
3749 printf("starting fdpasstest\n");
3751 cli_unlink(cli1
, fname
, FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
);
3753 status
= cli_openx(cli1
, fname
, O_RDWR
|O_CREAT
|O_EXCL
, DENY_NONE
,
3755 if (!NT_STATUS_IS_OK(status
)) {
3756 printf("open of %s failed (%s)\n", fname
, nt_errstr(status
));
3760 status
= cli_writeall(cli1
, fnum1
, 0, (const uint8_t *)"hello world\n", 0,
3762 if (!NT_STATUS_IS_OK(status
)) {
3763 printf("write failed (%s)\n", nt_errstr(status
));
3767 cli_state_set_uid(cli2
, cli_state_get_uid(cli1
));
3768 cli_state_set_tid(cli2
, cli_state_get_tid(cli1
));
3769 cli_setpid(cli2
, cli_getpid(cli1
));
3771 if (test_cli_read(cli2
, fnum1
, buf
, 0, 13, NULL
, 13)) {
3772 printf("read succeeded! nasty security hole [%s]\n", buf
);
3776 cli_close(cli1
, fnum1
);
3777 cli_unlink(cli1
, fname
, FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
);
3779 torture_close_connection(cli1
);
3780 torture_close_connection(cli2
);
3782 printf("finished fdpasstest\n");
3786 static bool run_fdsesstest(int dummy
)
3788 struct cli_state
*cli
;
3790 uint16_t saved_vuid
;
3792 uint32_t saved_cnum
;
3793 const char *fname
= "\\fdsess.tst";
3794 const char *fname1
= "\\fdsess1.tst";
3801 if (!torture_open_connection(&cli
, 0))
3803 smbXcli_conn_set_sockopt(cli
->conn
, sockops
);
3805 if (!torture_cli_session_setup2(cli
, &new_vuid
))
3808 saved_cnum
= cli_state_get_tid(cli
);
3809 if (!NT_STATUS_IS_OK(cli_tree_connect(cli
, share
, "?????", NULL
)))
3811 new_cnum
= cli_state_get_tid(cli
);
3812 cli_state_set_tid(cli
, saved_cnum
);
3814 printf("starting fdsesstest\n");
3816 cli_unlink(cli
, fname
, FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
);
3817 cli_unlink(cli
, fname1
, FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
);
3819 status
= cli_openx(cli
, fname
, O_RDWR
|O_CREAT
|O_EXCL
, DENY_NONE
, &fnum1
);
3820 if (!NT_STATUS_IS_OK(status
)) {
3821 printf("open of %s failed (%s)\n", fname
, nt_errstr(status
));
3825 status
= cli_writeall(cli
, fnum1
, 0, (const uint8_t *)"hello world\n", 0, 13,
3827 if (!NT_STATUS_IS_OK(status
)) {
3828 printf("write failed (%s)\n", nt_errstr(status
));
3832 saved_vuid
= cli_state_get_uid(cli
);
3833 cli_state_set_uid(cli
, new_vuid
);
3835 if (test_cli_read(cli
, fnum1
, buf
, 0, 13, NULL
, 13)) {
3836 printf("read succeeded with different vuid! "
3837 "nasty security hole [%s]\n", buf
);
3840 /* Try to open a file with different vuid, samba cnum. */
3841 if (NT_STATUS_IS_OK(cli_openx(cli
, fname1
, O_RDWR
|O_CREAT
|O_EXCL
, DENY_NONE
, &fnum2
))) {
3842 printf("create with different vuid, same cnum succeeded.\n");
3843 cli_close(cli
, fnum2
);
3844 cli_unlink(cli
, fname1
, FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
);
3846 printf("create with different vuid, same cnum failed.\n");
3847 printf("This will cause problems with service clients.\n");
3851 cli_state_set_uid(cli
, saved_vuid
);
3853 /* Try with same vuid, different cnum. */
3854 cli_state_set_tid(cli
, new_cnum
);
3856 if (test_cli_read(cli
, fnum1
, buf
, 0, 13, NULL
, 13)) {
3857 printf("read succeeded with different cnum![%s]\n", buf
);
3861 cli_state_set_tid(cli
, saved_cnum
);
3862 cli_close(cli
, fnum1
);
3863 cli_unlink(cli
, fname
, FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
);
3865 torture_close_connection(cli
);
3867 printf("finished fdsesstest\n");
3872 This test checks that
3874 1) the server does not allow an unlink on a file that is open
3876 static bool run_unlinktest(int dummy
)
3878 struct cli_state
*cli
;
3879 const char *fname
= "\\unlink.tst";
3881 bool correct
= True
;
3884 if (!torture_open_connection(&cli
, 0)) {
3888 smbXcli_conn_set_sockopt(cli
->conn
, sockops
);
3890 printf("starting unlink test\n");
3892 cli_unlink(cli
, fname
, FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
);
3896 status
= cli_openx(cli
, fname
, O_RDWR
|O_CREAT
|O_EXCL
, DENY_NONE
, &fnum
);
3897 if (!NT_STATUS_IS_OK(status
)) {
3898 printf("open of %s failed (%s)\n", fname
, nt_errstr(status
));
3902 status
= cli_unlink(cli
, fname
,
3903 FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
);
3904 if (NT_STATUS_IS_OK(status
)) {
3905 printf("error: server allowed unlink on an open file\n");
3908 correct
= check_error(__LINE__
, status
, ERRDOS
, ERRbadshare
,
3909 NT_STATUS_SHARING_VIOLATION
);
3912 cli_close(cli
, fnum
);
3913 cli_unlink(cli
, fname
, FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
);
3915 if (!torture_close_connection(cli
)) {
3919 printf("unlink test finished\n");
3926 test how many open files this server supports on the one socket
3928 static bool run_maxfidtest(int dummy
)
3930 struct cli_state
*cli
;
3932 uint16_t fnums
[0x11000];
3935 bool correct
= True
;
3941 printf("failed to connect\n");
3945 smbXcli_conn_set_sockopt(cli
->conn
, sockops
);
3947 for (i
=0; i
<0x11000; i
++) {
3948 slprintf(fname
,sizeof(fname
)-1,"\\maxfid.%d.%d", i
,(int)getpid());
3949 status
= cli_openx(cli
, fname
, O_RDWR
|O_CREAT
|O_TRUNC
, DENY_NONE
,
3951 if (!NT_STATUS_IS_OK(status
)) {
3952 printf("open of %s failed (%s)\n",
3953 fname
, nt_errstr(status
));
3954 printf("maximum fnum is %d\n", i
);
3962 printf("cleaning up\n");
3964 slprintf(fname
,sizeof(fname
)-1,"\\maxfid.%d.%d", i
,(int)getpid());
3965 cli_close(cli
, fnums
[i
]);
3967 status
= cli_unlink(cli
, fname
, FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
);
3968 if (!NT_STATUS_IS_OK(status
)) {
3969 printf("unlink of %s failed (%s)\n",
3970 fname
, nt_errstr(status
));
3977 printf("maxfid test finished\n");
3978 if (!torture_close_connection(cli
)) {
3984 /* send smb negprot commands, not reading the response */
3985 static bool run_negprot_nowait(int dummy
)
3987 struct tevent_context
*ev
;
3989 struct cli_state
*cli
;
3990 bool correct
= True
;
3992 printf("starting negprot nowait test\n");
3994 ev
= samba_tevent_context_init(talloc_tos());
3999 if (!(cli
= open_nbt_connection())) {
4004 for (i
=0;i
<50000;i
++) {
4005 struct tevent_req
*req
;
4007 req
= smbXcli_negprot_send(
4020 if (!tevent_req_poll(req
, ev
)) {
4021 d_fprintf(stderr
, "tevent_req_poll failed: %s\n",
4029 if (torture_close_connection(cli
)) {
4033 printf("finished negprot nowait test\n");
4038 /* send smb negprot commands, not reading the response */
4039 static bool run_bad_nbt_session(int dummy
)
4041 struct nmb_name called
, calling
;
4042 struct sockaddr_storage ss
;
4047 printf("starting bad nbt session test\n");
4049 make_nmb_name(&calling
, myname
, 0x0);
4050 make_nmb_name(&called
, host
, 0x20);
4052 if (!resolve_name(host
, &ss
, 0x20, true)) {
4053 d_fprintf(stderr
, "Could not resolve name %s\n", host
);
4057 status
= open_socket_out(&ss
, NBT_SMB_PORT
, 10000, &fd
);
4058 if (!NT_STATUS_IS_OK(status
)) {
4059 d_fprintf(stderr
, "open_socket_out failed: %s\n",
4064 ret
= cli_bad_session_request(fd
, &calling
, &called
);
4067 d_fprintf(stderr
, "open_socket_out failed: %s\n",
4072 printf("finished bad nbt session test\n");
4076 /* send random IPC commands */
4077 static bool run_randomipc(int dummy
)
4080 struct cli_state
*cli
;
4081 bool correct
= True
;
4084 printf("starting random ipc test\n");
4086 if (!torture_open_connection(&cli
, 0)) {
4090 for (i
=0;i
<count
;i
++) {
4091 int api
= sys_random() % 500;
4092 int param_len
= (sys_random() % 64);
4093 uint8_t param
[1024];
4094 uint8_t *rparam
= NULL
;
4095 uint8_t *rdata
= NULL
;
4096 uint32_t rdrcnt
, rprcnt
;
4098 generate_random_buffer(param
, param_len
);
4102 cli_trans(talloc_tos(), /* mem_ctx */
4105 "\\PIPE\\LANMAN", /* name */
4113 param_len
, /* num_param */
4117 CLI_BUFFER_SIZE
, /* max_data, for W2K */
4118 NULL
, /* recv_flags2 */
4121 NULL
, /* num_rsetup */
4122 &rparam
, /* rparam */
4124 &rprcnt
, /* num_rparam */
4127 &rdrcnt
); /* num_rdata */
4129 printf("%d/%d\r", i
,count
);
4131 TALLOC_FREE(rparam
);
4134 printf("%d/%d\n", i
, count
);
4136 if (!torture_close_connection(cli
)) {
4140 printf("finished random ipc test\n");
4147 static void browse_callback(const char *sname
, uint32_t stype
,
4148 const char *comment
, void *state
)
4150 printf("\t%20.20s %08x %s\n", sname
, stype
, comment
);
4156 This test checks the browse list code
4159 static bool run_browsetest(int dummy
)
4161 static struct cli_state
*cli
;
4162 bool correct
= True
;
4164 printf("starting browse test\n");
4166 if (!torture_open_connection(&cli
, 0)) {
4170 printf("domain list:\n");
4171 cli_NetServerEnum(cli
, cli
->server_domain
,
4172 SV_TYPE_DOMAIN_ENUM
,
4173 browse_callback
, NULL
);
4175 printf("machine list:\n");
4176 cli_NetServerEnum(cli
, cli
->server_domain
,
4178 browse_callback
, NULL
);
4180 if (!torture_close_connection(cli
)) {
4184 printf("browse test finished\n");
4190 static bool check_attributes(struct cli_state
*cli
,
4192 uint32_t expected_attrs
)
4195 NTSTATUS status
= cli_getatr(cli
,
4200 if (!NT_STATUS_IS_OK(status
)) {
4201 printf("cli_getatr failed with %s\n",
4205 if (attrs
!= expected_attrs
) {
4206 printf("Attributes incorrect 0x%x, should be 0x%x\n",
4207 (unsigned int)attrs
,
4208 (unsigned int)expected_attrs
);
4215 This checks how the getatr calls works
4217 static bool run_attrtest(int dummy
)
4219 struct cli_state
*cli
;
4222 const char *fname
= "\\attrib123456789.tst";
4223 bool correct
= True
;
4226 printf("starting attrib test\n");
4228 if (!torture_open_connection(&cli
, 0)) {
4232 /* Ensure we can't unlink with out-of-range (unknown) attribute. */
4233 status
= cli_unlink(cli
, fname
, 0x20000);
4234 if (!NT_STATUS_EQUAL(status
, NT_STATUS_INVALID_PARAMETER
)) {
4239 cli_unlink(cli
, fname
, FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
);
4240 cli_openx(cli
, fname
,
4241 O_RDWR
| O_CREAT
| O_TRUNC
, DENY_NONE
, &fnum
);
4242 cli_close(cli
, fnum
);
4244 status
= cli_getatr(cli
, fname
, NULL
, NULL
, &t
);
4245 if (!NT_STATUS_IS_OK(status
)) {
4246 printf("getatr failed (%s)\n", nt_errstr(status
));
4250 if (labs(t
- time(NULL
)) > 60*60*24*10) {
4251 printf("ERROR: SMBgetatr bug. time is %s",
4257 t2
= t
-60*60*24; /* 1 day ago */
4259 /* Ensure we can't set with out-of-range (unknown) attribute. */
4260 status
= cli_setatr(cli
, fname
, 0x20000, t2
);
4261 if (!NT_STATUS_EQUAL(status
, NT_STATUS_INVALID_PARAMETER
)) {
4266 status
= cli_setatr(cli
, fname
, 0, t2
);
4267 if (!NT_STATUS_IS_OK(status
)) {
4268 printf("setatr failed (%s)\n", nt_errstr(status
));
4272 status
= cli_getatr(cli
, fname
, NULL
, NULL
, &t
);
4273 if (!NT_STATUS_IS_OK(status
)) {
4274 printf("getatr failed (%s)\n", nt_errstr(status
));
4279 printf("ERROR: getatr/setatr bug. times are\n%s",
4281 printf("%s", ctime(&t2
));
4285 cli_unlink(cli
, fname
, FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
);
4287 /* Check cli_setpathinfo_ext() */
4288 /* Re-create the file. */
4289 status
= cli_openx(cli
, fname
,
4290 O_RDWR
| O_CREAT
| O_TRUNC
, DENY_NONE
, &fnum
);
4291 if (!NT_STATUS_IS_OK(status
)) {
4292 printf("Failed to recreate %s (%s)\n",
4293 fname
, nt_errstr(status
));
4296 cli_close(cli
, fnum
);
4298 status
= cli_setpathinfo_ext(
4301 (struct timespec
) { .tv_nsec
= SAMBA_UTIME_OMIT
}, /* create */
4302 (struct timespec
) { .tv_nsec
= SAMBA_UTIME_OMIT
}, /* access */
4303 (struct timespec
) { .tv_nsec
= SAMBA_UTIME_OMIT
}, /* write */
4304 (struct timespec
) { .tv_nsec
= SAMBA_UTIME_OMIT
}, /* change */
4305 FILE_ATTRIBUTE_SYSTEM
|
4306 FILE_ATTRIBUTE_HIDDEN
|
4307 FILE_ATTRIBUTE_READONLY
);
4308 if (!NT_STATUS_IS_OK(status
)) {
4309 printf("cli_setpathinfo_ext failed with %s\n",
4314 /* Check attributes are correct. */
4315 correct
= check_attributes(cli
,
4317 FILE_ATTRIBUTE_SYSTEM
|
4318 FILE_ATTRIBUTE_HIDDEN
|
4319 FILE_ATTRIBUTE_READONLY
);
4320 if (correct
== false) {
4324 /* Setting to FILE_ATTRIBUTE_NORMAL should be ignored. */
4325 status
= cli_setpathinfo_ext(
4328 (struct timespec
) { .tv_nsec
= SAMBA_UTIME_OMIT
}, /* create */
4329 (struct timespec
) { .tv_nsec
= SAMBA_UTIME_OMIT
}, /* access */
4330 (struct timespec
) { .tv_nsec
= SAMBA_UTIME_OMIT
}, /* write */
4331 (struct timespec
) { .tv_nsec
= SAMBA_UTIME_OMIT
}, /* change */
4332 FILE_ATTRIBUTE_NORMAL
);
4333 if (!NT_STATUS_IS_OK(status
)) {
4334 printf("cli_setpathinfo_ext failed with %s\n",
4339 /* Check attributes are correct. */
4340 correct
= check_attributes(cli
,
4342 FILE_ATTRIBUTE_SYSTEM
|
4343 FILE_ATTRIBUTE_HIDDEN
|
4344 FILE_ATTRIBUTE_READONLY
);
4345 if (correct
== false) {
4349 /* Setting to (uint16_t)-1 should also be ignored. */
4350 status
= cli_setpathinfo_ext(
4353 (struct timespec
) { .tv_nsec
= SAMBA_UTIME_OMIT
}, /* create */
4354 (struct timespec
) { .tv_nsec
= SAMBA_UTIME_OMIT
}, /* access */
4355 (struct timespec
) { .tv_nsec
= SAMBA_UTIME_OMIT
}, /* write */
4356 (struct timespec
) { .tv_nsec
= SAMBA_UTIME_OMIT
}, /* change */
4358 if (!NT_STATUS_IS_OK(status
)) {
4359 printf("cli_setpathinfo_ext failed with %s\n",
4364 /* Check attributes are correct. */
4365 correct
= check_attributes(cli
,
4367 FILE_ATTRIBUTE_SYSTEM
|
4368 FILE_ATTRIBUTE_HIDDEN
|
4369 FILE_ATTRIBUTE_READONLY
);
4370 if (correct
== false) {
4374 /* Setting to 0 should clear them all. */
4375 status
= cli_setpathinfo_ext(
4378 (struct timespec
) { .tv_nsec
= SAMBA_UTIME_OMIT
}, /* create */
4379 (struct timespec
) { .tv_nsec
= SAMBA_UTIME_OMIT
}, /* access */
4380 (struct timespec
) { .tv_nsec
= SAMBA_UTIME_OMIT
}, /* write */
4381 (struct timespec
) { .tv_nsec
= SAMBA_UTIME_OMIT
}, /* change */
4383 if (!NT_STATUS_IS_OK(status
)) {
4384 printf("cli_setpathinfo_ext failed with %s\n",
4389 /* Check attributes are correct. */
4390 correct
= check_attributes(cli
,
4392 FILE_ATTRIBUTE_NORMAL
);
4393 if (correct
== false) {
4401 FILE_ATTRIBUTE_SYSTEM
|
4402 FILE_ATTRIBUTE_HIDDEN
|
4403 FILE_ATTRIBUTE_READONLY
);
4405 if (!torture_close_connection(cli
)) {
4409 printf("attrib test finished\n");
4414 static NTSTATUS
cli_qfilename(
4415 struct cli_state
*cli
,
4417 TALLOC_CTX
*mem_ctx
,
4420 uint16_t recv_flags2
;
4427 status
= cli_qfileinfo(talloc_tos(),
4430 FSCC_FILE_NAME_INFORMATION
,
4436 if (!NT_STATUS_IS_OK(status
)) {
4440 namelen
= IVAL(rdata
, 0);
4441 if (namelen
> (num_rdata
- 4)) {
4443 return NT_STATUS_INVALID_NETWORK_RESPONSE
;
4446 pull_string_talloc(mem_ctx
,
4447 (const char *)rdata
,
4454 status
= map_nt_error_from_unix(errno
);
4461 return NT_STATUS_OK
;
4465 This checks a couple of trans2 calls
4467 static bool run_trans2test(int dummy
)
4469 struct cli_state
*cli
;
4472 time_t c_time
, a_time
, m_time
;
4473 struct timespec c_time_ts
, a_time_ts
, m_time_ts
, w_time_ts
, m_time2_ts
;
4474 const char *fname
= "\\trans2.tst";
4475 const char *dname
= "\\trans2";
4476 const char *fname2
= "\\trans2\\trans2.tst";
4478 bool correct
= True
;
4483 printf("starting trans2 test\n");
4485 if (!torture_open_connection(&cli
, 0)) {
4489 if (smbXcli_conn_protocol(cli
->conn
) >= PROTOCOL_SMB2_02
) {
4490 /* Ensure ino is zero, SMB2 gets a real one. */
4493 /* Ensure ino is -1, SMB1 never gets a real one. */
4497 status
= cli_get_fs_attr_info(cli
, &fs_attr
);
4498 if (!NT_STATUS_IS_OK(status
)) {
4499 printf("ERROR: cli_get_fs_attr_info returned %s\n",
4504 cli_unlink(cli
, fname
, FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
);
4505 cli_openx(cli
, fname
, O_RDWR
| O_CREAT
| O_TRUNC
, DENY_NONE
, &fnum
);
4506 status
= cli_qfileinfo_basic(cli
, fnum
, NULL
, &size
, &c_time_ts
,
4507 &a_time_ts
, &w_time_ts
, &m_time_ts
, NULL
);
4508 if (!NT_STATUS_IS_OK(status
)) {
4509 printf("ERROR: qfileinfo failed (%s)\n", nt_errstr(status
));
4513 status
= cli_qfilename(cli
, fnum
, talloc_tos(), &pname
);
4514 if (!NT_STATUS_IS_OK(status
)) {
4515 printf("ERROR: qfilename failed (%s)\n", nt_errstr(status
));
4518 else if (strcmp(pname
, fname
)) {
4519 printf("qfilename gave different name? [%s] [%s]\n",
4524 cli_close(cli
, fnum
);
4528 cli_unlink(cli
, fname
, FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
);
4529 status
= cli_openx(cli
, fname
, O_RDWR
| O_CREAT
| O_TRUNC
, DENY_NONE
,
4531 if (!NT_STATUS_IS_OK(status
)) {
4532 printf("open of %s failed (%s)\n", fname
, nt_errstr(status
));
4535 cli_close(cli
, fnum
);
4537 status
= cli_qpathinfo1(cli
, fname
, &c_time
, &a_time
, &m_time
, &size
,
4539 if (!NT_STATUS_IS_OK(status
)) {
4540 printf("ERROR: qpathinfo failed (%s)\n", nt_errstr(status
));
4543 time_t t
= time(NULL
);
4545 if (c_time
!= m_time
) {
4546 printf("create time=%s", ctime(&c_time
));
4547 printf("modify time=%s", ctime(&m_time
));
4548 printf("This system appears to have sticky create times\n");
4550 if ((labs(a_time
- t
) > 60) && (a_time
% (60*60) == 0)) {
4551 printf("access time=%s", ctime(&a_time
));
4552 printf("This system appears to set a midnight access time\n");
4556 if (labs(m_time
- t
) > 60*60*24*7) {
4557 printf("ERROR: totally incorrect times - maybe word reversed? mtime=%s", ctime(&m_time
));
4563 cli_unlink(cli
, fname
, FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
);
4564 cli_openx(cli
, fname
,
4565 O_RDWR
| O_CREAT
| O_TRUNC
, DENY_NONE
, &fnum
);
4566 cli_close(cli
, fnum
);
4567 status
= cli_qpathinfo2(cli
,
4577 if (!NT_STATUS_IS_OK(status
)) {
4578 printf("ERROR: qpathinfo2 failed (%s)\n", nt_errstr(status
));
4581 if (w_time_ts
.tv_sec
< 60*60*24*2) {
4582 printf("write time=%s", ctime(&w_time_ts
.tv_sec
));
4583 printf("This system appears to set a initial 0 write time\n");
4586 if (smbXcli_conn_protocol(cli
->conn
) >= PROTOCOL_SMB2_02
) {
4587 /* SMB2 should always return an inode. */
4589 printf("SMB2 bad inode (0)\n");
4593 /* SMB1 must always return zero here. */
4595 printf("SMB1 bad inode (!0)\n");
4601 cli_unlink(cli
, fname
, FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
);
4604 /* check if the server updates the directory modification time
4605 when creating a new file */
4606 status
= cli_mkdir(cli
, dname
);
4607 if (!NT_STATUS_IS_OK(status
)) {
4608 printf("ERROR: mkdir failed (%s)\n", nt_errstr(status
));
4612 status
= cli_qpathinfo2(cli
,
4622 if (!NT_STATUS_IS_OK(status
)) {
4623 printf("ERROR: qpathinfo2 failed (%s)\n", nt_errstr(status
));
4627 cli_openx(cli
, fname2
,
4628 O_RDWR
| O_CREAT
| O_TRUNC
, DENY_NONE
, &fnum
);
4629 cli_writeall(cli
, fnum
, 0, (uint8_t *)&fnum
, 0, sizeof(fnum
), NULL
);
4630 cli_close(cli
, fnum
);
4631 status
= cli_qpathinfo2(cli
,
4641 if (!NT_STATUS_IS_OK(status
)) {
4642 printf("ERROR: qpathinfo2 failed (%s)\n", nt_errstr(status
));
4645 if (memcmp(&m_time_ts
, &m_time2_ts
, sizeof(struct timespec
))
4647 printf("This system does not update directory modification times\n");
4651 cli_unlink(cli
, fname2
, FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
);
4652 cli_rmdir(cli
, dname
);
4654 if (!torture_close_connection(cli
)) {
4658 printf("trans2 test finished\n");
4664 This checks new W2K calls.
4667 static NTSTATUS
new_trans(struct cli_state
*pcli
, int fnum
, int level
)
4669 uint8_t *buf
= NULL
;
4673 status
= cli_qfileinfo(talloc_tos(), pcli
, fnum
, level
, 0,
4674 CLI_BUFFER_SIZE
, NULL
, &buf
, &len
);
4675 if (!NT_STATUS_IS_OK(status
)) {
4676 printf("ERROR: qfileinfo (%d) failed (%s)\n", level
,
4679 printf("qfileinfo: level %d, len = %u\n", level
, len
);
4680 dump_data(0, (uint8_t *)buf
, len
);
4687 static bool run_w2ktest(int dummy
)
4689 struct cli_state
*cli
;
4691 const char *fname
= "\\w2ktest\\w2k.tst";
4693 bool correct
= True
;
4695 printf("starting w2k test\n");
4697 if (!torture_open_connection(&cli
, 0)) {
4701 cli_openx(cli
, fname
,
4702 O_RDWR
| O_CREAT
, DENY_NONE
, &fnum
);
4704 for (level
= 1004; level
< 1040; level
++) {
4705 new_trans(cli
, fnum
, level
);
4708 cli_close(cli
, fnum
);
4710 if (!torture_close_connection(cli
)) {
4714 printf("w2k test finished\n");
4721 this is a harness for some oplock tests
4723 static bool run_oplock1(int dummy
)
4725 struct cli_state
*cli1
;
4726 const char *fname
= "\\lockt1.lck";
4728 bool correct
= True
;
4731 printf("starting oplock test 1\n");
4733 if (!torture_open_connection(&cli1
, 0)) {
4737 cli_unlink(cli1
, fname
, FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
);
4739 smbXcli_conn_set_sockopt(cli1
->conn
, sockops
);
4741 cli1
->use_oplocks
= True
;
4743 status
= cli_openx(cli1
, fname
, O_RDWR
|O_CREAT
|O_EXCL
, DENY_NONE
,
4745 if (!NT_STATUS_IS_OK(status
)) {
4746 printf("open of %s failed (%s)\n", fname
, nt_errstr(status
));
4750 cli1
->use_oplocks
= False
;
4752 cli_unlink(cli1
, fname
, FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
);
4753 cli_unlink(cli1
, fname
, FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
);
4755 status
= cli_close(cli1
, fnum1
);
4756 if (!NT_STATUS_IS_OK(status
)) {
4757 printf("close2 failed (%s)\n", nt_errstr(status
));
4761 status
= cli_unlink(cli1
, fname
, FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
);
4762 if (!NT_STATUS_IS_OK(status
)) {
4763 printf("unlink failed (%s)\n", nt_errstr(status
));
4767 if (!torture_close_connection(cli1
)) {
4771 printf("finished oplock test 1\n");
4776 static bool run_oplock2(int dummy
)
4778 struct cli_state
*cli1
, *cli2
;
4779 const char *fname
= "\\lockt2.lck";
4780 uint16_t fnum1
, fnum2
;
4781 int saved_use_oplocks
= use_oplocks
;
4783 bool correct
= True
;
4784 volatile bool *shared_correct
;
4788 shared_correct
= (volatile bool *)anonymous_shared_allocate(sizeof(bool));
4789 *shared_correct
= True
;
4791 use_level_II_oplocks
= True
;
4794 printf("starting oplock test 2\n");
4796 if (!torture_open_connection(&cli1
, 0)) {
4797 use_level_II_oplocks
= False
;
4798 use_oplocks
= saved_use_oplocks
;
4802 if (!torture_open_connection(&cli2
, 1)) {
4803 use_level_II_oplocks
= False
;
4804 use_oplocks
= saved_use_oplocks
;
4808 cli_unlink(cli1
, fname
, FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
);
4810 smbXcli_conn_set_sockopt(cli1
->conn
, sockops
);
4811 smbXcli_conn_set_sockopt(cli2
->conn
, sockops
);
4813 status
= cli_openx(cli1
, fname
, O_RDWR
|O_CREAT
|O_EXCL
, DENY_NONE
,
4815 if (!NT_STATUS_IS_OK(status
)) {
4816 printf("open of %s failed (%s)\n", fname
, nt_errstr(status
));
4820 /* Don't need the globals any more. */
4821 use_level_II_oplocks
= False
;
4822 use_oplocks
= saved_use_oplocks
;
4826 status
= cli_openx(cli2
, fname
, O_RDWR
, DENY_NONE
, &fnum2
);
4827 if (!NT_STATUS_IS_OK(status
)) {
4828 printf("second open of %s failed (%s)\n", fname
, nt_errstr(status
));
4829 *shared_correct
= False
;
4835 status
= cli_close(cli2
, fnum2
);
4836 if (!NT_STATUS_IS_OK(status
)) {
4837 printf("close2 failed (%s)\n", nt_errstr(status
));
4838 *shared_correct
= False
;
4846 /* Ensure cli1 processes the break. Empty file should always return 0
4848 status
= cli_read(cli1
, fnum1
, buf
, 0, 4, &nread
);
4849 if (!NT_STATUS_IS_OK(status
)) {
4850 printf("read on fnum1 failed (%s)\n", nt_errstr(status
));
4852 } else if (nread
!= 0) {
4853 printf("read on empty fnum1 failed. recv %ld expected %d\n",
4854 (unsigned long)nread
, 0);
4858 /* Should now be at level II. */
4859 /* Test if sending a write locks causes a break to none. */
4860 status
= cli_lock32(cli1
, fnum1
, 0, 4, 0, READ_LOCK
);
4861 if (!NT_STATUS_IS_OK(status
)) {
4862 printf("lock failed (%s)\n", nt_errstr(status
));
4866 cli_unlock(cli1
, fnum1
, 0, 4);
4870 status
= cli_lock32(cli1
, fnum1
, 0, 4, 0, WRITE_LOCK
);
4871 if (!NT_STATUS_IS_OK(status
)) {
4872 printf("lock failed (%s)\n", nt_errstr(status
));
4876 cli_unlock(cli1
, fnum1
, 0, 4);
4880 cli_read(cli1
, fnum1
, buf
, 0, 4, NULL
);
4882 status
= cli_close(cli1
, fnum1
);
4883 if (!NT_STATUS_IS_OK(status
)) {
4884 printf("close1 failed (%s)\n", nt_errstr(status
));
4890 status
= cli_unlink(cli1
, fname
, FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
);
4891 if (!NT_STATUS_IS_OK(status
)) {
4892 printf("unlink failed (%s)\n", nt_errstr(status
));
4896 if (!torture_close_connection(cli1
)) {
4900 if (!*shared_correct
) {
4904 printf("finished oplock test 2\n");
4909 struct oplock4_state
{
4910 struct tevent_context
*ev
;
4911 struct cli_state
*cli
;
4916 static void oplock4_got_break(struct tevent_req
*req
);
4917 static void oplock4_got_open(struct tevent_req
*req
);
4919 static bool run_oplock4(int dummy
)
4921 struct tevent_context
*ev
;
4922 struct cli_state
*cli1
, *cli2
;
4923 struct tevent_req
*oplock_req
, *open_req
;
4924 const char *fname
= "\\lockt4.lck";
4925 const char *fname_ln
= "\\lockt4_ln.lck";
4926 uint16_t fnum1
, fnum2
;
4927 int saved_use_oplocks
= use_oplocks
;
4929 bool correct
= true;
4933 struct oplock4_state
*state
;
4935 printf("starting oplock test 4\n");
4937 if (!torture_open_connection(&cli1
, 0)) {
4938 use_level_II_oplocks
= false;
4939 use_oplocks
= saved_use_oplocks
;
4943 if (!torture_open_connection(&cli2
, 1)) {
4944 use_level_II_oplocks
= false;
4945 use_oplocks
= saved_use_oplocks
;
4949 cli_unlink(cli1
, fname
, FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
);
4950 cli_unlink(cli1
, fname_ln
, FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
);
4952 smbXcli_conn_set_sockopt(cli1
->conn
, sockops
);
4953 smbXcli_conn_set_sockopt(cli2
->conn
, sockops
);
4955 /* Create the file. */
4956 status
= cli_openx(cli1
, fname
, O_RDWR
|O_CREAT
|O_EXCL
, DENY_NONE
,
4958 if (!NT_STATUS_IS_OK(status
)) {
4959 printf("open of %s failed (%s)\n", fname
, nt_errstr(status
));
4963 status
= cli_close(cli1
, fnum1
);
4964 if (!NT_STATUS_IS_OK(status
)) {
4965 printf("close1 failed (%s)\n", nt_errstr(status
));
4969 /* Now create a hardlink. */
4970 status
= cli_hardlink(cli1
, fname
, fname_ln
);
4971 if (!NT_STATUS_IS_OK(status
)) {
4972 printf("nt hardlink failed (%s)\n", nt_errstr(status
));
4976 /* Prove that opening hardlinks cause deny modes to conflict. */
4977 status
= cli_openx(cli1
, fname
, O_RDWR
, DENY_ALL
, &fnum1
);
4978 if (!NT_STATUS_IS_OK(status
)) {
4979 printf("open of %s failed (%s)\n", fname
, nt_errstr(status
));
4983 status
= cli_openx(cli1
, fname_ln
, O_RDWR
, DENY_NONE
, &fnum2
);
4984 if (NT_STATUS_IS_OK(status
)) {
4985 printf("open of %s succeeded - should fail with sharing violation.\n",
4990 if (!NT_STATUS_EQUAL(status
, NT_STATUS_SHARING_VIOLATION
)) {
4991 printf("open of %s should fail with sharing violation. Got %s\n",
4992 fname_ln
, nt_errstr(status
));
4996 status
= cli_close(cli1
, fnum1
);
4997 if (!NT_STATUS_IS_OK(status
)) {
4998 printf("close1 failed (%s)\n", nt_errstr(status
));
5002 cli1
->use_oplocks
= true;
5003 cli2
->use_oplocks
= true;
5005 status
= cli_openx(cli1
, fname
, O_RDWR
, DENY_NONE
, &fnum1
);
5006 if (!NT_STATUS_IS_OK(status
)) {
5007 printf("open of %s failed (%s)\n", fname
, nt_errstr(status
));
5011 ev
= samba_tevent_context_init(talloc_tos());
5013 printf("tevent_context_init failed\n");
5017 state
= talloc(ev
, struct oplock4_state
);
5018 if (state
== NULL
) {
5019 printf("talloc failed\n");
5024 state
->got_break
= &got_break
;
5025 state
->fnum2
= &fnum2
;
5027 oplock_req
= cli_smb_oplock_break_waiter_send(
5028 talloc_tos(), ev
, cli1
);
5029 if (oplock_req
== NULL
) {
5030 printf("cli_smb_oplock_break_waiter_send failed\n");
5033 tevent_req_set_callback(oplock_req
, oplock4_got_break
, state
);
5035 open_req
= cli_openx_send(
5036 talloc_tos(), ev
, cli2
, fname_ln
, O_RDWR
, DENY_NONE
);
5037 if (open_req
== NULL
) {
5038 printf("cli_openx_send failed\n");
5041 tevent_req_set_callback(open_req
, oplock4_got_open
, state
);
5046 while (!got_break
|| fnum2
== 0xffff) {
5048 ret
= tevent_loop_once(ev
);
5050 printf("tevent_loop_once failed: %s\n",
5056 status
= cli_close(cli2
, fnum2
);
5057 if (!NT_STATUS_IS_OK(status
)) {
5058 printf("close2 failed (%s)\n", nt_errstr(status
));
5062 status
= cli_close(cli1
, fnum1
);
5063 if (!NT_STATUS_IS_OK(status
)) {
5064 printf("close1 failed (%s)\n", nt_errstr(status
));
5068 status
= cli_unlink(cli1
, fname
, FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
);
5069 if (!NT_STATUS_IS_OK(status
)) {
5070 printf("unlink failed (%s)\n", nt_errstr(status
));
5074 status
= cli_unlink(cli1
, fname_ln
, FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
);
5075 if (!NT_STATUS_IS_OK(status
)) {
5076 printf("unlink failed (%s)\n", nt_errstr(status
));
5080 if (!torture_close_connection(cli1
)) {
5088 printf("finished oplock test 4\n");
5093 static void oplock4_got_break(struct tevent_req
*req
)
5095 struct oplock4_state
*state
= tevent_req_callback_data(
5096 req
, struct oplock4_state
);
5101 status
= cli_smb_oplock_break_waiter_recv(req
, &fnum
, &level
);
5103 if (!NT_STATUS_IS_OK(status
)) {
5104 printf("cli_smb_oplock_break_waiter_recv returned %s\n",
5108 *state
->got_break
= true;
5110 req
= cli_oplock_ack_send(state
, state
->ev
, state
->cli
, fnum
,
5113 printf("cli_oplock_ack_send failed\n");
5118 static void oplock4_got_open(struct tevent_req
*req
)
5120 struct oplock4_state
*state
= tevent_req_callback_data(
5121 req
, struct oplock4_state
);
5124 status
= cli_openx_recv(req
, state
->fnum2
);
5125 if (!NT_STATUS_IS_OK(status
)) {
5126 printf("cli_openx_recv returned %s\n", nt_errstr(status
));
5127 *state
->fnum2
= 0xffff;
5131 #ifdef HAVE_KERNEL_OPLOCKS_LINUX
5133 struct oplock5_state
{
5138 * Async open the file that has a kernel oplock, do an echo to get
5139 * that 100% across, close the file to signal to the child fd that the
5140 * oplock can be dropped, wait for the open reply.
5143 static void oplock5_opened(struct tevent_req
*subreq
);
5144 static void oplock5_pong(struct tevent_req
*subreq
);
5145 static void oplock5_timedout(struct tevent_req
*subreq
);
5147 static struct tevent_req
*oplock5_send(
5148 TALLOC_CTX
*mem_ctx
,
5149 struct tevent_context
*ev
,
5150 struct cli_state
*cli
,
5154 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
5155 struct oplock5_state
*state
= NULL
;
5156 static uint8_t data
= 0;
5158 req
= tevent_req_create(mem_ctx
, &state
, struct oplock5_state
);
5162 state
->pipe_down_fd
= pipe_down_fd
;
5164 subreq
= cli_ntcreate_send(
5170 SEC_FILE_READ_DATA
, /* DesiredAccess */
5171 FILE_ATTRIBUTE_NORMAL
, /* FileAttributes */
5172 FILE_SHARE_WRITE
|FILE_SHARE_READ
, /* ShareAccess */
5173 FILE_OPEN
, /* CreateDisposition */
5174 FILE_NON_DIRECTORY_FILE
, /* CreateOptions */
5175 0, /* Impersonation */
5176 0); /* SecurityFlags */
5177 if (tevent_req_nomem(subreq
, req
)) {
5178 return tevent_req_post(req
, ev
);
5180 tevent_req_set_callback(subreq
, oplock5_opened
, req
);
5182 subreq
= cli_echo_send(
5187 (DATA_BLOB
) { .data
= &data
, .length
= sizeof(data
) });
5188 if (tevent_req_nomem(subreq
, req
)) {
5189 return tevent_req_post(req
, ev
);
5191 tevent_req_set_callback(subreq
, oplock5_pong
, req
);
5193 subreq
= tevent_wakeup_send(state
, ev
, timeval_current_ofs(20, 0));
5194 if (tevent_req_nomem(subreq
, req
)) {
5195 return tevent_req_post(req
, ev
);
5197 tevent_req_set_callback(subreq
, oplock5_timedout
, req
);
5202 static void oplock5_opened(struct tevent_req
*subreq
)
5204 struct tevent_req
*req
= tevent_req_callback_data(
5205 subreq
, struct tevent_req
);
5209 status
= cli_ntcreate_recv(subreq
, &fnum
, NULL
);
5210 TALLOC_FREE(subreq
);
5211 if (tevent_req_nterror(req
, status
)) {
5214 tevent_req_done(req
);
5217 static void oplock5_pong(struct tevent_req
*subreq
)
5219 struct tevent_req
*req
= tevent_req_callback_data(
5220 subreq
, struct tevent_req
);
5221 struct oplock5_state
*state
= tevent_req_data(
5222 req
, struct oplock5_state
);
5225 status
= cli_echo_recv(subreq
);
5226 TALLOC_FREE(subreq
);
5227 if (tevent_req_nterror(req
, status
)) {
5231 close(state
->pipe_down_fd
);
5234 static void oplock5_timedout(struct tevent_req
*subreq
)
5236 struct tevent_req
*req
= tevent_req_callback_data(
5237 subreq
, struct tevent_req
);
5240 ok
= tevent_wakeup_recv(subreq
);
5241 TALLOC_FREE(subreq
);
5243 tevent_req_oom(req
);
5246 tevent_req_nterror(req
, NT_STATUS_TIMEOUT
);
5249 static NTSTATUS
oplock5_recv(struct tevent_req
*req
)
5251 return tevent_req_simple_recv_ntstatus(req
);
5254 static bool run_oplock5(int dummy
)
5256 struct tevent_context
*ev
= NULL
;
5257 struct tevent_req
*req
= NULL
;
5258 struct cli_state
*cli
= NULL
;
5259 const char *fname
= "oplock5.txt";
5260 int pipe_down
[2], pipe_up
[2];
5267 printf("starting oplock5\n");
5269 if (local_path
== NULL
) {
5270 d_fprintf(stderr
, "oplock5 must be given a local path via "
5271 "-l <localpath>\n");
5275 ret
= pipe(pipe_down
);
5277 d_fprintf(stderr
, "pipe() failed: %s\n", strerror(errno
));
5280 ret
= pipe(pipe_up
);
5282 d_fprintf(stderr
, "pipe() failed: %s\n", strerror(errno
));
5287 if (child_pid
== -1) {
5288 d_fprintf(stderr
, "fork() failed: %s\n", strerror(errno
));
5292 if (child_pid
== 0) {
5293 char *local_file
= NULL
;
5296 close(pipe_down
[1]);
5299 local_file
= talloc_asprintf(
5300 talloc_tos(), "%s/%s", local_path
, fname
);
5301 if (local_file
== 0) {
5305 fd
= open(local_file
, O_RDWR
|O_CREAT
, 0644);
5308 "open(%s) in child failed: %s\n",
5315 signal(SIGIO
, SIG_IGN
);
5317 ret
= fcntl(fd
, F_SETLEASE
, F_WRLCK
);
5320 "SETLEASE in child failed: %s\n",
5327 ret
= sys_write(pipe_up
[1], &c
, sizeof(c
));
5330 "sys_write failed: %s\n",
5334 ret
= sys_read(pipe_down
[0], &c
, sizeof(c
));
5337 "sys_read failed: %s\n",
5345 close(pipe_down
[0]);
5347 ret
= sys_read(pipe_up
[0], &c
, sizeof(c
));
5350 "sys_read failed: %s\n",
5355 d_fprintf(stderr
, "got error code %"PRIu8
"\n", c
);
5359 ok
= torture_open_connection(&cli
, 0);
5361 d_fprintf(stderr
, "torture_open_connection failed\n");
5365 ev
= samba_tevent_context_init(talloc_tos());
5367 d_fprintf(stderr
, "samba_tevent_context_init failed\n");
5371 req
= oplock5_send(ev
, ev
, cli
, fname
, pipe_down
[1]);
5373 d_fprintf(stderr
, "oplock5_send failed\n");
5377 ok
= tevent_req_poll_ntstatus(req
, ev
, &status
);
5380 "tevent_req_poll_ntstatus failed: %s\n",
5385 status
= oplock5_recv(req
);
5387 if (!NT_STATUS_IS_OK(status
)) {
5389 "oplock5 failed: %s\n",
5397 #endif /* HAVE_KERNEL_OPLOCKS_LINUX */
5400 Test delete on close semantics.
5402 static bool run_deletetest(int dummy
)
5404 struct cli_state
*cli1
= NULL
;
5405 struct cli_state
*cli2
= NULL
;
5406 const char *fname
= "\\delete.file";
5407 uint16_t fnum1
= (uint16_t)-1;
5408 uint16_t fnum2
= (uint16_t)-1;
5409 bool correct
= false;
5412 printf("starting delete test\n");
5414 if (!torture_open_connection(&cli1
, 0)) {
5418 smbXcli_conn_set_sockopt(cli1
->conn
, sockops
);
5420 /* Test 1 - this should delete the file on close. */
5422 cli_setatr(cli1
, fname
, 0, 0);
5423 cli_unlink(cli1
, fname
, FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
);
5425 status
= cli_ntcreate(cli1
, fname
, 0, GENERIC_ALL_ACCESS
|DELETE_ACCESS
,
5426 FILE_ATTRIBUTE_NORMAL
, 0, FILE_OVERWRITE_IF
,
5427 FILE_DELETE_ON_CLOSE
, 0, &fnum1
, NULL
);
5428 if (!NT_STATUS_IS_OK(status
)) {
5429 printf("[1] open of %s failed (%s)\n", fname
, nt_errstr(status
));
5433 status
= cli_close(cli1
, fnum1
);
5434 if (!NT_STATUS_IS_OK(status
)) {
5435 printf("[1] close failed (%s)\n", nt_errstr(status
));
5439 status
= cli_openx(cli1
, fname
, O_RDWR
, DENY_NONE
, &fnum1
);
5440 if (NT_STATUS_IS_OK(status
)) {
5441 printf("[1] open of %s succeeded (should fail)\n", fname
);
5445 printf("first delete on close test succeeded.\n");
5447 /* Test 2 - this should delete the file on close. */
5449 cli_setatr(cli1
, fname
, 0, 0);
5450 cli_unlink(cli1
, fname
, FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
);
5452 status
= cli_ntcreate(cli1
, fname
, 0, GENERIC_ALL_ACCESS
,
5453 FILE_ATTRIBUTE_NORMAL
, FILE_SHARE_NONE
,
5454 FILE_OVERWRITE_IF
, 0, 0, &fnum1
, NULL
);
5455 if (!NT_STATUS_IS_OK(status
)) {
5456 printf("[2] open of %s failed (%s)\n", fname
, nt_errstr(status
));
5460 status
= cli_nt_delete_on_close(cli1
, fnum1
, true);
5461 if (!NT_STATUS_IS_OK(status
)) {
5462 printf("[2] setting delete_on_close failed (%s)\n", nt_errstr(status
));
5466 status
= cli_close(cli1
, fnum1
);
5467 if (!NT_STATUS_IS_OK(status
)) {
5468 printf("[2] close failed (%s)\n", nt_errstr(status
));
5472 status
= cli_openx(cli1
, fname
, O_RDONLY
, DENY_NONE
, &fnum1
);
5473 if (NT_STATUS_IS_OK(status
)) {
5474 printf("[2] open of %s succeeded should have been deleted on close !\n", fname
);
5475 status
= cli_close(cli1
, fnum1
);
5476 if (!NT_STATUS_IS_OK(status
)) {
5477 printf("[2] close failed (%s)\n", nt_errstr(status
));
5479 cli_unlink(cli1
, fname
, FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
);
5483 printf("second delete on close test succeeded.\n");
5486 cli_setatr(cli1
, fname
, 0, 0);
5487 cli_unlink(cli1
, fname
, FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
);
5489 status
= cli_ntcreate(cli1
, fname
, 0, GENERIC_ALL_ACCESS
,
5490 FILE_ATTRIBUTE_NORMAL
,
5491 FILE_SHARE_READ
|FILE_SHARE_WRITE
,
5492 FILE_OVERWRITE_IF
, 0, 0, &fnum1
, NULL
);
5493 if (!NT_STATUS_IS_OK(status
)) {
5494 printf("[3] open - 1 of %s failed (%s)\n", fname
, nt_errstr(status
));
5498 /* This should fail with a sharing violation - open for delete is only compatible
5499 with SHARE_DELETE. */
5501 status
= cli_ntcreate(cli1
, fname
, 0, GENERIC_READ_ACCESS
,
5502 FILE_ATTRIBUTE_NORMAL
,
5503 FILE_SHARE_READ
|FILE_SHARE_WRITE
,
5504 FILE_OPEN
, 0, 0, &fnum2
, NULL
);
5505 if (NT_STATUS_IS_OK(status
)) {
5506 printf("[3] open - 2 of %s succeeded - should have failed.\n", fname
);
5510 /* This should succeed. */
5511 status
= cli_ntcreate(cli1
, fname
, 0, GENERIC_READ_ACCESS
,
5512 FILE_ATTRIBUTE_NORMAL
,
5513 FILE_SHARE_READ
|FILE_SHARE_WRITE
|FILE_SHARE_DELETE
,
5514 FILE_OPEN
, 0, 0, &fnum2
, NULL
);
5515 if (!NT_STATUS_IS_OK(status
)) {
5516 printf("[3] open - 3 of %s failed (%s)\n", fname
, nt_errstr(status
));
5520 status
= cli_nt_delete_on_close(cli1
, fnum1
, true);
5521 if (!NT_STATUS_IS_OK(status
)) {
5522 printf("[3] setting delete_on_close failed (%s)\n", nt_errstr(status
));
5526 status
= cli_close(cli1
, fnum1
);
5527 if (!NT_STATUS_IS_OK(status
)) {
5528 printf("[3] close 1 failed (%s)\n", nt_errstr(status
));
5532 status
= cli_close(cli1
, fnum2
);
5533 if (!NT_STATUS_IS_OK(status
)) {
5534 printf("[3] close 2 failed (%s)\n", nt_errstr(status
));
5538 /* This should fail - file should no longer be there. */
5540 status
= cli_openx(cli1
, fname
, O_RDONLY
, DENY_NONE
, &fnum1
);
5541 if (NT_STATUS_IS_OK(status
)) {
5542 printf("[3] open of %s succeeded should have been deleted on close !\n", fname
);
5543 status
= cli_close(cli1
, fnum1
);
5544 if (!NT_STATUS_IS_OK(status
)) {
5545 printf("[3] close failed (%s)\n", nt_errstr(status
));
5547 cli_unlink(cli1
, fname
, FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
);
5551 printf("third delete on close test succeeded.\n");
5554 cli_setatr(cli1
, fname
, 0, 0);
5555 cli_unlink(cli1
, fname
, FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
);
5557 status
= cli_ntcreate(cli1
, fname
, 0,
5558 FILE_READ_DATA
|FILE_WRITE_DATA
|DELETE_ACCESS
,
5559 FILE_ATTRIBUTE_NORMAL
,
5560 FILE_SHARE_READ
|FILE_SHARE_WRITE
,
5561 FILE_OVERWRITE_IF
, 0, 0, &fnum1
, NULL
);
5562 if (!NT_STATUS_IS_OK(status
)) {
5563 printf("[4] open of %s failed (%s)\n", fname
, nt_errstr(status
));
5567 /* This should succeed. */
5568 status
= cli_ntcreate(cli1
, fname
, 0, GENERIC_READ_ACCESS
,
5569 FILE_ATTRIBUTE_NORMAL
,
5570 FILE_SHARE_READ
|FILE_SHARE_WRITE
|FILE_SHARE_DELETE
,
5571 FILE_OPEN
, 0, 0, &fnum2
, NULL
);
5572 if (!NT_STATUS_IS_OK(status
)) {
5573 printf("[4] open - 2 of %s failed (%s)\n", fname
, nt_errstr(status
));
5577 status
= cli_close(cli1
, fnum2
);
5578 if (!NT_STATUS_IS_OK(status
)) {
5579 printf("[4] close - 1 failed (%s)\n", nt_errstr(status
));
5583 status
= cli_nt_delete_on_close(cli1
, fnum1
, true);
5584 if (!NT_STATUS_IS_OK(status
)) {
5585 printf("[4] setting delete_on_close failed (%s)\n", nt_errstr(status
));
5589 /* This should fail - no more opens once delete on close set. */
5590 status
= cli_ntcreate(cli1
, fname
, 0, GENERIC_READ_ACCESS
,
5591 FILE_ATTRIBUTE_NORMAL
,
5592 FILE_SHARE_READ
|FILE_SHARE_WRITE
|FILE_SHARE_DELETE
,
5593 FILE_OPEN
, 0, 0, &fnum2
, NULL
);
5594 if (NT_STATUS_IS_OK(status
)) {
5595 printf("[4] open - 3 of %s succeeded ! Should have failed.\n", fname
);
5599 status
= cli_close(cli1
, fnum1
);
5600 if (!NT_STATUS_IS_OK(status
)) {
5601 printf("[4] close - 2 failed (%s)\n", nt_errstr(status
));
5605 printf("fourth delete on close test succeeded.\n");
5608 cli_setatr(cli1
, fname
, 0, 0);
5609 cli_unlink(cli1
, fname
, FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
);
5611 status
= cli_openx(cli1
, fname
, O_RDWR
|O_CREAT
, DENY_NONE
, &fnum1
);
5612 if (!NT_STATUS_IS_OK(status
)) {
5613 printf("[5] open of %s failed (%s)\n", fname
, nt_errstr(status
));
5617 /* This should fail - only allowed on NT opens with DELETE access. */
5619 status
= cli_nt_delete_on_close(cli1
, fnum1
, true);
5620 if (NT_STATUS_IS_OK(status
)) {
5621 printf("[5] setting delete_on_close on OpenX file succeeded - should fail !\n");
5625 status
= cli_close(cli1
, fnum1
);
5626 if (!NT_STATUS_IS_OK(status
)) {
5627 printf("[5] close failed (%s)\n", nt_errstr(status
));
5631 printf("fifth delete on close test succeeded.\n");
5634 cli_setatr(cli1
, fname
, 0, 0);
5635 cli_unlink(cli1
, fname
, FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
);
5637 status
= cli_ntcreate(cli1
, fname
, 0, FILE_READ_DATA
|FILE_WRITE_DATA
,
5638 FILE_ATTRIBUTE_NORMAL
,
5639 FILE_SHARE_READ
|FILE_SHARE_WRITE
|FILE_SHARE_DELETE
,
5640 FILE_OVERWRITE_IF
, 0, 0, &fnum1
, NULL
);
5641 if (!NT_STATUS_IS_OK(status
)) {
5642 printf("[6] open of %s failed (%s)\n", fname
,
5647 /* This should fail - only allowed on NT opens with DELETE access. */
5649 status
= cli_nt_delete_on_close(cli1
, fnum1
, true);
5650 if (NT_STATUS_IS_OK(status
)) {
5651 printf("[6] setting delete_on_close on file with no delete access succeeded - should fail !\n");
5655 status
= cli_close(cli1
, fnum1
);
5656 if (!NT_STATUS_IS_OK(status
)) {
5657 printf("[6] close failed (%s)\n", nt_errstr(status
));
5661 printf("sixth delete on close test succeeded.\n");
5664 cli_setatr(cli1
, fname
, 0, 0);
5665 cli_unlink(cli1
, fname
, FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
);
5667 status
= cli_ntcreate(cli1
, fname
, 0,
5668 FILE_READ_DATA
|FILE_WRITE_DATA
|DELETE_ACCESS
,
5669 FILE_ATTRIBUTE_NORMAL
, 0, FILE_OVERWRITE_IF
,
5670 0, 0, &fnum1
, NULL
);
5671 if (!NT_STATUS_IS_OK(status
)) {
5672 printf("[7] open of %s failed (%s)\n", fname
, nt_errstr(status
));
5676 status
= cli_nt_delete_on_close(cli1
, fnum1
, true);
5677 if (!NT_STATUS_IS_OK(status
)) {
5678 printf("[7] setting delete_on_close on file failed !\n");
5682 status
= cli_nt_delete_on_close(cli1
, fnum1
, false);
5683 if (!NT_STATUS_IS_OK(status
)) {
5684 printf("[7] unsetting delete_on_close on file failed !\n");
5688 status
= cli_close(cli1
, fnum1
);
5689 if (!NT_STATUS_IS_OK(status
)) {
5690 printf("[7] close - 1 failed (%s)\n", nt_errstr(status
));
5694 /* This next open should succeed - we reset the flag. */
5695 status
= cli_openx(cli1
, fname
, O_RDONLY
, DENY_NONE
, &fnum1
);
5696 if (!NT_STATUS_IS_OK(status
)) {
5697 printf("[7] open of %s failed (%s)\n", fname
, nt_errstr(status
));
5701 status
= cli_close(cli1
, fnum1
);
5702 if (!NT_STATUS_IS_OK(status
)) {
5703 printf("[7] close - 2 failed (%s)\n", nt_errstr(status
));
5707 printf("seventh delete on close test succeeded.\n");
5710 cli_setatr(cli1
, fname
, 0, 0);
5711 cli_unlink(cli1
, fname
, FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
);
5713 if (!torture_open_connection(&cli2
, 1)) {
5714 printf("[8] failed to open second connection.\n");
5718 smbXcli_conn_set_sockopt(cli1
->conn
, sockops
);
5720 status
= cli_ntcreate(cli1
, fname
, 0,
5721 FILE_READ_DATA
|FILE_WRITE_DATA
|DELETE_ACCESS
,
5722 FILE_ATTRIBUTE_NORMAL
,
5723 FILE_SHARE_READ
|FILE_SHARE_WRITE
|FILE_SHARE_DELETE
,
5724 FILE_OVERWRITE_IF
, 0, 0, &fnum1
, NULL
);
5725 if (!NT_STATUS_IS_OK(status
)) {
5726 printf("[8] open 1 of %s failed (%s)\n", fname
, nt_errstr(status
));
5730 status
= cli_ntcreate(cli2
, fname
, 0,
5731 FILE_READ_DATA
|FILE_WRITE_DATA
|DELETE_ACCESS
,
5732 FILE_ATTRIBUTE_NORMAL
,
5733 FILE_SHARE_READ
|FILE_SHARE_WRITE
|FILE_SHARE_DELETE
,
5734 FILE_OPEN
, 0, 0, &fnum2
, NULL
);
5735 if (!NT_STATUS_IS_OK(status
)) {
5736 printf("[8] open 2 of %s failed (%s)\n", fname
, nt_errstr(status
));
5740 status
= cli_nt_delete_on_close(cli1
, fnum1
, true);
5741 if (!NT_STATUS_IS_OK(status
)) {
5742 printf("[8] setting delete_on_close on file failed !\n");
5746 status
= cli_close(cli1
, fnum1
);
5747 if (!NT_STATUS_IS_OK(status
)) {
5748 printf("[8] close - 1 failed (%s)\n", nt_errstr(status
));
5752 status
= cli_close(cli2
, fnum2
);
5753 if (!NT_STATUS_IS_OK(status
)) {
5754 printf("[8] close - 2 failed (%s)\n", nt_errstr(status
));
5758 /* This should fail.. */
5759 status
= cli_openx(cli1
, fname
, O_RDONLY
, DENY_NONE
, &fnum1
);
5760 if (NT_STATUS_IS_OK(status
)) {
5761 printf("[8] open of %s succeeded should have been deleted on close !\n", fname
);
5765 printf("eighth delete on close test succeeded.\n");
5769 /* This should fail - we need to set DELETE_ACCESS. */
5770 status
= cli_ntcreate(cli1
, fname
, 0, FILE_READ_DATA
|FILE_WRITE_DATA
,
5771 FILE_ATTRIBUTE_NORMAL
,
5774 FILE_DELETE_ON_CLOSE
, 0, &fnum1
, NULL
);
5775 if (NT_STATUS_IS_OK(status
)) {
5776 printf("[9] open of %s succeeded should have failed!\n", fname
);
5780 printf("ninth delete on close test succeeded.\n");
5784 status
= cli_ntcreate(cli1
, fname
, 0,
5785 FILE_READ_DATA
|FILE_WRITE_DATA
|DELETE_ACCESS
,
5786 FILE_ATTRIBUTE_NORMAL
, FILE_SHARE_NONE
,
5787 FILE_OVERWRITE_IF
, FILE_DELETE_ON_CLOSE
,
5789 if (!NT_STATUS_IS_OK(status
)) {
5790 printf("[10] open of %s failed (%s)\n", fname
, nt_errstr(status
));
5794 /* This should delete the file. */
5795 status
= cli_close(cli1
, fnum1
);
5796 if (!NT_STATUS_IS_OK(status
)) {
5797 printf("[10] close failed (%s)\n", nt_errstr(status
));
5801 /* This should fail.. */
5802 status
= cli_openx(cli1
, fname
, O_RDONLY
, DENY_NONE
, &fnum1
);
5803 if (NT_STATUS_IS_OK(status
)) {
5804 printf("[10] open of %s succeeded should have been deleted on close !\n", fname
);
5808 printf("tenth delete on close test succeeded.\n");
5812 cli_setatr(cli1
, fname
, 0, 0);
5813 cli_unlink(cli1
, fname
, FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
);
5815 /* Can we open a read-only file with delete access? */
5817 /* Create a readonly file. */
5818 status
= cli_ntcreate(cli1
, fname
, 0, FILE_READ_DATA
|FILE_WRITE_DATA
,
5819 FILE_ATTRIBUTE_READONLY
, FILE_SHARE_NONE
,
5820 FILE_OVERWRITE_IF
, 0, 0, &fnum1
, NULL
);
5821 if (!NT_STATUS_IS_OK(status
)) {
5822 printf("[11] open of %s failed (%s)\n", fname
, nt_errstr(status
));
5826 status
= cli_close(cli1
, fnum1
);
5827 if (!NT_STATUS_IS_OK(status
)) {
5828 printf("[11] close failed (%s)\n", nt_errstr(status
));
5832 /* Now try open for delete access. */
5833 status
= cli_ntcreate(cli1
, fname
, 0,
5834 FILE_READ_ATTRIBUTES
|DELETE_ACCESS
,
5836 FILE_SHARE_READ
|FILE_SHARE_WRITE
|FILE_SHARE_DELETE
,
5837 FILE_OPEN
, 0, 0, &fnum1
, NULL
);
5838 if (!NT_STATUS_IS_OK(status
)) {
5839 printf("[11] open of %s failed: %s\n", fname
, nt_errstr(status
));
5843 cli_close(cli1
, fnum1
);
5845 printf("eleventh delete on close test succeeded.\n");
5849 * like test 4 but with initial delete on close
5852 cli_setatr(cli1
, fname
, 0, 0);
5853 cli_unlink(cli1
, fname
, FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
);
5855 status
= cli_ntcreate(cli1
, fname
, 0,
5856 FILE_READ_DATA
|FILE_WRITE_DATA
|DELETE_ACCESS
,
5857 FILE_ATTRIBUTE_NORMAL
,
5858 FILE_SHARE_READ
|FILE_SHARE_WRITE
,
5860 FILE_DELETE_ON_CLOSE
, 0, &fnum1
, NULL
);
5861 if (!NT_STATUS_IS_OK(status
)) {
5862 printf("[12] open 1 of %s failed (%s)\n", fname
, nt_errstr(status
));
5866 status
= cli_ntcreate(cli1
, fname
, 0, GENERIC_READ_ACCESS
,
5867 FILE_ATTRIBUTE_NORMAL
,
5868 FILE_SHARE_READ
|FILE_SHARE_WRITE
|FILE_SHARE_DELETE
,
5869 FILE_OPEN
, 0, 0, &fnum2
, NULL
);
5870 if (!NT_STATUS_IS_OK(status
)) {
5871 printf("[12] open 2 of %s failed(%s).\n", fname
, nt_errstr(status
));
5875 status
= cli_close(cli1
, fnum2
);
5876 if (!NT_STATUS_IS_OK(status
)) {
5877 printf("[12] close 1 failed (%s)\n", nt_errstr(status
));
5881 status
= cli_nt_delete_on_close(cli1
, fnum1
, true);
5882 if (!NT_STATUS_IS_OK(status
)) {
5883 printf("[12] setting delete_on_close failed (%s)\n", nt_errstr(status
));
5887 /* This should fail - no more opens once delete on close set. */
5888 status
= cli_ntcreate(cli1
, fname
, 0, GENERIC_READ_ACCESS
,
5889 FILE_ATTRIBUTE_NORMAL
,
5890 FILE_SHARE_READ
|FILE_SHARE_WRITE
|FILE_SHARE_DELETE
,
5891 FILE_OPEN
, 0, 0, &fnum2
, NULL
);
5892 if (NT_STATUS_IS_OK(status
)) {
5893 printf("[12] open 3 of %s succeeded - should fail).\n", fname
);
5897 status
= cli_nt_delete_on_close(cli1
, fnum1
, false);
5898 if (!NT_STATUS_IS_OK(status
)) {
5899 printf("[12] unsetting delete_on_close failed (%s)\n", nt_errstr(status
));
5903 status
= cli_ntcreate(cli1
, fname
, 0, GENERIC_READ_ACCESS
,
5904 FILE_ATTRIBUTE_NORMAL
,
5905 FILE_SHARE_READ
|FILE_SHARE_WRITE
|FILE_SHARE_DELETE
,
5906 FILE_OPEN
, 0, 0, &fnum2
, NULL
);
5907 if (!NT_STATUS_IS_OK(status
)) {
5908 printf("[12] open 4 of %s failed (%s)\n", fname
, nt_errstr(status
));
5912 status
= cli_close(cli1
, fnum2
);
5913 if (!NT_STATUS_IS_OK(status
)) {
5914 printf("[12] close 2 failed (%s)\n", nt_errstr(status
));
5918 status
= cli_close(cli1
, fnum1
);
5919 if (!NT_STATUS_IS_OK(status
)) {
5920 printf("[12] close 3 failed (%s)\n", nt_errstr(status
));
5925 * setting delete on close on the handle does
5926 * not unset the initial delete on close...
5928 status
= cli_ntcreate(cli1
, fname
, 0, GENERIC_READ_ACCESS
,
5929 FILE_ATTRIBUTE_NORMAL
,
5930 FILE_SHARE_READ
|FILE_SHARE_WRITE
|FILE_SHARE_DELETE
,
5931 FILE_OPEN
, 0, 0, &fnum2
, NULL
);
5932 if (NT_STATUS_IS_OK(status
)) {
5933 printf("[12] open 5 of %s succeeded - should fail).\n", fname
);
5935 } else if (!NT_STATUS_EQUAL(status
, NT_STATUS_OBJECT_NAME_NOT_FOUND
)) {
5936 printf("ntcreate returned %s, expected "
5937 "NT_STATUS_OBJECT_NAME_NOT_FOUND\n",
5942 printf("twelfth delete on close test succeeded.\n");
5945 printf("finished delete test\n");
5950 /* FIXME: This will crash if we aborted before cli2 got
5951 * initialized, because these functions don't handle
5952 * uninitialized connections. */
5954 if (fnum1
!= (uint16_t)-1) cli_close(cli1
, fnum1
);
5955 if (fnum2
!= (uint16_t)-1) cli_close(cli1
, fnum2
);
5956 cli_setatr(cli1
, fname
, 0, 0);
5957 cli_unlink(cli1
, fname
, FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
);
5959 if (cli1
&& !torture_close_connection(cli1
)) {
5962 if (cli2
&& !torture_close_connection(cli2
)) {
5968 struct delete_stream_state
{
5972 static void delete_stream_unlinked(struct tevent_req
*subreq
);
5973 static void delete_stream_closed(struct tevent_req
*subreq
);
5975 static struct tevent_req
*delete_stream_send(
5976 TALLOC_CTX
*mem_ctx
,
5977 struct tevent_context
*ev
,
5978 struct cli_state
*cli
,
5979 const char *base_fname
,
5980 uint16_t stream_fnum
)
5982 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
5983 struct delete_stream_state
*state
= NULL
;
5985 req
= tevent_req_create(
5986 mem_ctx
, &state
, struct delete_stream_state
);
5991 subreq
= cli_unlink_send(
5996 FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
);
5997 if (tevent_req_nomem(subreq
, req
)) {
5998 return tevent_req_post(req
, ev
);
6000 tevent_req_set_callback(subreq
, delete_stream_unlinked
, req
);
6002 subreq
= cli_close_send(state
, ev
, cli
, stream_fnum
, 0);
6003 if (tevent_req_nomem(subreq
, req
)) {
6004 return tevent_req_post(req
, ev
);
6006 tevent_req_set_callback(subreq
, delete_stream_closed
, req
);
6011 static void delete_stream_unlinked(struct tevent_req
*subreq
)
6013 struct tevent_req
*req
= tevent_req_callback_data(
6014 subreq
, struct tevent_req
);
6015 struct delete_stream_state
*state
= tevent_req_data(
6016 req
, struct delete_stream_state
);
6019 status
= cli_unlink_recv(subreq
);
6020 TALLOC_FREE(subreq
);
6021 if (!NT_STATUS_EQUAL(status
, NT_STATUS_SHARING_VIOLATION
)) {
6022 printf("cli_unlink returned %s\n",
6024 tevent_req_nterror(req
, NT_STATUS_UNSUCCESSFUL
);
6027 if (!state
->closed
) {
6028 /* close reply should have come in first */
6029 printf("Not closed\n");
6030 tevent_req_nterror(req
, NT_STATUS_UNSUCCESSFUL
);
6033 tevent_req_done(req
);
6036 static void delete_stream_closed(struct tevent_req
*subreq
)
6038 struct tevent_req
*req
= tevent_req_callback_data(
6039 subreq
, struct tevent_req
);
6040 struct delete_stream_state
*state
= tevent_req_data(
6041 req
, struct delete_stream_state
);
6044 status
= cli_close_recv(subreq
);
6045 TALLOC_FREE(subreq
);
6046 if (tevent_req_nterror(req
, status
)) {
6049 /* also waiting for the unlink to come back */
6050 state
->closed
= true;
6053 static NTSTATUS
delete_stream_recv(struct tevent_req
*req
)
6055 return tevent_req_simple_recv_ntstatus(req
);
6058 static bool run_delete_stream(int dummy
)
6060 struct tevent_context
*ev
= NULL
;
6061 struct tevent_req
*req
= NULL
;
6062 struct cli_state
*cli
= NULL
;
6063 const char fname
[] = "delete_stream";
6064 const char fname_stream
[] = "delete_stream:Zone.Identifier:$DATA";
6065 uint16_t fnum1
, fnum2
;
6069 printf("Starting stream delete test\n");
6071 ok
= torture_open_connection(&cli
, 0);
6076 cli_setatr(cli
, fname
, 0, 0);
6077 cli_unlink(cli
, fname
, FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
);
6079 /* Create the file. */
6080 status
= cli_ntcreate(
6084 READ_CONTROL_ACCESS
,
6086 FILE_SHARE_READ
|FILE_SHARE_WRITE
|FILE_SHARE_DELETE
,
6092 if (!NT_STATUS_IS_OK(status
)) {
6094 "cli_ntcreate of %s failed (%s)\n",
6099 status
= cli_close(cli
, fnum1
);
6100 if (!NT_STATUS_IS_OK(status
)) {
6102 "cli_close of %s failed (%s)\n",
6108 /* Now create the stream. */
6109 status
= cli_ntcreate(
6115 FILE_SHARE_READ
|FILE_SHARE_WRITE
,
6122 if (!NT_STATUS_IS_OK(status
)) {
6124 "cli_ntcreate of %s failed (%s)\n",
6130 /* open it a second time */
6132 status
= cli_ntcreate(
6138 FILE_SHARE_READ
|FILE_SHARE_WRITE
,
6145 if (!NT_STATUS_IS_OK(status
)) {
6147 "2nd cli_ntcreate of %s failed (%s)\n",
6153 ev
= samba_tevent_context_init(talloc_tos());
6155 d_fprintf(stderr
, "samba_tevent_context_init failed\n");
6159 req
= delete_stream_send(ev
, ev
, cli
, fname
, fnum1
);
6161 d_fprintf(stderr
, "delete_stream_send failed\n");
6165 ok
= tevent_req_poll_ntstatus(req
, ev
, &status
);
6168 "tevent_req_poll_ntstatus failed: %s\n",
6173 status
= delete_stream_recv(req
);
6175 if (!NT_STATUS_IS_OK(status
)) {
6177 "delete_stream failed: %s\n",
6182 status
= cli_close(cli
, fnum2
);
6183 if (!NT_STATUS_IS_OK(status
)) {
6185 "close failed: %s\n",
6190 status
= cli_unlink(
6191 cli
, fname
, FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
);
6192 if (!NT_STATUS_IS_OK(status
)) {
6194 "unlink failed: %s\n",
6203 Exercise delete on close semantics - use on the PRINT1 share in torture
6206 static bool run_delete_print_test(int dummy
)
6208 struct cli_state
*cli1
= NULL
;
6209 const char *fname
= "print_delete.file";
6210 uint16_t fnum1
= (uint16_t)-1;
6211 bool correct
= false;
6212 const char *buf
= "print file data\n";
6215 printf("starting print delete test\n");
6217 if (!torture_open_connection(&cli1
, 0)) {
6221 smbXcli_conn_set_sockopt(cli1
->conn
, sockops
);
6223 status
= cli_ntcreate(cli1
, fname
, 0, GENERIC_ALL_ACCESS
|DELETE_ACCESS
,
6224 FILE_ATTRIBUTE_NORMAL
, 0, FILE_OVERWRITE_IF
,
6225 0, 0, &fnum1
, NULL
);
6226 if (!NT_STATUS_IS_OK(status
)) {
6227 printf("open of %s failed (%s)\n",
6233 status
= cli_writeall(cli1
,
6236 (const uint8_t *)buf
,
6238 strlen(buf
), /* size */
6240 if (!NT_STATUS_IS_OK(status
)) {
6241 printf("writing print file data failed (%s)\n",
6246 status
= cli_nt_delete_on_close(cli1
, fnum1
, true);
6247 if (!NT_STATUS_IS_OK(status
)) {
6248 printf("setting delete_on_close failed (%s)\n",
6253 status
= cli_close(cli1
, fnum1
);
6254 if (!NT_STATUS_IS_OK(status
)) {
6255 printf("close failed (%s)\n", nt_errstr(status
));
6259 printf("finished print delete test\n");
6265 if (fnum1
!= (uint16_t)-1) {
6266 cli_close(cli1
, fnum1
);
6269 if (cli1
&& !torture_close_connection(cli1
)) {
6275 static bool run_deletetest_ln(int dummy
)
6277 struct cli_state
*cli
;
6278 const char *fname
= "\\delete1";
6279 const char *fname_ln
= "\\delete1_ln";
6283 bool correct
= true;
6286 printf("starting deletetest-ln\n");
6288 if (!torture_open_connection(&cli
, 0)) {
6292 cli_unlink(cli
, fname
, FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
);
6293 cli_unlink(cli
, fname_ln
, FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
);
6295 smbXcli_conn_set_sockopt(cli
->conn
, sockops
);
6297 /* Create the file. */
6298 status
= cli_openx(cli
, fname
, O_RDWR
|O_CREAT
|O_EXCL
, DENY_NONE
, &fnum
);
6299 if (!NT_STATUS_IS_OK(status
)) {
6300 printf("open of %s failed (%s)\n", fname
, nt_errstr(status
));
6304 status
= cli_close(cli
, fnum
);
6305 if (!NT_STATUS_IS_OK(status
)) {
6306 printf("close1 failed (%s)\n", nt_errstr(status
));
6310 /* Now create a hardlink. */
6311 status
= cli_hardlink(cli
, fname
, fname_ln
);
6312 if (!NT_STATUS_IS_OK(status
)) {
6313 printf("nt hardlink failed (%s)\n", nt_errstr(status
));
6317 /* Open the original file. */
6318 status
= cli_ntcreate(cli
, fname
, 0, FILE_READ_DATA
,
6319 FILE_ATTRIBUTE_NORMAL
,
6320 FILE_SHARE_READ
|FILE_SHARE_WRITE
|FILE_SHARE_DELETE
,
6321 FILE_OPEN_IF
, 0, 0, &fnum
, NULL
);
6322 if (!NT_STATUS_IS_OK(status
)) {
6323 printf("ntcreate of %s failed (%s)\n", fname
, nt_errstr(status
));
6327 /* Unlink the hard link path. */
6328 status
= cli_ntcreate(cli
, fname_ln
, 0, DELETE_ACCESS
,
6329 FILE_ATTRIBUTE_NORMAL
,
6330 FILE_SHARE_READ
|FILE_SHARE_WRITE
|FILE_SHARE_DELETE
,
6331 FILE_OPEN_IF
, 0, 0, &fnum1
, NULL
);
6332 if (!NT_STATUS_IS_OK(status
)) {
6333 printf("ntcreate of %s failed (%s)\n", fname_ln
, nt_errstr(status
));
6336 status
= cli_nt_delete_on_close(cli
, fnum1
, true);
6337 if (!NT_STATUS_IS_OK(status
)) {
6338 d_printf("(%s) failed to set delete_on_close %s: %s\n",
6339 __location__
, fname_ln
, nt_errstr(status
));
6343 status
= cli_close(cli
, fnum1
);
6344 if (!NT_STATUS_IS_OK(status
)) {
6345 printf("close %s failed (%s)\n",
6346 fname_ln
, nt_errstr(status
));
6350 status
= cli_close(cli
, fnum
);
6351 if (!NT_STATUS_IS_OK(status
)) {
6352 printf("close %s failed (%s)\n",
6353 fname
, nt_errstr(status
));
6357 /* Ensure the original file is still there. */
6358 status
= cli_getatr(cli
, fname
, NULL
, NULL
, &t
);
6359 if (!NT_STATUS_IS_OK(status
)) {
6360 printf("%s getatr on file %s failed (%s)\n",
6367 /* Ensure the link path is gone. */
6368 status
= cli_getatr(cli
, fname_ln
, NULL
, NULL
, &t
);
6369 if (!NT_STATUS_EQUAL(status
, NT_STATUS_OBJECT_NAME_NOT_FOUND
)) {
6370 printf("%s, getatr for file %s returned wrong error code %s "
6371 "- should have been deleted\n",
6373 fname_ln
, nt_errstr(status
));
6377 cli_unlink(cli
, fname
, FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
);
6378 cli_unlink(cli
, fname_ln
, FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
);
6380 if (!torture_close_connection(cli
)) {
6384 printf("finished deletetest-ln\n");
6390 print out server properties
6392 static bool run_properties(int dummy
)
6394 struct cli_state
*cli
;
6395 bool correct
= True
;
6397 printf("starting properties test\n");
6401 if (!torture_open_connection(&cli
, 0)) {
6405 smbXcli_conn_set_sockopt(cli
->conn
, sockops
);
6407 d_printf("Capabilities 0x%08x\n", smb1cli_conn_capabilities(cli
->conn
));
6409 if (!torture_close_connection(cli
)) {
6418 /* FIRST_DESIRED_ACCESS 0xf019f */
6419 #define FIRST_DESIRED_ACCESS FILE_READ_DATA|FILE_WRITE_DATA|FILE_APPEND_DATA|\
6420 FILE_READ_EA| /* 0xf */ \
6421 FILE_WRITE_EA|FILE_READ_ATTRIBUTES| /* 0x90 */ \
6422 FILE_WRITE_ATTRIBUTES| /* 0x100 */ \
6423 DELETE_ACCESS|READ_CONTROL_ACCESS|\
6424 WRITE_DAC_ACCESS|WRITE_OWNER_ACCESS /* 0xf0000 */
6425 /* SECOND_DESIRED_ACCESS 0xe0080 */
6426 #define SECOND_DESIRED_ACCESS FILE_READ_ATTRIBUTES| /* 0x80 */ \
6427 READ_CONTROL_ACCESS|WRITE_DAC_ACCESS|\
6428 WRITE_OWNER_ACCESS /* 0xe0000 */
6431 #define THIRD_DESIRED_ACCESS FILE_READ_ATTRIBUTES| /* 0x80 */ \
6432 READ_CONTROL_ACCESS|WRITE_DAC_ACCESS|\
6434 WRITE_OWNER_ACCESS /* */
6438 Test ntcreate calls made by xcopy
6440 static bool run_xcopy(int dummy
)
6442 static struct cli_state
*cli1
;
6443 const char *fname
= "\\test.txt";
6444 bool correct
= True
;
6445 uint16_t fnum1
, fnum2
;
6448 printf("starting xcopy test\n");
6450 if (!torture_open_connection(&cli1
, 0)) {
6454 status
= cli_ntcreate(cli1
, fname
, 0, FIRST_DESIRED_ACCESS
,
6455 FILE_ATTRIBUTE_ARCHIVE
, FILE_SHARE_NONE
,
6456 FILE_OVERWRITE_IF
, 0x4044, 0, &fnum1
, NULL
);
6457 if (!NT_STATUS_IS_OK(status
)) {
6458 printf("First open failed - %s\n", nt_errstr(status
));
6462 status
= cli_ntcreate(cli1
, fname
, 0, SECOND_DESIRED_ACCESS
, 0,
6463 FILE_SHARE_READ
|FILE_SHARE_WRITE
|FILE_SHARE_DELETE
,
6464 FILE_OPEN
, 0x200000, 0, &fnum2
, NULL
);
6465 if (!NT_STATUS_IS_OK(status
)) {
6466 printf("second open failed - %s\n", nt_errstr(status
));
6470 if (!torture_close_connection(cli1
)) {
6478 Test rename on files open with share delete and no share delete.
6480 static bool run_rename(int dummy
)
6482 static struct cli_state
*cli1
;
6483 const char *fname
= "\\test.txt";
6484 const char *fname1
= "\\test1.txt";
6485 bool correct
= True
;
6490 printf("starting rename test\n");
6492 if (!torture_open_connection(&cli1
, 0)) {
6496 cli_unlink(cli1
, fname
, FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
);
6497 cli_unlink(cli1
, fname1
, FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
);
6499 status
= cli_ntcreate(cli1
, fname
, 0, GENERIC_READ_ACCESS
,
6500 FILE_ATTRIBUTE_NORMAL
, FILE_SHARE_READ
,
6501 FILE_OVERWRITE_IF
, 0, 0, &fnum1
, NULL
);
6502 if (!NT_STATUS_IS_OK(status
)) {
6503 printf("First open failed - %s\n", nt_errstr(status
));
6507 status
= cli_rename(cli1
, fname
, fname1
, false);
6508 if (!NT_STATUS_IS_OK(status
)) {
6509 printf("First rename failed (SHARE_READ) (this is correct) - %s\n", nt_errstr(status
));
6511 printf("First rename succeeded (SHARE_READ) - this should have failed !\n");
6515 status
= cli_close(cli1
, fnum1
);
6516 if (!NT_STATUS_IS_OK(status
)) {
6517 printf("close - 1 failed (%s)\n", nt_errstr(status
));
6521 cli_unlink(cli1
, fname
, FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
);
6522 cli_unlink(cli1
, fname1
, FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
);
6523 status
= cli_ntcreate(cli1
, fname
, 0, GENERIC_READ_ACCESS
, FILE_ATTRIBUTE_NORMAL
,
6525 FILE_SHARE_DELETE
|FILE_SHARE_NONE
,
6527 FILE_SHARE_DELETE
|FILE_SHARE_READ
,
6529 FILE_OVERWRITE_IF
, 0, 0, &fnum1
, NULL
);
6530 if (!NT_STATUS_IS_OK(status
)) {
6531 printf("Second open failed - %s\n", nt_errstr(status
));
6535 status
= cli_rename(cli1
, fname
, fname1
, false);
6536 if (!NT_STATUS_IS_OK(status
)) {
6537 printf("Second rename failed (SHARE_DELETE | SHARE_READ) - this should have succeeded - %s\n", nt_errstr(status
));
6540 printf("Second rename succeeded (SHARE_DELETE | SHARE_READ)\n");
6543 status
= cli_close(cli1
, fnum1
);
6544 if (!NT_STATUS_IS_OK(status
)) {
6545 printf("close - 2 failed (%s)\n", nt_errstr(status
));
6549 cli_unlink(cli1
, fname
, FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
);
6550 cli_unlink(cli1
, fname1
, FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
);
6552 status
= cli_ntcreate(cli1
, fname
, 0, READ_CONTROL_ACCESS
,
6553 FILE_ATTRIBUTE_NORMAL
, FILE_SHARE_NONE
,
6554 FILE_OVERWRITE_IF
, 0, 0, &fnum1
, NULL
);
6555 if (!NT_STATUS_IS_OK(status
)) {
6556 printf("Third open failed - %s\n", nt_errstr(status
));
6561 status
= cli_rename(cli1
, fname
, fname1
, false);
6562 if (!NT_STATUS_IS_OK(status
)) {
6563 printf("Third rename failed (SHARE_NONE) - this should have succeeded - %s\n", nt_errstr(status
));
6566 printf("Third rename succeeded (SHARE_NONE)\n");
6569 status
= cli_close(cli1
, fnum1
);
6570 if (!NT_STATUS_IS_OK(status
)) {
6571 printf("close - 3 failed (%s)\n", nt_errstr(status
));
6575 cli_unlink(cli1
, fname
, FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
);
6576 cli_unlink(cli1
, fname1
, FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
);
6580 status
= cli_ntcreate(cli1
, fname
, 0, GENERIC_READ_ACCESS
,
6581 FILE_ATTRIBUTE_NORMAL
,
6582 FILE_SHARE_READ
| FILE_SHARE_WRITE
,
6583 FILE_OVERWRITE_IF
, 0, 0, &fnum1
, NULL
);
6584 if (!NT_STATUS_IS_OK(status
)) {
6585 printf("Fourth open failed - %s\n", nt_errstr(status
));
6589 status
= cli_rename(cli1
, fname
, fname1
, false);
6590 if (!NT_STATUS_IS_OK(status
)) {
6591 printf("Fourth rename failed (SHARE_READ | SHARE_WRITE) (this is correct) - %s\n", nt_errstr(status
));
6593 printf("Fourth rename succeeded (SHARE_READ | SHARE_WRITE) - this should have failed !\n");
6597 status
= cli_close(cli1
, fnum1
);
6598 if (!NT_STATUS_IS_OK(status
)) {
6599 printf("close - 4 failed (%s)\n", nt_errstr(status
));
6603 cli_unlink(cli1
, fname
, FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
);
6604 cli_unlink(cli1
, fname1
, FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
);
6608 status
= cli_ntcreate(cli1
, fname
, 0, GENERIC_READ_ACCESS
,
6609 FILE_ATTRIBUTE_NORMAL
,
6610 FILE_SHARE_READ
| FILE_SHARE_WRITE
| FILE_SHARE_DELETE
,
6611 FILE_OVERWRITE_IF
, 0, 0, &fnum1
, NULL
);
6612 if (!NT_STATUS_IS_OK(status
)) {
6613 printf("Fifth open failed - %s\n", nt_errstr(status
));
6617 status
= cli_rename(cli1
, fname
, fname1
, false);
6618 if (!NT_STATUS_IS_OK(status
)) {
6619 printf("Fifth rename failed (SHARE_READ | SHARE_WRITE | SHARE_DELETE) - this should have succeeded - %s ! \n", nt_errstr(status
));
6622 printf("Fifth rename succeeded (SHARE_READ | SHARE_WRITE | SHARE_DELETE) (this is correct) - %s\n", nt_errstr(status
));
6626 status
= cli_close(cli1
, fnum1
);
6627 if (!NT_STATUS_IS_OK(status
)) {
6628 printf("close - 5 failed (%s)\n", nt_errstr(status
));
6632 /* Check that the renamed file has FILE_ATTRIBUTE_ARCHIVE. */
6633 status
= cli_getatr(cli1
, fname1
, &attr
, NULL
, NULL
);
6634 if (!NT_STATUS_IS_OK(status
)) {
6635 printf("getatr on file %s failed - %s ! \n",
6636 fname1
, nt_errstr(status
));
6639 if (attr
!= FILE_ATTRIBUTE_ARCHIVE
) {
6640 printf("Renamed file %s has wrong attr 0x%x "
6641 "(should be 0x%x)\n",
6644 (unsigned int)FILE_ATTRIBUTE_ARCHIVE
);
6647 printf("Renamed file %s has archive bit set\n", fname1
);
6651 cli_unlink(cli1
, fname
, FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
);
6652 cli_unlink(cli1
, fname1
, FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
);
6654 if (!torture_close_connection(cli1
)) {
6662 Test rename into a directory with an ACL denying it.
6664 static bool run_rename_access(int dummy
)
6666 static struct cli_state
*cli
= NULL
;
6667 static struct cli_state
*posix_cli
= NULL
;
6668 const char *src
= "test.txt";
6669 const char *dname
= "dir";
6670 const char *dst
= "dir\\test.txt";
6671 const char *dsrc
= "test.dir";
6672 const char *ddst
= "dir\\test.dir";
6673 uint16_t fnum
= (uint16_t)-1;
6674 struct security_descriptor
*sd
= NULL
;
6675 struct security_descriptor
*newsd
= NULL
;
6677 TALLOC_CTX
*frame
= NULL
;
6679 frame
= talloc_stackframe();
6680 printf("starting rename access test\n");
6682 /* Windows connection. */
6683 if (!torture_open_connection(&cli
, 0)) {
6687 smbXcli_conn_set_sockopt(cli
->conn
, sockops
);
6689 /* Posix connection. */
6690 if (!torture_open_connection(&posix_cli
, 0)) {
6694 smbXcli_conn_set_sockopt(posix_cli
->conn
, sockops
);
6696 status
= torture_setup_unix_extensions(posix_cli
);
6697 if (!NT_STATUS_IS_OK(status
)) {
6701 /* Start with a clean slate. */
6702 cli_unlink(cli
, src
, FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
);
6703 cli_unlink(cli
, dst
, FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
);
6704 cli_rmdir(cli
, dsrc
);
6705 cli_rmdir(cli
, ddst
);
6706 cli_rmdir(cli
, dname
);
6709 * Setup the destination directory with a DENY ACE to
6710 * prevent new files within it.
6712 status
= cli_ntcreate(cli
,
6715 FILE_READ_ATTRIBUTES
|READ_CONTROL_ACCESS
|
6716 WRITE_DAC_ACCESS
|FILE_READ_DATA
|
6718 FILE_ATTRIBUTE_DIRECTORY
,
6719 FILE_SHARE_READ
|FILE_SHARE_WRITE
,
6721 FILE_DIRECTORY_FILE
,
6725 if (!NT_STATUS_IS_OK(status
)) {
6726 printf("Create of %s - %s\n", dname
, nt_errstr(status
));
6730 status
= cli_query_secdesc(cli
,
6734 if (!NT_STATUS_IS_OK(status
)) {
6735 printf("cli_query_secdesc failed for %s (%s)\n",
6736 dname
, nt_errstr(status
));
6740 newsd
= security_descriptor_dacl_create(frame
,
6745 SEC_ACE_TYPE_ACCESS_DENIED
,
6746 SEC_DIR_ADD_FILE
|SEC_DIR_ADD_SUBDIR
,
6749 if (newsd
== NULL
) {
6752 sd
->dacl
= security_acl_concatenate(frame
,
6755 if (sd
->dacl
== NULL
) {
6758 status
= cli_set_secdesc(cli
, fnum
, sd
);
6759 if (!NT_STATUS_IS_OK(status
)) {
6760 printf("cli_set_secdesc failed for %s (%s)\n",
6761 dname
, nt_errstr(status
));
6764 status
= cli_close(cli
, fnum
);
6765 if (!NT_STATUS_IS_OK(status
)) {
6766 printf("close failed for %s (%s)\n",
6767 dname
, nt_errstr(status
));
6770 /* Now go around the back and chmod to 777 via POSIX. */
6771 status
= cli_chmod(posix_cli
, dname
, 0777);
6772 if (!NT_STATUS_IS_OK(status
)) {
6773 printf("cli_chmod failed for %s (%s)\n",
6779 /* Check we can't create a file within dname via Windows. */
6780 status
= cli_openx(cli
, dst
, O_RDWR
|O_CREAT
|O_EXCL
, DENY_NONE
, &fnum
);
6781 if (!NT_STATUS_EQUAL(status
, NT_STATUS_ACCESS_DENIED
)) {
6782 cli_close(posix_cli
, fnum
);
6783 printf("Create of %s should be ACCESS denied, was %s\n",
6784 dst
, nt_errstr(status
));
6788 /* Make the sample file/directory. */
6789 status
= cli_openx(cli
, src
, O_RDWR
|O_CREAT
|O_EXCL
, DENY_NONE
, &fnum
);
6790 if (!NT_STATUS_IS_OK(status
)) {
6791 printf("open of %s failed (%s)\n", src
, nt_errstr(status
));
6794 status
= cli_close(cli
, fnum
);
6795 if (!NT_STATUS_IS_OK(status
)) {
6796 printf("cli_close failed (%s)\n", nt_errstr(status
));
6800 status
= cli_mkdir(cli
, dsrc
);
6801 if (!NT_STATUS_IS_OK(status
)) {
6802 printf("cli_mkdir of %s failed (%s)\n",
6803 dsrc
, nt_errstr(status
));
6808 * OK - renames of the new file and directory into the
6809 * dst directory should fail.
6812 status
= cli_rename(cli
, src
, dst
, false);
6813 if (!NT_STATUS_EQUAL(status
, NT_STATUS_ACCESS_DENIED
)) {
6814 printf("rename of %s -> %s should be ACCESS denied, was %s\n",
6815 src
, dst
, nt_errstr(status
));
6818 status
= cli_rename(cli
, dsrc
, ddst
, false);
6819 if (!NT_STATUS_EQUAL(status
, NT_STATUS_ACCESS_DENIED
)) {
6820 printf("rename of %s -> %s should be ACCESS denied, was %s\n",
6821 src
, dst
, nt_errstr(status
));
6831 torture_close_connection(posix_cli
);
6835 if (fnum
!= (uint16_t)-1) {
6836 cli_close(cli
, fnum
);
6838 cli_unlink(cli
, src
,
6839 FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
);
6840 cli_unlink(cli
, dst
,
6841 FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
);
6842 cli_rmdir(cli
, dsrc
);
6843 cli_rmdir(cli
, ddst
);
6844 cli_rmdir(cli
, dname
);
6846 torture_close_connection(cli
);
6854 Test owner rights ACE.
6856 static bool run_owner_rights(int dummy
)
6858 static struct cli_state
*cli
= NULL
;
6859 const char *fname
= "owner_rights.txt";
6860 uint16_t fnum
= (uint16_t)-1;
6861 struct security_descriptor
*sd
= NULL
;
6862 struct security_descriptor
*newsd
= NULL
;
6864 TALLOC_CTX
*frame
= NULL
;
6866 frame
= talloc_stackframe();
6867 printf("starting owner rights test\n");
6869 /* Windows connection. */
6870 if (!torture_open_connection(&cli
, 0)) {
6874 smbXcli_conn_set_sockopt(cli
->conn
, sockops
);
6876 /* Start with a clean slate. */
6877 cli_unlink(cli
, fname
, FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
);
6879 /* Create the test file. */
6880 /* Now try and open for read and write-dac. */
6881 status
= cli_ntcreate(cli
,
6885 FILE_ATTRIBUTE_NORMAL
,
6886 FILE_SHARE_READ
|FILE_SHARE_WRITE
|
6893 if (!NT_STATUS_IS_OK(status
)) {
6894 printf("Create of %s - %s\n", fname
, nt_errstr(status
));
6898 /* Get the original SD. */
6899 status
= cli_query_secdesc(cli
,
6903 if (!NT_STATUS_IS_OK(status
)) {
6904 printf("cli_query_secdesc failed for %s (%s)\n",
6905 fname
, nt_errstr(status
));
6910 * Add an "owner-rights" ACE denying WRITE_DATA,
6911 * and an "owner-rights" ACE allowing READ_DATA.
6914 newsd
= security_descriptor_dacl_create(frame
,
6919 SEC_ACE_TYPE_ACCESS_DENIED
,
6923 SEC_ACE_TYPE_ACCESS_ALLOWED
,
6927 if (newsd
== NULL
) {
6930 sd
->dacl
= security_acl_concatenate(frame
,
6933 if (sd
->dacl
== NULL
) {
6936 status
= cli_set_secdesc(cli
, fnum
, sd
);
6937 if (!NT_STATUS_IS_OK(status
)) {
6938 printf("cli_set_secdesc failed for %s (%s)\n",
6939 fname
, nt_errstr(status
));
6942 status
= cli_close(cli
, fnum
);
6943 if (!NT_STATUS_IS_OK(status
)) {
6944 printf("close failed for %s (%s)\n",
6945 fname
, nt_errstr(status
));
6948 fnum
= (uint16_t)-1;
6950 /* Try and open for FILE_WRITE_DATA */
6951 status
= cli_ntcreate(cli
,
6955 FILE_ATTRIBUTE_NORMAL
,
6956 FILE_SHARE_READ
|FILE_SHARE_WRITE
|
6963 if (!NT_STATUS_EQUAL(status
, NT_STATUS_ACCESS_DENIED
)) {
6964 printf("Open of %s - %s\n", fname
, nt_errstr(status
));
6968 /* Now try and open for FILE_READ_DATA */
6969 status
= cli_ntcreate(cli
,
6973 FILE_ATTRIBUTE_NORMAL
,
6974 FILE_SHARE_READ
|FILE_SHARE_WRITE
|
6981 if (!NT_STATUS_IS_OK(status
)) {
6982 printf("Open of %s - %s\n", fname
, nt_errstr(status
));
6986 status
= cli_close(cli
, fnum
);
6987 if (!NT_STATUS_IS_OK(status
)) {
6988 printf("close failed for %s (%s)\n",
6989 fname
, nt_errstr(status
));
6993 /* Restore clean slate. */
6995 cli_unlink(cli
, fname
, FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
);
6997 /* Create the test file. */
6998 status
= cli_ntcreate(cli
,
7002 FILE_ATTRIBUTE_NORMAL
,
7003 FILE_SHARE_READ
|FILE_SHARE_WRITE
|
7010 if (!NT_STATUS_IS_OK(status
)) {
7011 printf("Create of %s - %s\n", fname
, nt_errstr(status
));
7015 /* Get the original SD. */
7016 status
= cli_query_secdesc(cli
,
7020 if (!NT_STATUS_IS_OK(status
)) {
7021 printf("cli_query_secdesc failed for %s (%s)\n",
7022 fname
, nt_errstr(status
));
7027 * Add an "owner-rights ACE denying WRITE_DATA,
7028 * and an "owner-rights ACE allowing READ_DATA|WRITE_DATA.
7031 newsd
= security_descriptor_dacl_create(frame
,
7036 SEC_ACE_TYPE_ACCESS_DENIED
,
7040 SEC_ACE_TYPE_ACCESS_ALLOWED
,
7041 FILE_READ_DATA
|FILE_WRITE_DATA
,
7044 if (newsd
== NULL
) {
7047 sd
->dacl
= security_acl_concatenate(frame
,
7050 if (sd
->dacl
== NULL
) {
7053 status
= cli_set_secdesc(cli
, fnum
, sd
);
7054 if (!NT_STATUS_IS_OK(status
)) {
7055 printf("cli_set_secdesc failed for %s (%s)\n",
7056 fname
, nt_errstr(status
));
7059 status
= cli_close(cli
, fnum
);
7060 if (!NT_STATUS_IS_OK(status
)) {
7061 printf("close failed for %s (%s)\n",
7062 fname
, nt_errstr(status
));
7065 fnum
= (uint16_t)-1;
7067 /* Try and open for FILE_WRITE_DATA */
7068 status
= cli_ntcreate(cli
,
7072 FILE_ATTRIBUTE_NORMAL
,
7073 FILE_SHARE_READ
|FILE_SHARE_WRITE
|
7080 if (!NT_STATUS_EQUAL(status
, NT_STATUS_ACCESS_DENIED
)) {
7081 printf("Open of %s - %s\n", fname
, nt_errstr(status
));
7085 /* Now try and open for FILE_READ_DATA */
7086 status
= cli_ntcreate(cli
,
7090 FILE_ATTRIBUTE_NORMAL
,
7091 FILE_SHARE_READ
|FILE_SHARE_WRITE
|
7098 if (!NT_STATUS_IS_OK(status
)) {
7099 printf("Open of %s - %s\n", fname
, nt_errstr(status
));
7103 status
= cli_close(cli
, fnum
);
7104 if (!NT_STATUS_IS_OK(status
)) {
7105 printf("close failed for %s (%s)\n",
7106 fname
, nt_errstr(status
));
7110 /* Restore clean slate. */
7112 cli_unlink(cli
, fname
, FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
);
7115 /* Create the test file. */
7116 status
= cli_ntcreate(cli
,
7120 FILE_ATTRIBUTE_NORMAL
,
7121 FILE_SHARE_READ
|FILE_SHARE_WRITE
|
7128 if (!NT_STATUS_IS_OK(status
)) {
7129 printf("Create of %s - %s\n", fname
, nt_errstr(status
));
7133 /* Get the original SD. */
7134 status
= cli_query_secdesc(cli
,
7138 if (!NT_STATUS_IS_OK(status
)) {
7139 printf("cli_query_secdesc failed for %s (%s)\n",
7140 fname
, nt_errstr(status
));
7145 * Add an "authenticated users" ACE allowing READ_DATA,
7146 * add an "owner-rights" denying READ_DATA,
7147 * and an "authenticated users" ACE allowing WRITE_DATA.
7150 newsd
= security_descriptor_dacl_create(frame
,
7154 SID_NT_AUTHENTICATED_USERS
,
7155 SEC_ACE_TYPE_ACCESS_ALLOWED
,
7159 SEC_ACE_TYPE_ACCESS_DENIED
,
7162 SID_NT_AUTHENTICATED_USERS
,
7163 SEC_ACE_TYPE_ACCESS_ALLOWED
,
7167 if (newsd
== NULL
) {
7168 printf("newsd == NULL\n");
7171 sd
->dacl
= security_acl_concatenate(frame
,
7174 if (sd
->dacl
== NULL
) {
7175 printf("sd->dacl == NULL\n");
7178 status
= cli_set_secdesc(cli
, fnum
, sd
);
7179 if (!NT_STATUS_IS_OK(status
)) {
7180 printf("cli_set_secdesc failed for %s (%s)\n",
7181 fname
, nt_errstr(status
));
7184 status
= cli_close(cli
, fnum
);
7185 if (!NT_STATUS_IS_OK(status
)) {
7186 printf("close failed for %s (%s)\n",
7187 fname
, nt_errstr(status
));
7190 fnum
= (uint16_t)-1;
7192 /* Now try and open for FILE_READ_DATA|FILE_WRITE_DATA */
7193 status
= cli_ntcreate(cli
,
7196 FILE_READ_DATA
|FILE_WRITE_DATA
,
7197 FILE_ATTRIBUTE_NORMAL
,
7198 FILE_SHARE_READ
|FILE_SHARE_WRITE
|
7205 if (!NT_STATUS_IS_OK(status
)) {
7206 printf("Open of %s - %s\n", fname
, nt_errstr(status
));
7210 status
= cli_close(cli
, fnum
);
7211 if (!NT_STATUS_IS_OK(status
)) {
7212 printf("close failed for %s (%s)\n",
7213 fname
, nt_errstr(status
));
7217 cli_unlink(cli
, fname
,
7218 FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
);
7226 if (fnum
!= (uint16_t)-1) {
7227 cli_close(cli
, fnum
);
7229 cli_unlink(cli
, fname
,
7230 FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
);
7231 torture_close_connection(cli
);
7239 * Test SMB1-specific open with SEC_FLAG_SYSTEM_SECURITY.
7240 * Note this test only works with a user with SeSecurityPrivilege set.
7242 * NB. This is also tested in samba3.base.createx_access
7243 * but this makes it very explicit what we're looking for.
7245 static bool run_smb1_system_security(int dummy
)
7247 static struct cli_state
*cli
= NULL
;
7248 const char *fname
= "system_security.txt";
7249 uint16_t fnum
= (uint16_t)-1;
7251 TALLOC_CTX
*frame
= NULL
;
7253 frame
= talloc_stackframe();
7254 printf("starting smb1 system security test\n");
7256 /* SMB1 connection - torture_open_connection() forces this. */
7257 if (!torture_open_connection(&cli
, 0)) {
7261 smbXcli_conn_set_sockopt(cli
->conn
, sockops
);
7263 /* Start with a clean slate. */
7264 cli_unlink(cli
, fname
, FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
);
7266 /* Create the test file. */
7267 status
= cli_ntcreate(cli
,
7271 FILE_ATTRIBUTE_NORMAL
,
7272 FILE_SHARE_READ
|FILE_SHARE_WRITE
|
7279 if (!NT_STATUS_IS_OK(status
)) {
7280 printf("Create of %s - %s\n", fname
, nt_errstr(status
));
7284 status
= cli_close(cli
, fnum
);
7286 /* Open with SEC_FLAG_SYSTEM_SECURITY only. */
7288 * On SMB1 this succeeds - SMB2 it fails,
7289 * see the SMB2-SACL test.
7291 status
= cli_ntcreate(cli
,
7294 SEC_FLAG_SYSTEM_SECURITY
,
7295 FILE_ATTRIBUTE_NORMAL
,
7296 FILE_SHARE_READ
|FILE_SHARE_WRITE
|
7303 if (!NT_STATUS_IS_OK(status
)) {
7304 printf("Open of %s - %s\n", fname
, nt_errstr(status
));
7308 status
= cli_close(cli
, fnum
);
7310 cli_unlink(cli
, fname
,
7311 FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
);
7313 torture_close_connection(cli
);
7320 if (fnum
!= (uint16_t)-1) {
7321 cli_close(cli
, fnum
);
7323 cli_unlink(cli
, fname
,
7324 FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
);
7325 torture_close_connection(cli
);
7332 static bool run_pipe_number(int dummy
)
7334 struct cli_state
*cli1
;
7335 const char *pipe_name
= "\\SPOOLSS";
7340 printf("starting pipenumber test\n");
7341 if (!torture_open_connection(&cli1
, 0)) {
7345 smbXcli_conn_set_sockopt(cli1
->conn
, sockops
);
7347 status
= cli_ntcreate(cli1
, pipe_name
, 0, FILE_READ_DATA
,
7348 FILE_ATTRIBUTE_NORMAL
,
7349 FILE_SHARE_READ
|FILE_SHARE_WRITE
,
7350 FILE_OPEN_IF
, 0, 0, &fnum
, NULL
);
7351 if (!NT_STATUS_IS_OK(status
)) {
7352 printf("Open of pipe %s failed with error (%s)\n", pipe_name
, nt_errstr(status
));
7356 printf("\r%6d", num_pipes
);
7359 printf("pipe_number test - we can open %d %s pipes.\n", num_pipes
, pipe_name
);
7360 torture_close_connection(cli1
);
7365 Test open mode returns on read-only files.
7367 static bool run_opentest(int dummy
)
7369 static struct cli_state
*cli1
;
7370 static struct cli_state
*cli2
;
7371 const char *fname
= "\\readonly.file";
7372 uint16_t fnum1
, fnum2
;
7375 bool correct
= True
;
7379 printf("starting open test\n");
7381 if (!torture_open_connection(&cli1
, 0)) {
7385 cli_setatr(cli1
, fname
, 0, 0);
7386 cli_unlink(cli1
, fname
, FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
);
7388 smbXcli_conn_set_sockopt(cli1
->conn
, sockops
);
7390 status
= cli_openx(cli1
, fname
, O_RDWR
|O_CREAT
|O_EXCL
, DENY_NONE
, &fnum1
);
7391 if (!NT_STATUS_IS_OK(status
)) {
7392 printf("open of %s failed (%s)\n", fname
, nt_errstr(status
));
7396 status
= cli_close(cli1
, fnum1
);
7397 if (!NT_STATUS_IS_OK(status
)) {
7398 printf("close2 failed (%s)\n", nt_errstr(status
));
7402 status
= cli_setatr(cli1
, fname
, FILE_ATTRIBUTE_READONLY
, 0);
7403 if (!NT_STATUS_IS_OK(status
)) {
7404 printf("cli_setatr failed (%s)\n", nt_errstr(status
));
7408 status
= cli_openx(cli1
, fname
, O_RDONLY
, DENY_WRITE
, &fnum1
);
7409 if (!NT_STATUS_IS_OK(status
)) {
7410 printf("open of %s failed (%s)\n", fname
, nt_errstr(status
));
7414 /* This will fail - but the error should be ERRnoaccess, not ERRbadshare. */
7415 status
= cli_openx(cli1
, fname
, O_RDWR
, DENY_ALL
, &fnum2
);
7417 if (check_error(__LINE__
, status
, ERRDOS
, ERRnoaccess
,
7418 NT_STATUS_ACCESS_DENIED
)) {
7419 printf("correct error code ERRDOS/ERRnoaccess returned\n");
7422 printf("finished open test 1\n");
7424 cli_close(cli1
, fnum1
);
7426 /* Now try not readonly and ensure ERRbadshare is returned. */
7428 cli_setatr(cli1
, fname
, 0, 0);
7430 status
= cli_openx(cli1
, fname
, O_RDONLY
, DENY_WRITE
, &fnum1
);
7431 if (!NT_STATUS_IS_OK(status
)) {
7432 printf("open of %s failed (%s)\n", fname
, nt_errstr(status
));
7436 /* This will fail - but the error should be ERRshare. */
7437 status
= cli_openx(cli1
, fname
, O_RDWR
, DENY_ALL
, &fnum2
);
7439 if (check_error(__LINE__
, status
, ERRDOS
, ERRbadshare
,
7440 NT_STATUS_SHARING_VIOLATION
)) {
7441 printf("correct error code ERRDOS/ERRbadshare returned\n");
7444 status
= cli_close(cli1
, fnum1
);
7445 if (!NT_STATUS_IS_OK(status
)) {
7446 printf("close2 failed (%s)\n", nt_errstr(status
));
7450 cli_unlink(cli1
, fname
, FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
);
7452 printf("finished open test 2\n");
7454 /* Test truncate open disposition on file opened for read. */
7455 status
= cli_openx(cli1
, fname
, O_RDWR
|O_CREAT
|O_EXCL
, DENY_NONE
, &fnum1
);
7456 if (!NT_STATUS_IS_OK(status
)) {
7457 printf("(3) open (1) of %s failed (%s)\n", fname
, nt_errstr(status
));
7461 /* write 20 bytes. */
7463 memset(buf
, '\0', 20);
7465 status
= cli_writeall(cli1
, fnum1
, 0, (uint8_t *)buf
, 0, 20, NULL
);
7466 if (!NT_STATUS_IS_OK(status
)) {
7467 printf("write failed (%s)\n", nt_errstr(status
));
7471 status
= cli_close(cli1
, fnum1
);
7472 if (!NT_STATUS_IS_OK(status
)) {
7473 printf("(3) close1 failed (%s)\n", nt_errstr(status
));
7477 /* Ensure size == 20. */
7478 status
= cli_getatr(cli1
, fname
, NULL
, &fsize
, NULL
);
7479 if (!NT_STATUS_IS_OK(status
)) {
7480 printf("(3) getatr failed (%s)\n", nt_errstr(status
));
7485 printf("(3) file size != 20\n");
7489 /* Now test if we can truncate a file opened for readonly. */
7490 status
= cli_openx(cli1
, fname
, O_RDONLY
|O_TRUNC
, DENY_NONE
, &fnum1
);
7491 if (!NT_STATUS_IS_OK(status
)) {
7492 printf("(3) open (2) of %s failed (%s)\n", fname
, nt_errstr(status
));
7496 status
= cli_close(cli1
, fnum1
);
7497 if (!NT_STATUS_IS_OK(status
)) {
7498 printf("close2 failed (%s)\n", nt_errstr(status
));
7502 /* Ensure size == 0. */
7503 status
= cli_getatr(cli1
, fname
, NULL
, &fsize
, NULL
);
7504 if (!NT_STATUS_IS_OK(status
)) {
7505 printf("(3) getatr failed (%s)\n", nt_errstr(status
));
7510 printf("(3) file size != 0\n");
7513 printf("finished open test 3\n");
7515 cli_unlink(cli1
, fname
, FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
);
7517 printf("Do ctemp tests\n");
7518 status
= cli_ctemp(cli1
, talloc_tos(), "\\", &fnum1
, &tmp_path
);
7519 if (!NT_STATUS_IS_OK(status
)) {
7520 printf("ctemp failed (%s)\n", nt_errstr(status
));
7524 printf("ctemp gave path %s\n", tmp_path
);
7525 status
= cli_close(cli1
, fnum1
);
7526 if (!NT_STATUS_IS_OK(status
)) {
7527 printf("close of temp failed (%s)\n", nt_errstr(status
));
7530 status
= cli_unlink(cli1
, tmp_path
, FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
);
7531 if (!NT_STATUS_IS_OK(status
)) {
7532 printf("unlink of temp failed (%s)\n", nt_errstr(status
));
7535 /* Test the non-io opens... */
7537 if (!torture_open_connection(&cli2
, 1)) {
7541 cli_setatr(cli2
, fname
, 0, 0);
7542 cli_unlink(cli2
, fname
, FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
);
7544 smbXcli_conn_set_sockopt(cli2
->conn
, sockops
);
7546 printf("TEST #1 testing 2 non-io opens (no delete)\n");
7547 status
= cli_ntcreate(cli1
, fname
, 0, FILE_READ_ATTRIBUTES
,
7548 FILE_ATTRIBUTE_NORMAL
, FILE_SHARE_NONE
,
7549 FILE_OVERWRITE_IF
, 0, 0, &fnum1
, NULL
);
7550 if (!NT_STATUS_IS_OK(status
)) {
7551 printf("TEST #1 open 1 of %s failed (%s)\n", fname
, nt_errstr(status
));
7555 status
= cli_ntcreate(cli2
, fname
, 0, FILE_READ_ATTRIBUTES
,
7556 FILE_ATTRIBUTE_NORMAL
, FILE_SHARE_NONE
,
7557 FILE_OPEN_IF
, 0, 0, &fnum2
, NULL
);
7558 if (!NT_STATUS_IS_OK(status
)) {
7559 printf("TEST #1 open 2 of %s failed (%s)\n", fname
, nt_errstr(status
));
7563 status
= cli_close(cli1
, fnum1
);
7564 if (!NT_STATUS_IS_OK(status
)) {
7565 printf("TEST #1 close 1 of %s failed (%s)\n", fname
, nt_errstr(status
));
7569 status
= cli_close(cli2
, fnum2
);
7570 if (!NT_STATUS_IS_OK(status
)) {
7571 printf("TEST #1 close 2 of %s failed (%s)\n", fname
, nt_errstr(status
));
7575 printf("non-io open test #1 passed.\n");
7577 cli_unlink(cli1
, fname
, FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
);
7579 printf("TEST #2 testing 2 non-io opens (first with delete)\n");
7581 status
= cli_ntcreate(cli1
, fname
, 0,
7582 DELETE_ACCESS
|FILE_READ_ATTRIBUTES
,
7583 FILE_ATTRIBUTE_NORMAL
, FILE_SHARE_NONE
,
7584 FILE_OVERWRITE_IF
, 0, 0, &fnum1
, NULL
);
7585 if (!NT_STATUS_IS_OK(status
)) {
7586 printf("TEST #2 open 1 of %s failed (%s)\n", fname
, nt_errstr(status
));
7590 status
= cli_ntcreate(cli2
, fname
, 0, FILE_READ_ATTRIBUTES
,
7591 FILE_ATTRIBUTE_NORMAL
, FILE_SHARE_NONE
,
7592 FILE_OPEN_IF
, 0, 0, &fnum2
, NULL
);
7593 if (!NT_STATUS_IS_OK(status
)) {
7594 printf("TEST #2 open 2 of %s failed (%s)\n", fname
, nt_errstr(status
));
7598 status
= cli_close(cli1
, fnum1
);
7599 if (!NT_STATUS_IS_OK(status
)) {
7600 printf("TEST #2 close 1 of %s failed (%s)\n", fname
, nt_errstr(status
));
7604 status
= cli_close(cli2
, fnum2
);
7605 if (!NT_STATUS_IS_OK(status
)) {
7606 printf("TEST #2 close 2 of %s failed (%s)\n", fname
, nt_errstr(status
));
7610 printf("non-io open test #2 passed.\n");
7612 cli_unlink(cli1
, fname
, FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
);
7614 printf("TEST #3 testing 2 non-io opens (second with delete)\n");
7616 status
= cli_ntcreate(cli1
, fname
, 0, FILE_READ_ATTRIBUTES
,
7617 FILE_ATTRIBUTE_NORMAL
, FILE_SHARE_NONE
,
7618 FILE_OVERWRITE_IF
, 0, 0, &fnum1
, NULL
);
7619 if (!NT_STATUS_IS_OK(status
)) {
7620 printf("TEST #3 open 1 of %s failed (%s)\n", fname
, nt_errstr(status
));
7624 status
= cli_ntcreate(cli2
, fname
, 0,
7625 DELETE_ACCESS
|FILE_READ_ATTRIBUTES
,
7626 FILE_ATTRIBUTE_NORMAL
, FILE_SHARE_NONE
,
7627 FILE_OPEN_IF
, 0, 0, &fnum2
, NULL
);
7628 if (!NT_STATUS_IS_OK(status
)) {
7629 printf("TEST #3 open 2 of %s failed (%s)\n", fname
, nt_errstr(status
));
7633 status
= cli_close(cli1
, fnum1
);
7634 if (!NT_STATUS_IS_OK(status
)) {
7635 printf("TEST #3 close 1 of %s failed (%s)\n", fname
, nt_errstr(status
));
7639 status
= cli_close(cli2
, fnum2
);
7640 if (!NT_STATUS_IS_OK(status
)) {
7641 printf("TEST #3 close 2 of %s failed (%s)\n", fname
, nt_errstr(status
));
7645 printf("non-io open test #3 passed.\n");
7647 cli_unlink(cli1
, fname
, FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
);
7649 printf("TEST #4 testing 2 non-io opens (both with delete)\n");
7651 status
= cli_ntcreate(cli1
, fname
, 0,
7652 DELETE_ACCESS
|FILE_READ_ATTRIBUTES
,
7653 FILE_ATTRIBUTE_NORMAL
, FILE_SHARE_NONE
,
7654 FILE_OVERWRITE_IF
, 0, 0, &fnum1
, NULL
);
7655 if (!NT_STATUS_IS_OK(status
)) {
7656 printf("TEST #4 open 1 of %s failed (%s)\n", fname
, nt_errstr(status
));
7660 status
= cli_ntcreate(cli2
, fname
, 0,
7661 DELETE_ACCESS
|FILE_READ_ATTRIBUTES
,
7662 FILE_ATTRIBUTE_NORMAL
, FILE_SHARE_NONE
,
7663 FILE_OPEN_IF
, 0, 0, &fnum2
, NULL
);
7664 if (NT_STATUS_IS_OK(status
)) {
7665 printf("TEST #4 open 2 of %s SUCCEEDED - should have failed (%s)\n", fname
, nt_errstr(status
));
7669 printf("TEST #4 open 2 of %s gave %s (correct error should be %s)\n", fname
, nt_errstr(status
), "sharing violation");
7671 status
= cli_close(cli1
, fnum1
);
7672 if (!NT_STATUS_IS_OK(status
)) {
7673 printf("TEST #4 close 1 of %s failed (%s)\n", fname
, nt_errstr(status
));
7677 printf("non-io open test #4 passed.\n");
7679 cli_unlink(cli1
, fname
, FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
);
7681 printf("TEST #5 testing 2 non-io opens (both with delete - both with file share delete)\n");
7683 status
= cli_ntcreate(cli1
, fname
, 0,
7684 DELETE_ACCESS
|FILE_READ_ATTRIBUTES
,
7685 FILE_ATTRIBUTE_NORMAL
, FILE_SHARE_DELETE
,
7686 FILE_OVERWRITE_IF
, 0, 0, &fnum1
, NULL
);
7687 if (!NT_STATUS_IS_OK(status
)) {
7688 printf("TEST #5 open 1 of %s failed (%s)\n", fname
, nt_errstr(status
));
7692 status
= cli_ntcreate(cli2
, fname
, 0,
7693 DELETE_ACCESS
|FILE_READ_ATTRIBUTES
,
7694 FILE_ATTRIBUTE_NORMAL
, FILE_SHARE_DELETE
,
7695 FILE_OPEN_IF
, 0, 0, &fnum2
, NULL
);
7696 if (!NT_STATUS_IS_OK(status
)) {
7697 printf("TEST #5 open 2 of %s failed (%s)\n", fname
, nt_errstr(status
));
7701 status
= cli_close(cli1
, fnum1
);
7702 if (!NT_STATUS_IS_OK(status
)) {
7703 printf("TEST #5 close 1 of %s failed (%s)\n", fname
, nt_errstr(status
));
7707 status
= cli_close(cli2
, fnum2
);
7708 if (!NT_STATUS_IS_OK(status
)) {
7709 printf("TEST #5 close 2 of %s failed (%s)\n", fname
, nt_errstr(status
));
7713 printf("non-io open test #5 passed.\n");
7715 printf("TEST #6 testing 1 non-io open, one io open\n");
7717 cli_unlink(cli1
, fname
, FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
);
7719 status
= cli_ntcreate(cli1
, fname
, 0, FILE_READ_DATA
,
7720 FILE_ATTRIBUTE_NORMAL
, FILE_SHARE_NONE
,
7721 FILE_OVERWRITE_IF
, 0, 0, &fnum1
, NULL
);
7722 if (!NT_STATUS_IS_OK(status
)) {
7723 printf("TEST #6 open 1 of %s failed (%s)\n", fname
, nt_errstr(status
));
7727 status
= cli_ntcreate(cli2
, fname
, 0, FILE_READ_ATTRIBUTES
,
7728 FILE_ATTRIBUTE_NORMAL
, FILE_SHARE_READ
,
7729 FILE_OPEN_IF
, 0, 0, &fnum2
, NULL
);
7730 if (!NT_STATUS_IS_OK(status
)) {
7731 printf("TEST #6 open 2 of %s failed (%s)\n", fname
, nt_errstr(status
));
7735 status
= cli_close(cli1
, fnum1
);
7736 if (!NT_STATUS_IS_OK(status
)) {
7737 printf("TEST #6 close 1 of %s failed (%s)\n", fname
, nt_errstr(status
));
7741 status
= cli_close(cli2
, fnum2
);
7742 if (!NT_STATUS_IS_OK(status
)) {
7743 printf("TEST #6 close 2 of %s failed (%s)\n", fname
, nt_errstr(status
));
7747 printf("non-io open test #6 passed.\n");
7749 printf("TEST #7 testing 1 non-io open, one io open with delete\n");
7751 cli_unlink(cli1
, fname
, FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
);
7753 status
= cli_ntcreate(cli1
, fname
, 0, FILE_READ_DATA
,
7754 FILE_ATTRIBUTE_NORMAL
, FILE_SHARE_NONE
,
7755 FILE_OVERWRITE_IF
, 0, 0, &fnum1
, NULL
);
7756 if (!NT_STATUS_IS_OK(status
)) {
7757 printf("TEST #7 open 1 of %s failed (%s)\n", fname
, nt_errstr(status
));
7761 status
= cli_ntcreate(cli2
, fname
, 0,
7762 DELETE_ACCESS
|FILE_READ_ATTRIBUTES
,
7763 FILE_ATTRIBUTE_NORMAL
,
7764 FILE_SHARE_READ
|FILE_SHARE_DELETE
,
7765 FILE_OPEN_IF
, 0, 0, &fnum2
, NULL
);
7766 if (NT_STATUS_IS_OK(status
)) {
7767 printf("TEST #7 open 2 of %s SUCCEEDED - should have failed (%s)\n", fname
, nt_errstr(status
));
7771 printf("TEST #7 open 2 of %s gave %s (correct error should be %s)\n", fname
, nt_errstr(status
), "sharing violation");
7773 status
= cli_close(cli1
, fnum1
);
7774 if (!NT_STATUS_IS_OK(status
)) {
7775 printf("TEST #7 close 1 of %s failed (%s)\n", fname
, nt_errstr(status
));
7779 printf("non-io open test #7 passed.\n");
7781 cli_unlink(cli1
, fname
, FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
);
7783 printf("TEST #8 testing open without WRITE_ATTRIBUTES, updating close write time.\n");
7784 status
= cli_ntcreate(cli1
, fname
, 0, FILE_WRITE_DATA
, FILE_ATTRIBUTE_NORMAL
,
7785 FILE_SHARE_READ
|FILE_SHARE_WRITE
|FILE_SHARE_DELETE
,
7786 FILE_OVERWRITE_IF
, 0, 0, &fnum1
, NULL
);
7787 if (!NT_STATUS_IS_OK(status
)) {
7788 printf("TEST #8 open of %s failed (%s)\n", fname
, nt_errstr(status
));
7793 /* Write to ensure we have to update the file time. */
7794 status
= cli_writeall(cli1
, fnum1
, 0, (const uint8_t *)"TEST DATA\n", 0, 10,
7796 if (!NT_STATUS_IS_OK(status
)) {
7797 printf("TEST #8 cli_write failed: %s\n", nt_errstr(status
));
7802 status
= cli_close(cli1
, fnum1
);
7803 if (!NT_STATUS_IS_OK(status
)) {
7804 printf("TEST #8 close of %s failed (%s)\n", fname
, nt_errstr(status
));
7810 if (!torture_close_connection(cli1
)) {
7813 if (!torture_close_connection(cli2
)) {
7820 NTSTATUS
torture_setup_unix_extensions(struct cli_state
*cli
)
7822 uint16_t major
, minor
;
7823 uint32_t caplow
, caphigh
;
7826 if (!SERVER_HAS_UNIX_CIFS(cli
)) {
7827 printf("Server doesn't support UNIX CIFS extensions.\n");
7828 return NT_STATUS_NOT_SUPPORTED
;
7831 status
= cli_unix_extensions_version(cli
, &major
, &minor
, &caplow
,
7833 if (!NT_STATUS_IS_OK(status
)) {
7834 printf("Server didn't return UNIX CIFS extensions: %s\n",
7839 status
= cli_set_unix_extensions_capabilities(cli
, major
, minor
,
7841 if (!NT_STATUS_IS_OK(status
)) {
7842 printf("Server doesn't support setting UNIX CIFS extensions: "
7843 "%s.\n", nt_errstr(status
));
7847 return NT_STATUS_OK
;
7851 Test POSIX open /mkdir calls.
7853 static bool run_simple_posix_open_test(int dummy
)
7855 static struct cli_state
*cli1
;
7856 const char *fname
= "posix:file";
7857 const char *hname
= "posix:hlink";
7858 const char *sname
= "posix:symlink";
7859 const char *dname
= "posix:dir";
7861 char *target
= NULL
;
7862 uint16_t fnum1
= (uint16_t)-1;
7863 SMB_STRUCT_STAT sbuf
;
7864 bool correct
= false;
7867 const char *fname_windows
= "windows_file";
7868 uint16_t fnum2
= (uint16_t)-1;
7871 printf("Starting simple POSIX open test\n");
7873 if (!torture_open_connection(&cli1
, 0)) {
7877 smbXcli_conn_set_sockopt(cli1
->conn
, sockops
);
7879 status
= torture_setup_unix_extensions(cli1
);
7880 if (!NT_STATUS_IS_OK(status
)) {
7884 cli_setatr(cli1
, fname
, 0, 0);
7885 cli_posix_unlink(cli1
, fname
);
7886 cli_setatr(cli1
, dname
, 0, 0);
7887 cli_posix_rmdir(cli1
, dname
);
7888 cli_setatr(cli1
, hname
, 0, 0);
7889 cli_posix_unlink(cli1
, hname
);
7890 cli_setatr(cli1
, sname
, 0, 0);
7891 cli_posix_unlink(cli1
, sname
);
7892 cli_setatr(cli1
, fname_windows
, 0, 0);
7893 cli_posix_unlink(cli1
, fname_windows
);
7895 /* Create a directory. */
7896 status
= cli_posix_mkdir(cli1
, dname
, 0777);
7897 if (!NT_STATUS_IS_OK(status
)) {
7898 printf("POSIX mkdir of %s failed (%s)\n", dname
, nt_errstr(status
));
7902 status
= cli_posix_open(cli1
, fname
, O_RDWR
|O_CREAT
|O_EXCL
,
7904 if (!NT_STATUS_IS_OK(status
)) {
7905 printf("POSIX create of %s failed (%s)\n", fname
, nt_errstr(status
));
7909 /* Test ftruncate - set file size. */
7910 status
= cli_ftruncate(cli1
, fnum1
, 1000);
7911 if (!NT_STATUS_IS_OK(status
)) {
7912 printf("ftruncate failed (%s)\n", nt_errstr(status
));
7916 /* Ensure st_size == 1000 */
7917 status
= cli_posix_stat(cli1
, fname
, &sbuf
);
7918 if (!NT_STATUS_IS_OK(status
)) {
7919 printf("stat failed (%s)\n", nt_errstr(status
));
7923 if (sbuf
.st_ex_size
!= 1000) {
7924 printf("ftruncate - stat size (%u) != 1000\n", (unsigned int)sbuf
.st_ex_size
);
7928 /* Ensure st_mode == 0600 */
7929 if ((sbuf
.st_ex_mode
& 07777) != 0600) {
7930 printf("posix_open - bad permissions 0%o != 0600\n",
7931 (unsigned int)(sbuf
.st_ex_mode
& 07777));
7935 /* Test ftruncate - set file size back to zero. */
7936 status
= cli_ftruncate(cli1
, fnum1
, 0);
7937 if (!NT_STATUS_IS_OK(status
)) {
7938 printf("ftruncate failed (%s)\n", nt_errstr(status
));
7942 status
= cli_close(cli1
, fnum1
);
7943 if (!NT_STATUS_IS_OK(status
)) {
7944 printf("close failed (%s)\n", nt_errstr(status
));
7948 /* Now open the file again for read only. */
7949 status
= cli_posix_open(cli1
, fname
, O_RDONLY
, 0, &fnum1
);
7950 if (!NT_STATUS_IS_OK(status
)) {
7951 printf("POSIX open of %s failed (%s)\n", fname
, nt_errstr(status
));
7955 /* Now unlink while open. */
7956 status
= cli_posix_unlink(cli1
, fname
);
7957 if (!NT_STATUS_IS_OK(status
)) {
7958 printf("POSIX unlink of %s failed (%s)\n", fname
, nt_errstr(status
));
7962 status
= cli_close(cli1
, fnum1
);
7963 if (!NT_STATUS_IS_OK(status
)) {
7964 printf("close(2) failed (%s)\n", nt_errstr(status
));
7968 /* Ensure the file has gone. */
7969 status
= cli_posix_open(cli1
, fname
, O_RDONLY
, 0, &fnum1
);
7970 if (NT_STATUS_IS_OK(status
)) {
7971 printf("POSIX open of %s succeeded, should have been deleted.\n", fname
);
7975 /* Create again to test open with O_TRUNC. */
7976 status
= cli_posix_open(cli1
, fname
, O_RDWR
|O_CREAT
|O_EXCL
, 0600, &fnum1
);
7977 if (!NT_STATUS_IS_OK(status
)) {
7978 printf("POSIX create of %s failed (%s)\n", fname
, nt_errstr(status
));
7982 /* Test ftruncate - set file size. */
7983 status
= cli_ftruncate(cli1
, fnum1
, 1000);
7984 if (!NT_STATUS_IS_OK(status
)) {
7985 printf("ftruncate failed (%s)\n", nt_errstr(status
));
7989 /* Ensure st_size == 1000 */
7990 status
= cli_posix_stat(cli1
, fname
, &sbuf
);
7991 if (!NT_STATUS_IS_OK(status
)) {
7992 printf("stat failed (%s)\n", nt_errstr(status
));
7996 if (sbuf
.st_ex_size
!= 1000) {
7997 printf("ftruncate - stat size (%u) != 1000\n", (unsigned int)sbuf
.st_ex_size
);
8001 status
= cli_close(cli1
, fnum1
);
8002 if (!NT_STATUS_IS_OK(status
)) {
8003 printf("close(2) failed (%s)\n", nt_errstr(status
));
8007 /* Re-open with O_TRUNC. */
8008 status
= cli_posix_open(cli1
, fname
, O_WRONLY
|O_TRUNC
, 0600, &fnum1
);
8009 if (!NT_STATUS_IS_OK(status
)) {
8010 printf("POSIX create of %s failed (%s)\n", fname
, nt_errstr(status
));
8014 /* Ensure st_size == 0 */
8015 status
= cli_posix_stat(cli1
, fname
, &sbuf
);
8016 if (!NT_STATUS_IS_OK(status
)) {
8017 printf("stat failed (%s)\n", nt_errstr(status
));
8021 if (sbuf
.st_ex_size
!= 0) {
8022 printf("O_TRUNC - stat size (%u) != 0\n", (unsigned int)sbuf
.st_ex_size
);
8026 status
= cli_close(cli1
, fnum1
);
8027 if (!NT_STATUS_IS_OK(status
)) {
8028 printf("close failed (%s)\n", nt_errstr(status
));
8032 status
= cli_posix_unlink(cli1
, fname
);
8033 if (!NT_STATUS_IS_OK(status
)) {
8034 printf("POSIX unlink of %s failed (%s)\n", fname
, nt_errstr(status
));
8038 status
= cli_posix_open(cli1
, dname
, O_RDONLY
, 0, &fnum1
);
8039 if (!NT_STATUS_IS_OK(status
)) {
8040 printf("POSIX open directory O_RDONLY of %s failed (%s)\n",
8041 dname
, nt_errstr(status
));
8045 cli_close(cli1
, fnum1
);
8047 /* What happens when we try and POSIX open a directory for write ? */
8048 status
= cli_posix_open(cli1
, dname
, O_RDWR
, 0, &fnum1
);
8049 if (NT_STATUS_IS_OK(status
)) {
8050 printf("POSIX open of directory %s succeeded, "
8051 "should have failed.\n",
8055 if (!check_both_error(__LINE__
, status
, ERRDOS
, EISDIR
,
8056 NT_STATUS_FILE_IS_A_DIRECTORY
)) {
8061 /* Create the file. */
8062 status
= cli_posix_open(cli1
, fname
, O_RDWR
|O_CREAT
|O_EXCL
,
8064 if (!NT_STATUS_IS_OK(status
)) {
8065 printf("POSIX create of %s failed (%s)\n", fname
, nt_errstr(status
));
8069 /* Write some data into it. */
8070 status
= cli_writeall(cli1
, fnum1
, 0, (const uint8_t *)"TEST DATA\n", 0, 10,
8072 if (!NT_STATUS_IS_OK(status
)) {
8073 printf("cli_write failed: %s\n", nt_errstr(status
));
8077 cli_close(cli1
, fnum1
);
8079 /* Now create a hardlink. */
8080 status
= cli_posix_hardlink(cli1
, fname
, hname
);
8081 if (!NT_STATUS_IS_OK(status
)) {
8082 printf("POSIX hardlink of %s failed (%s)\n", hname
, nt_errstr(status
));
8086 /* Now create a symlink. */
8087 status
= cli_posix_symlink(cli1
, fname
, sname
);
8088 if (!NT_STATUS_IS_OK(status
)) {
8089 printf("POSIX symlink of %s failed (%s)\n", sname
, nt_errstr(status
));
8093 /* Open the hardlink for read. */
8094 status
= cli_posix_open(cli1
, hname
, O_RDONLY
, 0, &fnum1
);
8095 if (!NT_STATUS_IS_OK(status
)) {
8096 printf("POSIX open of %s failed (%s)\n", hname
, nt_errstr(status
));
8100 status
= cli_read(cli1
, fnum1
, buf
, 0, 10, &nread
);
8101 if (!NT_STATUS_IS_OK(status
)) {
8102 printf("POSIX read of %s failed (%s)\n", hname
,
8105 } else if (nread
!= 10) {
8106 printf("POSIX read of %s failed. Received %ld, expected %d\n",
8107 hname
, (unsigned long)nread
, 10);
8111 if (memcmp(buf
, "TEST DATA\n", 10)) {
8112 printf("invalid data read from hardlink\n");
8116 /* Do a POSIX lock/unlock. */
8117 status
= cli_posix_lock(cli1
, fnum1
, 0, 100, true, READ_LOCK
);
8118 if (!NT_STATUS_IS_OK(status
)) {
8119 printf("POSIX lock failed %s\n", nt_errstr(status
));
8123 /* Punch a hole in the locked area. */
8124 status
= cli_posix_unlock(cli1
, fnum1
, 10, 80);
8125 if (!NT_STATUS_IS_OK(status
)) {
8126 printf("POSIX unlock failed %s\n", nt_errstr(status
));
8130 cli_close(cli1
, fnum1
);
8132 /* Open the symlink for read - this should fail. A POSIX
8133 client should not be doing opens on a symlink. */
8134 status
= cli_posix_open(cli1
, sname
, O_RDONLY
, 0, &fnum1
);
8135 if (NT_STATUS_IS_OK(status
)) {
8136 printf("POSIX open of %s succeeded (should have failed)\n", sname
);
8139 ok
= check_both_error(
8140 __LINE__
, status
, ERRDOS
, ERRbadpath
,
8141 NT_STATUS_OBJECT_NAME_NOT_FOUND
);
8143 printf("POSIX open of %s should have failed "
8144 "with NT_STATUS_OBJECT_NAME_NOT_FOUND, "
8145 "failed with %s instead.\n",
8146 sname
, nt_errstr(status
));
8150 status
= cli_readlink(cli1
, sname
, talloc_tos(), &target
, NULL
, NULL
);
8151 if (!NT_STATUS_IS_OK(status
)) {
8152 printf("POSIX readlink on %s failed (%s)\n", sname
, nt_errstr(status
));
8156 if (strcmp(target
, fname
) != 0) {
8157 printf("POSIX readlink on %s failed to match name %s (read %s)\n",
8158 sname
, fname
, target
);
8162 status
= cli_posix_rmdir(cli1
, dname
);
8163 if (!NT_STATUS_IS_OK(status
)) {
8164 printf("POSIX rmdir failed (%s)\n", nt_errstr(status
));
8168 /* Check directory opens with a specific permission. */
8169 status
= cli_posix_mkdir(cli1
, dname
, 0700);
8170 if (!NT_STATUS_IS_OK(status
)) {
8171 printf("POSIX mkdir of %s failed (%s)\n", dname
, nt_errstr(status
));
8175 /* Ensure st_mode == 0700 */
8176 status
= cli_posix_stat(cli1
, dname
, &sbuf
);
8177 if (!NT_STATUS_IS_OK(status
)) {
8178 printf("stat failed (%s)\n", nt_errstr(status
));
8182 if ((sbuf
.st_ex_mode
& 07777) != 0700) {
8183 printf("posix_mkdir - bad permissions 0%o != 0700\n",
8184 (unsigned int)(sbuf
.st_ex_mode
& 07777));
8189 * Now create a Windows file, and attempt a POSIX unlink.
8190 * This should fail with a sharing violation but due to:
8192 * [Bug 9571] Unlink after open causes smbd to panic
8194 * ensure we've fixed the lock ordering violation.
8197 status
= cli_ntcreate(cli1
, fname_windows
, 0,
8198 FILE_READ_DATA
|FILE_WRITE_DATA
, 0,
8199 FILE_SHARE_READ
|FILE_SHARE_WRITE
|FILE_SHARE_DELETE
,
8201 0x0, 0x0, &fnum2
, NULL
);
8202 if (!NT_STATUS_IS_OK(status
)) {
8203 printf("Windows create of %s failed (%s)\n", fname_windows
,
8208 /* Now try posix_unlink. */
8209 status
= cli_posix_unlink(cli1
, fname_windows
);
8210 if (!NT_STATUS_EQUAL(status
, NT_STATUS_SHARING_VIOLATION
)) {
8211 printf("POSIX unlink of %s should fail "
8212 "with NT_STATUS_SHARING_VIOLATION "
8213 "got %s instead !\n",
8219 cli_close(cli1
, fnum2
);
8221 printf("Simple POSIX open test passed\n");
8226 if (fnum1
!= (uint16_t)-1) {
8227 cli_close(cli1
, fnum1
);
8228 fnum1
= (uint16_t)-1;
8231 if (fnum2
!= (uint16_t)-1) {
8232 cli_close(cli1
, fnum2
);
8233 fnum2
= (uint16_t)-1;
8236 cli_setatr(cli1
, sname
, 0, 0);
8237 cli_posix_unlink(cli1
, sname
);
8238 cli_setatr(cli1
, hname
, 0, 0);
8239 cli_posix_unlink(cli1
, hname
);
8240 cli_setatr(cli1
, fname
, 0, 0);
8241 cli_posix_unlink(cli1
, fname
);
8242 cli_setatr(cli1
, dname
, 0, 0);
8243 cli_posix_rmdir(cli1
, dname
);
8244 cli_setatr(cli1
, fname_windows
, 0, 0);
8245 cli_posix_unlink(cli1
, fname_windows
);
8247 if (!torture_close_connection(cli1
)) {
8255 Test POSIX and Windows ACLs are rejected on symlinks.
8257 static bool run_acl_symlink_test(int dummy
)
8259 static struct cli_state
*cli
;
8260 const char *fname
= "posix_file";
8261 const char *sname
= "posix_symlink";
8262 uint16_t fnum
= (uint16_t)-1;
8263 bool correct
= false;
8265 char *posix_acl
= NULL
;
8266 size_t posix_acl_len
= 0;
8267 char *posix_acl_sym
= NULL
;
8268 size_t posix_acl_len_sym
= 0;
8269 struct security_descriptor
*sd
= NULL
;
8270 TALLOC_CTX
*frame
= NULL
;
8272 frame
= talloc_stackframe();
8274 printf("Starting acl symlink test\n");
8276 if (!torture_open_connection(&cli
, 0)) {
8281 smbXcli_conn_set_sockopt(cli
->conn
, sockops
);
8283 status
= torture_setup_unix_extensions(cli
);
8284 if (!NT_STATUS_IS_OK(status
)) {
8289 cli_setatr(cli
, fname
, 0, 0);
8290 cli_posix_unlink(cli
, fname
);
8291 cli_setatr(cli
, sname
, 0, 0);
8292 cli_posix_unlink(cli
, sname
);
8294 status
= cli_ntcreate(cli
,
8297 READ_CONTROL_ACCESS
,
8299 FILE_SHARE_READ
|FILE_SHARE_WRITE
|FILE_SHARE_DELETE
,
8306 if (!NT_STATUS_IS_OK(status
)) {
8307 printf("cli_ntcreate of %s failed (%s)\n",
8313 /* Get the Windows ACL on the file. */
8314 status
= cli_query_secdesc(cli
,
8318 if (!NT_STATUS_IS_OK(status
)) {
8319 printf("cli_query_secdesc failed (%s)\n",
8324 /* Get the POSIX ACL on the file. */
8325 status
= cli_posix_getacl(cli
,
8331 if (!NT_STATUS_IS_OK(status
)) {
8332 printf("cli_posix_getacl failed (%s)\n",
8337 status
= cli_close(cli
, fnum
);
8338 if (!NT_STATUS_IS_OK(status
)) {
8339 printf("close failed (%s)\n", nt_errstr(status
));
8342 fnum
= (uint16_t)-1;
8344 /* Now create a symlink. */
8345 status
= cli_posix_symlink(cli
, fname
, sname
);
8346 if (!NT_STATUS_IS_OK(status
)) {
8347 printf("cli_posix_symlink of %s -> %s failed (%s)\n",
8354 /* Open a handle on the symlink for SD set/get should fail. */
8355 status
= cli_ntcreate(cli
,
8358 READ_CONTROL_ACCESS
|SEC_STD_WRITE_DAC
,
8360 FILE_SHARE_READ
|FILE_SHARE_WRITE
|FILE_SHARE_DELETE
,
8367 if (NT_STATUS_IS_OK(status
)) {
8368 printf("Symlink open for getsd/setsd of %s "
8369 "succeeded (should fail)\n",
8374 /* Try a stat-open on the symlink, should also fail. */
8375 status
= cli_ntcreate(cli
,
8378 FILE_READ_ATTRIBUTES
|FILE_WRITE_ATTRIBUTES
,
8380 FILE_SHARE_READ
|FILE_SHARE_WRITE
|FILE_SHARE_DELETE
,
8387 if (NT_STATUS_IS_OK(status
)) {
8388 printf("Stat-open of symlink succeeded (should fail)\n");
8392 /* Get the POSIX ACL on the symlink pathname. Should fail. */
8393 status
= cli_posix_getacl(cli
,
8399 if (!NT_STATUS_EQUAL(status
, NT_STATUS_ACCESS_DENIED
)) {
8400 printf("cli_posix_getacl on a symlink gave %s. "
8401 "Should be NT_STATUS_ACCESS_DENIED.\n",
8406 /* Set the POSIX ACL on the symlink pathname. Should fail. */
8407 status
= cli_posix_setacl(cli
,
8412 if (!NT_STATUS_EQUAL(status
, NT_STATUS_ACCESS_DENIED
)) {
8413 printf("cli_posix_setacl on a symlink gave %s. "
8414 "Should be NT_STATUS_ACCESS_DENIED.\n",
8419 printf("ACL symlink test passed\n");
8424 if (fnum
!= (uint16_t)-1) {
8425 cli_close(cli
, fnum
);
8426 fnum
= (uint16_t)-1;
8429 cli_setatr(cli
, sname
, 0, 0);
8430 cli_posix_unlink(cli
, sname
);
8431 cli_setatr(cli
, fname
, 0, 0);
8432 cli_posix_unlink(cli
, fname
);
8434 if (!torture_close_connection(cli
)) {
8443 Test POSIX can delete a file containing streams.
8445 static bool run_posix_stream_delete(int dummy
)
8447 struct cli_state
*cli1
= NULL
;
8448 struct cli_state
*cli2
= NULL
;
8449 const char *fname
= "streamfile";
8450 const char *stream_fname
= "streamfile:Zone.Identifier:$DATA";
8451 uint16_t fnum1
= (uint16_t)-1;
8452 bool correct
= false;
8454 TALLOC_CTX
*frame
= NULL
;
8456 frame
= talloc_stackframe();
8458 printf("Starting POSIX stream delete test\n");
8460 if (!torture_open_connection(&cli1
, 0) ||
8461 !torture_open_connection(&cli2
, 1)) {
8466 smbXcli_conn_set_sockopt(cli1
->conn
, sockops
);
8467 smbXcli_conn_set_sockopt(cli2
->conn
, sockops
);
8469 status
= torture_setup_unix_extensions(cli2
);
8470 if (!NT_STATUS_IS_OK(status
)) {
8474 cli_setatr(cli1
, fname
, 0, 0);
8475 cli_unlink(cli1
, fname
, FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
);
8477 /* Create the file. */
8478 status
= cli_ntcreate(cli1
,
8481 READ_CONTROL_ACCESS
,
8483 FILE_SHARE_READ
|FILE_SHARE_WRITE
|FILE_SHARE_DELETE
,
8490 if (!NT_STATUS_IS_OK(status
)) {
8491 printf("cli_ntcreate of %s failed (%s)\n",
8497 status
= cli_close(cli1
, fnum1
);
8498 if (!NT_STATUS_IS_OK(status
)) {
8499 printf("cli_close of %s failed (%s)\n",
8504 fnum1
= (uint16_t)-1;
8506 /* Now create the stream. */
8507 status
= cli_ntcreate(cli1
,
8512 FILE_SHARE_READ
|FILE_SHARE_WRITE
,
8519 if (!NT_STATUS_IS_OK(status
)) {
8520 printf("cli_ntcreate of %s failed (%s)\n",
8526 /* Leave the stream handle open... */
8528 /* POSIX unlink should fail. */
8529 status
= cli_posix_unlink(cli2
, fname
);
8530 if (NT_STATUS_IS_OK(status
)) {
8531 printf("cli_posix_unlink of %s succeeded, should have failed\n",
8536 if (!NT_STATUS_EQUAL(status
, NT_STATUS_SHARING_VIOLATION
)) {
8537 printf("cli_posix_unlink of %s failed with (%s) "
8538 "should have been NT_STATUS_SHARING_VIOLATION\n",
8544 /* Close the stream handle. */
8545 status
= cli_close(cli1
, fnum1
);
8546 if (!NT_STATUS_IS_OK(status
)) {
8547 printf("cli_close of %s failed (%s)\n",
8552 fnum1
= (uint16_t)-1;
8554 /* POSIX unlink after stream handle closed should succeed. */
8555 status
= cli_posix_unlink(cli2
, fname
);
8556 if (!NT_STATUS_IS_OK(status
)) {
8557 printf("cli_posix_unlink of %s failed (%s)\n",
8563 printf("POSIX stream delete test passed\n");
8568 if (fnum1
!= (uint16_t)-1) {
8569 cli_close(cli1
, fnum1
);
8570 fnum1
= (uint16_t)-1;
8573 cli_setatr(cli1
, fname
, 0, 0);
8574 cli_unlink(cli1
, fname
, FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
);
8576 if (!torture_close_connection(cli1
)) {
8579 if (!torture_close_connection(cli2
)) {
8588 Test setting EA's are rejected on symlinks.
8590 static bool run_ea_symlink_test(int dummy
)
8592 static struct cli_state
*cli
;
8593 const char *fname
= "posix_file_ea";
8594 const char *sname
= "posix_symlink_ea";
8595 const char *ea_name
= "testea_name";
8596 const char *ea_value
= "testea_value";
8597 uint16_t fnum
= (uint16_t)-1;
8598 bool correct
= false;
8601 struct ea_struct
*eas
= NULL
;
8602 TALLOC_CTX
*frame
= NULL
;
8604 frame
= talloc_stackframe();
8606 printf("Starting EA symlink test\n");
8608 if (!torture_open_connection(&cli
, 0)) {
8613 smbXcli_conn_set_sockopt(cli
->conn
, sockops
);
8615 status
= torture_setup_unix_extensions(cli
);
8616 if (!NT_STATUS_IS_OK(status
)) {
8621 cli_setatr(cli
, fname
, 0, 0);
8622 cli_posix_unlink(cli
, fname
);
8623 cli_setatr(cli
, sname
, 0, 0);
8624 cli_posix_unlink(cli
, sname
);
8626 status
= cli_ntcreate(cli
,
8629 READ_CONTROL_ACCESS
,
8631 FILE_SHARE_READ
|FILE_SHARE_WRITE
|FILE_SHARE_DELETE
,
8638 if (!NT_STATUS_IS_OK(status
)) {
8639 printf("cli_ntcreate of %s failed (%s)\n",
8645 status
= cli_close(cli
, fnum
);
8646 if (!NT_STATUS_IS_OK(status
)) {
8647 printf("close failed (%s)\n",
8651 fnum
= (uint16_t)-1;
8653 /* Set an EA on the path. */
8654 status
= cli_set_ea_path(cli
,
8658 strlen(ea_value
)+1);
8660 if (!NT_STATUS_IS_OK(status
)) {
8661 printf("cli_set_ea_path failed (%s)\n",
8666 /* Now create a symlink. */
8667 status
= cli_posix_symlink(cli
, fname
, sname
);
8668 if (!NT_STATUS_IS_OK(status
)) {
8669 printf("cli_posix_symlink of %s -> %s failed (%s)\n",
8676 /* Get the EA list on the path. Should return value set. */
8677 status
= cli_get_ea_list_path(cli
,
8683 if (!NT_STATUS_IS_OK(status
)) {
8684 printf("cli_get_ea_list_path failed (%s)\n",
8689 /* Ensure the EA we set is there. */
8690 for (i
=0; i
<num_eas
; i
++) {
8691 if (strcmp(eas
[i
].name
, ea_name
) == 0 &&
8692 eas
[i
].value
.length
== strlen(ea_value
)+1 &&
8693 memcmp(eas
[i
].value
.data
,
8695 eas
[i
].value
.length
) == 0) {
8701 printf("Didn't find EA on pathname %s\n",
8709 /* Get the EA list on the symlink. Should return empty list. */
8710 status
= cli_get_ea_list_path(cli
,
8716 if (!NT_STATUS_IS_OK(status
)) {
8717 printf("cli_get_ea_list_path failed (%s)\n",
8723 printf("cli_get_ea_list_path failed (%s)\n",
8728 /* Set an EA on the symlink. Should fail. */
8729 status
= cli_set_ea_path(cli
,
8733 strlen(ea_value
)+1);
8735 if (!NT_STATUS_EQUAL(status
, NT_STATUS_ACCESS_DENIED
)) {
8736 printf("cli_set_ea_path on a symlink gave %s. "
8737 "Should be NT_STATUS_ACCESS_DENIED.\n",
8742 printf("EA symlink test passed\n");
8747 if (fnum
!= (uint16_t)-1) {
8748 cli_close(cli
, fnum
);
8749 fnum
= (uint16_t)-1;
8752 cli_setatr(cli
, sname
, 0, 0);
8753 cli_posix_unlink(cli
, sname
);
8754 cli_setatr(cli
, fname
, 0, 0);
8755 cli_posix_unlink(cli
, fname
);
8757 if (!torture_close_connection(cli
)) {
8766 Test POSIX locks are OFD-locks.
8768 static bool run_posix_ofd_lock_test(int dummy
)
8770 static struct cli_state
*cli
;
8771 const char *fname
= "posix_file";
8772 uint16_t fnum1
= (uint16_t)-1;
8773 uint16_t fnum2
= (uint16_t)-1;
8774 bool correct
= false;
8776 TALLOC_CTX
*frame
= NULL
;
8778 frame
= talloc_stackframe();
8780 printf("Starting POSIX ofd-lock test\n");
8782 if (!torture_open_connection(&cli
, 0)) {
8787 smbXcli_conn_set_sockopt(cli
->conn
, sockops
);
8789 status
= torture_setup_unix_extensions(cli
);
8790 if (!NT_STATUS_IS_OK(status
)) {
8795 cli_setatr(cli
, fname
, 0, 0);
8796 cli_posix_unlink(cli
, fname
);
8798 /* Open the file twice. */
8799 status
= cli_posix_open(cli
, fname
, O_RDWR
|O_CREAT
|O_EXCL
,
8801 if (!NT_STATUS_IS_OK(status
)) {
8802 printf("First POSIX open of %s failed\n", fname
);
8806 status
= cli_posix_open(cli
, fname
, O_RDWR
, 0, &fnum2
);
8807 if (!NT_STATUS_IS_OK(status
)) {
8808 printf("First POSIX open of %s failed\n", fname
);
8812 /* Set a 0-50 lock on fnum1. */
8813 status
= cli_posix_lock(cli
, fnum1
, 0, 50, false, WRITE_LOCK
);
8814 if (!NT_STATUS_IS_OK(status
)) {
8815 printf("POSIX lock (1) failed %s\n", nt_errstr(status
));
8819 /* Set a 60-100 lock on fnum2. */
8820 status
= cli_posix_lock(cli
, fnum2
, 60, 100, false, WRITE_LOCK
);
8821 if (!NT_STATUS_IS_OK(status
)) {
8822 printf("POSIX lock (2) failed %s\n", nt_errstr(status
));
8826 /* close fnum1 - 0-50 lock should go away. */
8827 status
= cli_close(cli
, fnum1
);
8828 if (!NT_STATUS_IS_OK(status
)) {
8829 printf("close failed (%s)\n",
8833 fnum1
= (uint16_t)-1;
8835 /* Change the lock context. */
8836 cli_setpid(cli
, cli_getpid(cli
) + 1);
8838 /* Re-open fnum1. */
8839 status
= cli_posix_open(cli
, fname
, O_RDWR
, 0, &fnum1
);
8840 if (!NT_STATUS_IS_OK(status
)) {
8841 printf("Third POSIX open of %s failed\n", fname
);
8845 /* 60-100 lock should still be there. */
8846 status
= cli_posix_lock(cli
, fnum1
, 60, 100, false, WRITE_LOCK
);
8847 if (!NT_STATUS_EQUAL(status
, NT_STATUS_FILE_LOCK_CONFLICT
)) {
8848 printf("POSIX lock 60-100 not there %s\n", nt_errstr(status
));
8852 /* 0-50 lock should be gone. */
8853 status
= cli_posix_lock(cli
, fnum1
, 0, 50, false, WRITE_LOCK
);
8854 if (!NT_STATUS_IS_OK(status
)) {
8855 printf("POSIX lock 0-50 failed %s\n", nt_errstr(status
));
8859 printf("POSIX OFD lock test passed\n");
8864 if (fnum1
!= (uint16_t)-1) {
8865 cli_close(cli
, fnum1
);
8866 fnum1
= (uint16_t)-1;
8868 if (fnum2
!= (uint16_t)-1) {
8869 cli_close(cli
, fnum2
);
8870 fnum2
= (uint16_t)-1;
8873 cli_setatr(cli
, fname
, 0, 0);
8874 cli_posix_unlink(cli
, fname
);
8876 if (!torture_close_connection(cli
)) {
8884 struct posix_blocking_state
{
8885 struct tevent_context
*ev
;
8886 struct cli_state
*cli1
;
8888 struct cli_state
*cli2
;
8894 static void posix_blocking_locked(struct tevent_req
*subreq
);
8895 static void posix_blocking_gotblocked(struct tevent_req
*subreq
);
8896 static void posix_blocking_gotecho(struct tevent_req
*subreq
);
8897 static void posix_blocking_unlocked(struct tevent_req
*subreq
);
8899 static struct tevent_req
*posix_blocking_send(
8900 TALLOC_CTX
*mem_ctx
,
8901 struct tevent_context
*ev
,
8902 struct cli_state
*cli1
,
8904 struct cli_state
*cli2
,
8907 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
8908 struct posix_blocking_state
*state
= NULL
;
8910 req
= tevent_req_create(mem_ctx
, &state
, struct posix_blocking_state
);
8916 state
->fnum1
= fnum1
;
8918 state
->fnum2
= fnum2
;
8920 subreq
= cli_posix_lock_send(
8929 if (tevent_req_nomem(subreq
, req
)) {
8930 return tevent_req_post(req
, ev
);
8932 tevent_req_set_callback(subreq
, posix_blocking_locked
, req
);
8936 static void posix_blocking_locked(struct tevent_req
*subreq
)
8938 struct tevent_req
*req
= tevent_req_callback_data(
8939 subreq
, struct tevent_req
);
8940 struct posix_blocking_state
*state
= tevent_req_data(
8941 req
, struct posix_blocking_state
);
8944 status
= cli_posix_lock_recv(subreq
);
8945 TALLOC_FREE(subreq
);
8946 if (tevent_req_nterror(req
, status
)) {
8950 subreq
= cli_posix_lock_send(
8959 if (tevent_req_nomem(subreq
, req
)) {
8962 tevent_req_set_callback(subreq
, posix_blocking_gotblocked
, req
);
8964 /* Make sure the blocking request is delivered */
8965 subreq
= cli_echo_send(
8970 (DATA_BLOB
) { .data
= (uint8_t *)state
, .length
= 1 });
8971 if (tevent_req_nomem(subreq
, req
)) {
8974 tevent_req_set_callback(subreq
, posix_blocking_gotecho
, req
);
8977 static void posix_blocking_gotblocked(struct tevent_req
*subreq
)
8979 struct tevent_req
*req
= tevent_req_callback_data(
8980 subreq
, struct tevent_req
);
8981 struct posix_blocking_state
*state
= tevent_req_data(
8982 req
, struct posix_blocking_state
);
8985 status
= cli_posix_lock_recv(subreq
);
8986 TALLOC_FREE(subreq
);
8987 if (tevent_req_nterror(req
, status
)) {
8990 if (!state
->gotecho
) {
8991 printf("blocked req got through before echo\n");
8992 tevent_req_nterror(req
, NT_STATUS_INVALID_LOCK_SEQUENCE
);
8995 tevent_req_done(req
);
8998 static void posix_blocking_gotecho(struct tevent_req
*subreq
)
9000 struct tevent_req
*req
= tevent_req_callback_data(
9001 subreq
, struct tevent_req
);
9002 struct posix_blocking_state
*state
= tevent_req_data(
9003 req
, struct posix_blocking_state
);
9006 status
= cli_echo_recv(subreq
);
9007 TALLOC_FREE(subreq
);
9008 if (tevent_req_nterror(req
, status
)) {
9011 if (state
->gotblocked
) {
9012 printf("blocked req got through before echo\n");
9013 tevent_req_nterror(req
, NT_STATUS_INVALID_LOCK_SEQUENCE
);
9016 state
->gotecho
= true;
9018 subreq
= cli_posix_lock_send(
9027 if (tevent_req_nomem(subreq
, req
)) {
9030 tevent_req_set_callback(subreq
, posix_blocking_unlocked
, req
);
9033 static void posix_blocking_unlocked(struct tevent_req
*subreq
)
9035 struct tevent_req
*req
= tevent_req_callback_data(
9036 subreq
, struct tevent_req
);
9039 status
= cli_posix_lock_recv(subreq
);
9040 TALLOC_FREE(subreq
);
9041 if (tevent_req_nterror(req
, status
)) {
9044 /* tevent_req_done in posix_blocking_gotlocked */
9047 static NTSTATUS
posix_blocking_recv(struct tevent_req
*req
)
9049 return tevent_req_simple_recv_ntstatus(req
);
9052 static bool run_posix_blocking_lock(int dummy
)
9054 struct tevent_context
*ev
= NULL
;
9055 struct cli_state
*cli1
= NULL
, *cli2
= NULL
;
9056 const char *fname
= "posix_blocking";
9057 uint16_t fnum1
= UINT16_MAX
, fnum2
= UINT16_MAX
;
9058 struct tevent_req
*req
= NULL
;
9063 printf("Starting posix blocking lock test\n");
9065 ev
= samba_tevent_context_init(NULL
);
9070 ok
= torture_open_connection(&cli1
, 0);
9074 ok
= torture_open_connection(&cli2
, 0);
9079 smbXcli_conn_set_sockopt(cli1
->conn
, sockops
);
9081 status
= torture_setup_unix_extensions(cli1
);
9082 if (!NT_STATUS_IS_OK(status
)) {
9086 status
= torture_setup_unix_extensions(cli2
);
9087 if (!NT_STATUS_IS_OK(status
)) {
9091 cli_setatr(cli1
, fname
, 0, 0);
9092 cli_posix_unlink(cli1
, fname
);
9094 status
= cli_posix_open(cli1
, fname
, O_RDWR
|O_CREAT
|O_EXCL
,
9096 if (!NT_STATUS_IS_OK(status
)) {
9097 printf("First POSIX open of %s failed: %s\n",
9103 status
= cli_posix_open(cli2
, fname
, O_RDWR
, 0600, &fnum2
);
9104 if (!NT_STATUS_IS_OK(status
)) {
9105 printf("Second POSIX open of %s failed: %s\n",
9111 req
= posix_blocking_send(ev
, ev
, cli1
, fnum1
, cli2
, fnum2
);
9113 printf("cli_posix_blocking failed\n");
9117 ok
= tevent_req_poll_ntstatus(req
, ev
, &status
);
9119 printf("tevent_req_poll_ntstatus failed: %s\n",
9123 status
= posix_blocking_recv(req
);
9125 if (!NT_STATUS_IS_OK(status
)) {
9126 printf("posix_blocking_recv returned %s\n",
9134 if (fnum1
!= UINT16_MAX
) {
9135 cli_close(cli1
, fnum1
);
9138 if (fnum2
!= UINT16_MAX
) {
9139 cli_close(cli2
, fnum2
);
9144 cli_setatr(cli1
, fname
, 0, 0);
9145 cli_posix_unlink(cli1
, fname
);
9151 ok
&= torture_close_connection(cli1
);
9155 ok
&= torture_close_connection(cli2
);
9167 Test POSIX mkdir is case-sensitive.
9169 static bool run_posix_mkdir_test(int dummy
)
9171 static struct cli_state
*cli
;
9172 const char *fname_foo
= "POSIX_foo";
9173 const char *fname_foo_Foo
= "POSIX_foo/Foo";
9174 const char *fname_foo_foo
= "POSIX_foo/foo";
9175 const char *fname_Foo
= "POSIX_Foo";
9176 const char *fname_Foo_Foo
= "POSIX_Foo/Foo";
9177 const char *fname_Foo_foo
= "POSIX_Foo/foo";
9178 bool correct
= false;
9180 TALLOC_CTX
*frame
= NULL
;
9181 uint16_t fnum
= (uint16_t)-1;
9183 frame
= talloc_stackframe();
9185 printf("Starting POSIX mkdir test\n");
9187 if (!torture_open_connection(&cli
, 0)) {
9192 smbXcli_conn_set_sockopt(cli
->conn
, sockops
);
9194 status
= torture_setup_unix_extensions(cli
);
9195 if (!NT_STATUS_IS_OK(status
)) {
9200 cli_posix_rmdir(cli
, fname_foo_foo
);
9201 cli_posix_rmdir(cli
, fname_foo_Foo
);
9202 cli_posix_rmdir(cli
, fname_foo
);
9204 cli_posix_rmdir(cli
, fname_Foo_foo
);
9205 cli_posix_rmdir(cli
, fname_Foo_Foo
);
9206 cli_posix_rmdir(cli
, fname_Foo
);
9209 * Create a file POSIX_foo then try
9210 * and use it in a directory path by
9211 * doing mkdir POSIX_foo/bar.
9212 * The mkdir should fail with
9213 * NT_STATUS_OBJECT_PATH_NOT_FOUND
9216 status
= cli_posix_open(cli
,
9221 if (!NT_STATUS_IS_OK(status
)) {
9222 printf("cli_posix_open of %s failed error %s\n",
9228 status
= cli_posix_mkdir(cli
, fname_foo_foo
, 0777);
9229 if (!NT_STATUS_EQUAL(status
, NT_STATUS_OBJECT_PATH_NOT_FOUND
)) {
9230 printf("cli_posix_mkdir of %s should fail with "
9231 "NT_STATUS_OBJECT_PATH_NOT_FOUND got "
9238 status
= cli_close(cli
, fnum
);
9239 if (!NT_STATUS_IS_OK(status
)) {
9240 printf("cli_close failed %s\n", nt_errstr(status
));
9243 fnum
= (uint16_t)-1;
9245 status
= cli_posix_unlink(cli
, fname_foo
);
9246 if (!NT_STATUS_IS_OK(status
)) {
9247 printf("cli_posix_unlink of %s failed error %s\n",
9254 * Now we've deleted everything, posix_mkdir, posix_rmdir,
9255 * posix_open, posix_unlink, on
9256 * POSIX_foo/foo should return NT_STATUS_OBJECT_PATH_NOT_FOUND
9257 * not silently create POSIX_foo/foo.
9260 status
= cli_posix_mkdir(cli
, fname_foo_foo
, 0777);
9261 if (!NT_STATUS_EQUAL(status
, NT_STATUS_OBJECT_PATH_NOT_FOUND
)) {
9262 printf("cli_posix_mkdir of %s should fail with "
9263 "NT_STATUS_OBJECT_PATH_NOT_FOUND got "
9270 status
= cli_posix_rmdir(cli
, fname_foo_foo
);
9271 if (!NT_STATUS_EQUAL(status
, NT_STATUS_OBJECT_PATH_NOT_FOUND
)) {
9272 printf("cli_posix_rmdir of %s should fail with "
9273 "NT_STATUS_OBJECT_PATH_NOT_FOUND got "
9280 status
= cli_posix_open(cli
,
9285 if (!NT_STATUS_EQUAL(status
, NT_STATUS_OBJECT_PATH_NOT_FOUND
)) {
9286 printf("cli_posix_open of %s should fail with "
9287 "NT_STATUS_OBJECT_PATH_NOT_FOUND got "
9294 status
= cli_posix_unlink(cli
, fname_foo_foo
);
9295 if (!NT_STATUS_EQUAL(status
, NT_STATUS_OBJECT_PATH_NOT_FOUND
)) {
9296 printf("cli_posix_unlink of %s should fail with "
9297 "NT_STATUS_OBJECT_PATH_NOT_FOUND got "
9304 status
= cli_posix_mkdir(cli
, fname_foo
, 0777);
9305 if (!NT_STATUS_IS_OK(status
)) {
9306 printf("cli_posix_mkdir of %s failed\n", fname_foo
);
9310 status
= cli_posix_mkdir(cli
, fname_Foo
, 0777);
9311 if (!NT_STATUS_IS_OK(status
)) {
9312 printf("cli_posix_mkdir of %s failed\n", fname_Foo
);
9316 status
= cli_posix_mkdir(cli
, fname_foo_foo
, 0777);
9317 if (!NT_STATUS_IS_OK(status
)) {
9318 printf("cli_posix_mkdir of %s failed\n", fname_foo_foo
);
9322 status
= cli_posix_mkdir(cli
, fname_foo_Foo
, 0777);
9323 if (!NT_STATUS_IS_OK(status
)) {
9324 printf("cli_posix_mkdir of %s failed\n", fname_foo_Foo
);
9328 status
= cli_posix_mkdir(cli
, fname_Foo_foo
, 0777);
9329 if (!NT_STATUS_IS_OK(status
)) {
9330 printf("cli_posix_mkdir of %s failed\n", fname_Foo_foo
);
9334 status
= cli_posix_mkdir(cli
, fname_Foo_Foo
, 0777);
9335 if (!NT_STATUS_IS_OK(status
)) {
9336 printf("cli_posix_mkdir of %s failed\n", fname_Foo_Foo
);
9340 printf("POSIX mkdir test passed\n");
9345 if (fnum
!= (uint16_t)-1) {
9346 cli_close(cli
, fnum
);
9347 fnum
= (uint16_t)-1;
9350 cli_posix_rmdir(cli
, fname_foo_foo
);
9351 cli_posix_rmdir(cli
, fname_foo_Foo
);
9352 cli_posix_rmdir(cli
, fname_foo
);
9354 cli_posix_rmdir(cli
, fname_Foo_foo
);
9355 cli_posix_rmdir(cli
, fname_Foo_Foo
);
9356 cli_posix_rmdir(cli
, fname_Foo
);
9358 if (!torture_close_connection(cli
)) {
9366 struct posix_acl_oplock_state
{
9367 struct tevent_context
*ev
;
9368 struct cli_state
*cli
;
9374 static void posix_acl_oplock_got_break(struct tevent_req
*req
)
9376 struct posix_acl_oplock_state
*state
= tevent_req_callback_data(
9377 req
, struct posix_acl_oplock_state
);
9382 status
= cli_smb_oplock_break_waiter_recv(req
, &fnum
, &level
);
9384 if (!NT_STATUS_IS_OK(status
)) {
9385 printf("cli_smb_oplock_break_waiter_recv returned %s\n",
9389 *state
->got_break
= true;
9391 req
= cli_oplock_ack_send(state
, state
->ev
, state
->cli
, fnum
,
9394 printf("cli_oplock_ack_send failed\n");
9399 static void posix_acl_oplock_got_acl(struct tevent_req
*req
)
9401 struct posix_acl_oplock_state
*state
= tevent_req_callback_data(
9402 req
, struct posix_acl_oplock_state
);
9403 size_t ret_size
= 0;
9404 char *ret_data
= NULL
;
9406 state
->status
= cli_posix_getacl_recv(req
,
9411 if (!NT_STATUS_IS_OK(state
->status
)) {
9412 printf("cli_posix_getacl_recv returned %s\n",
9413 nt_errstr(state
->status
));
9415 *state
->acl_ret
= true;
9418 static bool run_posix_acl_oplock_test(int dummy
)
9420 struct tevent_context
*ev
;
9421 struct cli_state
*cli1
, *cli2
;
9422 struct tevent_req
*oplock_req
, *getacl_req
;
9423 const char *fname
= "posix_acl_oplock";
9425 int saved_use_oplocks
= use_oplocks
;
9427 bool correct
= true;
9428 bool got_break
= false;
9429 bool acl_ret
= false;
9431 struct posix_acl_oplock_state
*state
;
9433 printf("starting posix_acl_oplock test\n");
9435 if (!torture_open_connection(&cli1
, 0)) {
9436 use_level_II_oplocks
= false;
9437 use_oplocks
= saved_use_oplocks
;
9441 if (!torture_open_connection(&cli2
, 1)) {
9442 use_level_II_oplocks
= false;
9443 use_oplocks
= saved_use_oplocks
;
9447 /* Setup posix on cli2 only. */
9448 status
= torture_setup_unix_extensions(cli2
);
9449 if (!NT_STATUS_IS_OK(status
)) {
9453 smbXcli_conn_set_sockopt(cli1
->conn
, sockops
);
9454 smbXcli_conn_set_sockopt(cli2
->conn
, sockops
);
9456 cli_unlink(cli1
, fname
, FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
);
9458 /* Create the file on the Windows connection. */
9459 status
= cli_openx(cli1
, fname
, O_RDWR
|O_CREAT
|O_EXCL
, DENY_NONE
,
9461 if (!NT_STATUS_IS_OK(status
)) {
9462 printf("open of %s failed (%s)\n", fname
, nt_errstr(status
));
9466 status
= cli_close(cli1
, fnum
);
9467 if (!NT_STATUS_IS_OK(status
)) {
9468 printf("close1 failed (%s)\n", nt_errstr(status
));
9472 cli1
->use_oplocks
= true;
9474 /* Open with oplock. */
9475 status
= cli_ntcreate(cli1
,
9479 FILE_ATTRIBUTE_NORMAL
,
9480 FILE_SHARE_READ
|FILE_SHARE_WRITE
|FILE_SHARE_DELETE
,
9487 if (!NT_STATUS_IS_OK(status
)) {
9488 printf("open of %s failed (%s)\n", fname
, nt_errstr(status
));
9492 ev
= samba_tevent_context_init(talloc_tos());
9494 printf("tevent_context_init failed\n");
9498 state
= talloc_zero(ev
, struct posix_acl_oplock_state
);
9499 if (state
== NULL
) {
9500 printf("talloc failed\n");
9505 state
->got_break
= &got_break
;
9506 state
->acl_ret
= &acl_ret
;
9508 oplock_req
= cli_smb_oplock_break_waiter_send(
9509 talloc_tos(), ev
, cli1
);
9510 if (oplock_req
== NULL
) {
9511 printf("cli_smb_oplock_break_waiter_send failed\n");
9514 tevent_req_set_callback(oplock_req
, posix_acl_oplock_got_break
, state
);
9516 /* Get ACL on POSIX connection - should break oplock. */
9517 getacl_req
= cli_posix_getacl_send(talloc_tos(),
9521 if (getacl_req
== NULL
) {
9522 printf("cli_posix_getacl_send failed\n");
9525 tevent_req_set_callback(getacl_req
, posix_acl_oplock_got_acl
, state
);
9527 while (!got_break
|| !acl_ret
) {
9529 ret
= tevent_loop_once(ev
);
9531 printf("tevent_loop_once failed: %s\n",
9537 if (!NT_STATUS_IS_OK(state
->status
)) {
9538 printf("getacl failed (%s)\n", nt_errstr(state
->status
));
9542 status
= cli_close(cli1
, fnum
);
9543 if (!NT_STATUS_IS_OK(status
)) {
9544 printf("close2 failed (%s)\n", nt_errstr(status
));
9548 status
= cli_unlink(cli1
,
9550 FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
);
9551 if (!NT_STATUS_IS_OK(status
)) {
9552 printf("unlink failed (%s)\n", nt_errstr(status
));
9556 if (!torture_close_connection(cli1
)) {
9559 if (!torture_close_connection(cli2
)) {
9567 printf("finished posix acl oplock test\n");
9572 static bool run_posix_acl_shareroot_test(int dummy
)
9574 struct cli_state
*cli
;
9576 bool correct
= false;
9577 char *posix_acl
= NULL
;
9578 size_t posix_acl_len
= 0;
9579 uint16_t num_file_acls
= 0;
9580 uint16_t num_dir_acls
= 0;
9582 uint32_t expected_size
= 0;
9583 bool got_user
= false;
9584 bool got_group
= false;
9585 bool got_other
= false;
9586 TALLOC_CTX
*frame
= NULL
;
9588 frame
= talloc_stackframe();
9590 printf("starting posix_acl_shareroot test\n");
9592 if (!torture_open_connection(&cli
, 0)) {
9597 smbXcli_conn_set_sockopt(cli
->conn
, sockops
);
9599 status
= torture_setup_unix_extensions(cli
);
9600 if (!NT_STATUS_IS_OK(status
)) {
9601 printf("Failed to setup unix extensions\n");
9605 /* Get the POSIX ACL on the root of the share. */
9606 status
= cli_posix_getacl(cli
,
9612 if (!NT_STATUS_IS_OK(status
)) {
9613 printf("cli_posix_getacl of '.' failed (%s)\n",
9618 if (posix_acl_len
< 6 ||
9619 SVAL(posix_acl
,0) != SMB_POSIX_ACL_VERSION
) {
9620 printf("getfacl ., unknown POSIX acl version %u.\n",
9621 (unsigned int)CVAL(posix_acl
,0) );
9625 num_file_acls
= SVAL(posix_acl
,2);
9626 num_dir_acls
= SVAL(posix_acl
,4);
9627 expected_size
= SMB_POSIX_ACL_HEADER_SIZE
+
9628 SMB_POSIX_ACL_ENTRY_SIZE
*
9629 (num_file_acls
+num_dir_acls
);
9631 if (posix_acl_len
!= expected_size
) {
9632 printf("incorrect POSIX acl buffer size "
9633 "(should be %u, was %u).\n",
9634 (unsigned int)expected_size
,
9635 (unsigned int)posix_acl_len
);
9640 * We don't need to know what the ACL's are
9641 * we just need to know we have at least 3
9642 * file entries (u,g,o).
9645 for (i
= 0; i
< num_file_acls
; i
++) {
9646 unsigned char tagtype
=
9648 SMB_POSIX_ACL_HEADER_SIZE
+
9649 (i
*SMB_POSIX_ACL_ENTRY_SIZE
));
9652 case SMB_POSIX_ACL_USER_OBJ
:
9655 case SMB_POSIX_ACL_GROUP_OBJ
:
9658 case SMB_POSIX_ACL_OTHER
:
9667 printf("Missing user entry\n");
9672 printf("Missing group entry\n");
9677 printf("Missing other entry\n");
9685 if (!torture_close_connection(cli
)) {
9689 printf("finished posix acl shareroot test\n");
9695 static uint32_t open_attrs_table
[] = {
9696 FILE_ATTRIBUTE_NORMAL
,
9697 FILE_ATTRIBUTE_ARCHIVE
,
9698 FILE_ATTRIBUTE_READONLY
,
9699 FILE_ATTRIBUTE_HIDDEN
,
9700 FILE_ATTRIBUTE_SYSTEM
,
9702 FILE_ATTRIBUTE_ARCHIVE
|FILE_ATTRIBUTE_READONLY
,
9703 FILE_ATTRIBUTE_ARCHIVE
|FILE_ATTRIBUTE_HIDDEN
,
9704 FILE_ATTRIBUTE_ARCHIVE
|FILE_ATTRIBUTE_SYSTEM
,
9705 FILE_ATTRIBUTE_ARCHIVE
|FILE_ATTRIBUTE_READONLY
|FILE_ATTRIBUTE_HIDDEN
,
9706 FILE_ATTRIBUTE_ARCHIVE
|FILE_ATTRIBUTE_READONLY
|FILE_ATTRIBUTE_SYSTEM
,
9707 FILE_ATTRIBUTE_ARCHIVE
|FILE_ATTRIBUTE_HIDDEN
|FILE_ATTRIBUTE_SYSTEM
,
9709 FILE_ATTRIBUTE_READONLY
|FILE_ATTRIBUTE_HIDDEN
,
9710 FILE_ATTRIBUTE_READONLY
|FILE_ATTRIBUTE_SYSTEM
,
9711 FILE_ATTRIBUTE_READONLY
|FILE_ATTRIBUTE_HIDDEN
|FILE_ATTRIBUTE_SYSTEM
,
9712 FILE_ATTRIBUTE_HIDDEN
,FILE_ATTRIBUTE_SYSTEM
,
9715 struct trunc_open_results
{
9718 uint32_t trunc_attr
;
9719 uint32_t result_attr
;
9722 static struct trunc_open_results attr_results
[] = {
9723 { 0, FILE_ATTRIBUTE_NORMAL
, FILE_ATTRIBUTE_NORMAL
, FILE_ATTRIBUTE_ARCHIVE
},
9724 { 1, FILE_ATTRIBUTE_NORMAL
, FILE_ATTRIBUTE_ARCHIVE
, FILE_ATTRIBUTE_ARCHIVE
},
9725 { 2, FILE_ATTRIBUTE_NORMAL
, FILE_ATTRIBUTE_READONLY
, FILE_ATTRIBUTE_ARCHIVE
|FILE_ATTRIBUTE_READONLY
},
9726 { 16, FILE_ATTRIBUTE_ARCHIVE
, FILE_ATTRIBUTE_NORMAL
, FILE_ATTRIBUTE_ARCHIVE
},
9727 { 17, FILE_ATTRIBUTE_ARCHIVE
, FILE_ATTRIBUTE_ARCHIVE
, FILE_ATTRIBUTE_ARCHIVE
},
9728 { 18, FILE_ATTRIBUTE_ARCHIVE
, FILE_ATTRIBUTE_READONLY
, FILE_ATTRIBUTE_ARCHIVE
|FILE_ATTRIBUTE_READONLY
},
9729 { 51, FILE_ATTRIBUTE_HIDDEN
, FILE_ATTRIBUTE_HIDDEN
, FILE_ATTRIBUTE_ARCHIVE
|FILE_ATTRIBUTE_HIDDEN
},
9730 { 54, FILE_ATTRIBUTE_HIDDEN
, FILE_ATTRIBUTE_ARCHIVE
|FILE_ATTRIBUTE_HIDDEN
, FILE_ATTRIBUTE_ARCHIVE
|FILE_ATTRIBUTE_HIDDEN
},
9731 { 56, FILE_ATTRIBUTE_HIDDEN
, FILE_ATTRIBUTE_ARCHIVE
|FILE_ATTRIBUTE_READONLY
|FILE_ATTRIBUTE_HIDDEN
, FILE_ATTRIBUTE_ARCHIVE
|FILE_ATTRIBUTE_READONLY
|FILE_ATTRIBUTE_HIDDEN
},
9732 { 68, FILE_ATTRIBUTE_SYSTEM
, FILE_ATTRIBUTE_SYSTEM
, FILE_ATTRIBUTE_ARCHIVE
|FILE_ATTRIBUTE_SYSTEM
},
9733 { 71, FILE_ATTRIBUTE_SYSTEM
, FILE_ATTRIBUTE_ARCHIVE
|FILE_ATTRIBUTE_SYSTEM
, FILE_ATTRIBUTE_ARCHIVE
|FILE_ATTRIBUTE_SYSTEM
},
9734 { 73, FILE_ATTRIBUTE_SYSTEM
, FILE_ATTRIBUTE_ARCHIVE
|FILE_ATTRIBUTE_READONLY
|FILE_ATTRIBUTE_SYSTEM
, FILE_ATTRIBUTE_ARCHIVE
|FILE_ATTRIBUTE_READONLY
|FILE_ATTRIBUTE_SYSTEM
},
9735 { 99, FILE_ATTRIBUTE_ARCHIVE
|FILE_ATTRIBUTE_HIDDEN
, FILE_ATTRIBUTE_HIDDEN
,FILE_ATTRIBUTE_ARCHIVE
|FILE_ATTRIBUTE_HIDDEN
},
9736 { 102, FILE_ATTRIBUTE_ARCHIVE
|FILE_ATTRIBUTE_HIDDEN
, FILE_ATTRIBUTE_ARCHIVE
|FILE_ATTRIBUTE_HIDDEN
, FILE_ATTRIBUTE_ARCHIVE
|FILE_ATTRIBUTE_HIDDEN
},
9737 { 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
},
9738 { 116, FILE_ATTRIBUTE_ARCHIVE
|FILE_ATTRIBUTE_SYSTEM
, FILE_ATTRIBUTE_SYSTEM
, FILE_ATTRIBUTE_ARCHIVE
|FILE_ATTRIBUTE_SYSTEM
},
9739 { 119, FILE_ATTRIBUTE_ARCHIVE
|FILE_ATTRIBUTE_SYSTEM
, FILE_ATTRIBUTE_ARCHIVE
|FILE_ATTRIBUTE_SYSTEM
, FILE_ATTRIBUTE_ARCHIVE
|FILE_ATTRIBUTE_SYSTEM
},
9740 { 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
},
9741 { 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
},
9742 { 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
},
9743 { 227, FILE_ATTRIBUTE_HIDDEN
, FILE_ATTRIBUTE_HIDDEN
, FILE_ATTRIBUTE_ARCHIVE
|FILE_ATTRIBUTE_HIDDEN
},
9744 { 230, FILE_ATTRIBUTE_HIDDEN
, FILE_ATTRIBUTE_ARCHIVE
|FILE_ATTRIBUTE_HIDDEN
, FILE_ATTRIBUTE_ARCHIVE
|FILE_ATTRIBUTE_HIDDEN
},
9745 { 232, FILE_ATTRIBUTE_HIDDEN
, FILE_ATTRIBUTE_ARCHIVE
|FILE_ATTRIBUTE_READONLY
|FILE_ATTRIBUTE_HIDDEN
, FILE_ATTRIBUTE_ARCHIVE
|FILE_ATTRIBUTE_READONLY
|FILE_ATTRIBUTE_HIDDEN
},
9746 { 244, FILE_ATTRIBUTE_SYSTEM
, FILE_ATTRIBUTE_SYSTEM
, FILE_ATTRIBUTE_ARCHIVE
|FILE_ATTRIBUTE_SYSTEM
},
9747 { 247, FILE_ATTRIBUTE_SYSTEM
, FILE_ATTRIBUTE_ARCHIVE
|FILE_ATTRIBUTE_SYSTEM
, FILE_ATTRIBUTE_ARCHIVE
|FILE_ATTRIBUTE_SYSTEM
},
9748 { 249, FILE_ATTRIBUTE_SYSTEM
, FILE_ATTRIBUTE_ARCHIVE
|FILE_ATTRIBUTE_READONLY
|FILE_ATTRIBUTE_SYSTEM
, FILE_ATTRIBUTE_ARCHIVE
|FILE_ATTRIBUTE_READONLY
|FILE_ATTRIBUTE_SYSTEM
}
9751 static bool run_openattrtest(int dummy
)
9753 static struct cli_state
*cli1
;
9754 const char *fname
= "\\openattr.file";
9756 bool correct
= True
;
9758 unsigned int i
, j
, k
, l
;
9761 printf("starting open attr test\n");
9763 if (!torture_open_connection(&cli1
, 0)) {
9767 smbXcli_conn_set_sockopt(cli1
->conn
, sockops
);
9769 for (k
= 0, i
= 0; i
< sizeof(open_attrs_table
)/sizeof(uint32_t); i
++) {
9770 cli_setatr(cli1
, fname
, 0, 0);
9771 cli_unlink(cli1
, fname
, FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
);
9773 status
= cli_ntcreate(cli1
, fname
, 0, FILE_WRITE_DATA
,
9774 open_attrs_table
[i
], FILE_SHARE_NONE
,
9775 FILE_OVERWRITE_IF
, 0, 0, &fnum1
, NULL
);
9776 if (!NT_STATUS_IS_OK(status
)) {
9777 printf("open %d (1) of %s failed (%s)\n", i
, fname
, nt_errstr(status
));
9781 status
= cli_close(cli1
, fnum1
);
9782 if (!NT_STATUS_IS_OK(status
)) {
9783 printf("close %d (1) of %s failed (%s)\n", i
, fname
, nt_errstr(status
));
9787 for (j
= 0; j
< sizeof(open_attrs_table
)/sizeof(uint32_t); j
++) {
9788 status
= cli_ntcreate(cli1
, fname
, 0,
9789 FILE_READ_DATA
|FILE_WRITE_DATA
,
9790 open_attrs_table
[j
],
9791 FILE_SHARE_NONE
, FILE_OVERWRITE
,
9792 0, 0, &fnum1
, NULL
);
9793 if (!NT_STATUS_IS_OK(status
)) {
9794 for (l
= 0; l
< sizeof(attr_results
)/sizeof(struct trunc_open_results
); l
++) {
9795 if (attr_results
[l
].num
== k
) {
9796 printf("[%d] trunc open 0x%x -> 0x%x of %s failed - should have succeeded !(0x%x:%s)\n",
9797 k
, open_attrs_table
[i
],
9798 open_attrs_table
[j
],
9799 fname
, NT_STATUS_V(status
), nt_errstr(status
));
9804 if (!NT_STATUS_EQUAL(status
, NT_STATUS_ACCESS_DENIED
)) {
9805 printf("[%d] trunc open 0x%x -> 0x%x failed with wrong error code %s\n",
9806 k
, open_attrs_table
[i
], open_attrs_table
[j
],
9811 printf("[%d] trunc open 0x%x -> 0x%x failed\n", k
, open_attrs_table
[i
], open_attrs_table
[j
]);
9817 status
= cli_close(cli1
, fnum1
);
9818 if (!NT_STATUS_IS_OK(status
)) {
9819 printf("close %d (2) of %s failed (%s)\n", j
, fname
, nt_errstr(status
));
9823 status
= cli_getatr(cli1
, fname
, &attr
, NULL
, NULL
);
9824 if (!NT_STATUS_IS_OK(status
)) {
9825 printf("getatr(2) failed (%s)\n", nt_errstr(status
));
9830 printf("[%d] getatr check [0x%x] trunc [0x%x] got attr 0x%x\n",
9831 k
, open_attrs_table
[i
], open_attrs_table
[j
], attr
);
9834 for (l
= 0; l
< sizeof(attr_results
)/sizeof(struct trunc_open_results
); l
++) {
9835 if (attr_results
[l
].num
== k
) {
9836 if (attr
!= attr_results
[l
].result_attr
||
9837 open_attrs_table
[i
] != attr_results
[l
].init_attr
||
9838 open_attrs_table
[j
] != attr_results
[l
].trunc_attr
) {
9839 printf("getatr check failed. [0x%x] trunc [0x%x] got attr 0x%x, should be 0x%x\n",
9840 open_attrs_table
[i
],
9841 open_attrs_table
[j
],
9843 attr_results
[l
].result_attr
);
9853 cli_setatr(cli1
, fname
, 0, 0);
9854 cli_unlink(cli1
, fname
, FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
);
9856 printf("open attr test %s.\n", correct
? "passed" : "failed");
9858 if (!torture_close_connection(cli1
)) {
9864 static NTSTATUS
list_fn(struct file_info
*finfo
,
9865 const char *name
, void *state
)
9867 int *matched
= (int *)state
;
9868 if (matched
!= NULL
) {
9871 return NT_STATUS_OK
;
9875 test directory listing speed
9877 static bool run_dirtest(int dummy
)
9880 static struct cli_state
*cli
;
9882 struct timeval core_start
;
9883 bool correct
= True
;
9886 printf("starting directory test\n");
9888 if (!torture_open_connection(&cli
, 0)) {
9892 smbXcli_conn_set_sockopt(cli
->conn
, sockops
);
9895 for (i
=0;i
<torture_numops
;i
++) {
9897 slprintf(fname
, sizeof(fname
), "\\%x", (int)random());
9898 if (!NT_STATUS_IS_OK(cli_openx(cli
, fname
, O_RDWR
|O_CREAT
, DENY_NONE
, &fnum
))) {
9899 fprintf(stderr
,"Failed to open %s\n", fname
);
9902 cli_close(cli
, fnum
);
9905 core_start
= timeval_current();
9908 cli_list(cli
, "a*.*", 0, list_fn
, &matched
);
9909 printf("Matched %d\n", matched
);
9912 cli_list(cli
, "b*.*", 0, list_fn
, &matched
);
9913 printf("Matched %d\n", matched
);
9916 cli_list(cli
, "xyzabc", 0, list_fn
, &matched
);
9917 printf("Matched %d\n", matched
);
9919 printf("dirtest core %g seconds\n", timeval_elapsed(&core_start
));
9922 for (i
=0;i
<torture_numops
;i
++) {
9924 slprintf(fname
, sizeof(fname
), "\\%x", (int)random());
9925 cli_unlink(cli
, fname
, FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
);
9928 if (!torture_close_connection(cli
)) {
9932 printf("finished dirtest\n");
9937 static NTSTATUS
del_fn(struct file_info
*finfo
, const char *mask
,
9940 struct cli_state
*pcli
= (struct cli_state
*)state
;
9942 slprintf(fname
, sizeof(fname
), "\\LISTDIR\\%s", finfo
->name
);
9944 if (strcmp(finfo
->name
, ".") == 0 || strcmp(finfo
->name
, "..") == 0)
9945 return NT_STATUS_OK
;
9947 if (finfo
->attr
& FILE_ATTRIBUTE_DIRECTORY
) {
9948 if (!NT_STATUS_IS_OK(cli_rmdir(pcli
, fname
)))
9949 printf("del_fn: failed to rmdir %s\n,", fname
);
9951 if (!NT_STATUS_IS_OK(cli_unlink(pcli
, fname
, FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
)))
9952 printf("del_fn: failed to unlink %s\n,", fname
);
9954 return NT_STATUS_OK
;
9959 send a raw ioctl - used by the torture code
9961 static NTSTATUS
cli_raw_ioctl(struct cli_state
*cli
,
9969 PUSH_LE_U16(vwv
+ 0, 0, fnum
);
9970 PUSH_LE_U16(vwv
+ 1, 0, code
>> 16);
9971 PUSH_LE_U16(vwv
+ 2, 0, (code
& 0xFFFF));
9973 status
= cli_smb(talloc_tos(),
9987 if (!NT_STATUS_IS_OK(status
)) {
9990 *blob
= data_blob_null
;
9991 return NT_STATUS_OK
;
9995 sees what IOCTLs are supported
9997 bool torture_ioctl_test(int dummy
)
9999 static struct cli_state
*cli
;
10000 uint16_t device
, function
;
10002 const char *fname
= "\\ioctl.dat";
10006 if (!torture_open_connection(&cli
, 0)) {
10010 printf("starting ioctl test\n");
10012 cli_unlink(cli
, fname
, FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
);
10014 status
= cli_openx(cli
, fname
, O_RDWR
|O_CREAT
|O_EXCL
, DENY_NONE
, &fnum
);
10015 if (!NT_STATUS_IS_OK(status
)) {
10016 printf("open of %s failed (%s)\n", fname
, nt_errstr(status
));
10020 status
= cli_raw_ioctl(cli
, fnum
, 0x2d0000 | (0x0420<<2), &blob
);
10021 printf("ioctl device info: %s\n", nt_errstr(status
));
10023 status
= cli_raw_ioctl(cli
, fnum
, IOCTL_QUERY_JOB_INFO
, &blob
);
10024 printf("ioctl job info: %s\n", nt_errstr(status
));
10026 for (device
=0;device
<0x100;device
++) {
10027 printf("ioctl test with device = 0x%x\n", device
);
10028 for (function
=0;function
<0x100;function
++) {
10029 uint32_t code
= (device
<<16) | function
;
10031 status
= cli_raw_ioctl(cli
, fnum
, code
, &blob
);
10033 if (NT_STATUS_IS_OK(status
)) {
10034 printf("ioctl 0x%x OK : %d bytes\n", (int)code
,
10036 data_blob_free(&blob
);
10041 if (!torture_close_connection(cli
)) {
10050 tries variants of chkpath
10052 bool torture_chkpath_test(int dummy
)
10054 static struct cli_state
*cli
;
10059 if (!torture_open_connection(&cli
, 0)) {
10063 printf("starting chkpath test\n");
10065 /* cleanup from an old run */
10066 torture_deltree(cli
, "\\chkpath.dir");
10068 status
= cli_mkdir(cli
, "\\chkpath.dir");
10069 if (!NT_STATUS_IS_OK(status
)) {
10070 printf("mkdir1 failed : %s\n", nt_errstr(status
));
10074 status
= cli_mkdir(cli
, "\\chkpath.dir\\dir2");
10075 if (!NT_STATUS_IS_OK(status
)) {
10076 printf("mkdir2 failed : %s\n", nt_errstr(status
));
10080 status
= cli_openx(cli
, "\\chkpath.dir\\foo.txt", O_RDWR
|O_CREAT
|O_EXCL
,
10082 if (!NT_STATUS_IS_OK(status
)) {
10083 printf("open1 failed (%s)\n", nt_errstr(status
));
10086 cli_close(cli
, fnum
);
10088 status
= cli_chkpath(cli
, "\\chkpath.dir");
10089 if (!NT_STATUS_IS_OK(status
)) {
10090 printf("chkpath1 failed: %s\n", nt_errstr(status
));
10094 status
= cli_chkpath(cli
, "\\chkpath.dir\\dir2");
10095 if (!NT_STATUS_IS_OK(status
)) {
10096 printf("chkpath2 failed: %s\n", nt_errstr(status
));
10100 status
= cli_chkpath(cli
, "\\chkpath.dir\\foo.txt");
10101 if (!NT_STATUS_IS_OK(status
)) {
10102 ret
= check_error(__LINE__
, status
, ERRDOS
, ERRbadpath
,
10103 NT_STATUS_NOT_A_DIRECTORY
);
10105 printf("* chkpath on a file should fail\n");
10109 status
= cli_chkpath(cli
, "\\chkpath.dir\\bar.txt");
10110 if (!NT_STATUS_IS_OK(status
)) {
10111 ret
= check_error(__LINE__
, status
, ERRDOS
, ERRbadfile
,
10112 NT_STATUS_OBJECT_NAME_NOT_FOUND
);
10114 printf("* chkpath on a non existent file should fail\n");
10118 status
= cli_chkpath(cli
, "\\chkpath.dir\\dirxx\\bar.txt");
10119 if (!NT_STATUS_IS_OK(status
)) {
10120 ret
= check_error(__LINE__
, status
, ERRDOS
, ERRbadpath
,
10121 NT_STATUS_OBJECT_PATH_NOT_FOUND
);
10123 printf("* chkpath on a non existent component should fail\n");
10127 torture_deltree(cli
, "\\chkpath.dir");
10129 if (!torture_close_connection(cli
)) {
10136 static bool run_eatest(int dummy
)
10138 static struct cli_state
*cli
;
10139 const char *fname
= "\\eatest.txt";
10140 bool correct
= True
;
10143 struct ea_struct
*ea_list
= NULL
;
10144 TALLOC_CTX
*mem_ctx
= talloc_init("eatest");
10147 printf("starting eatest\n");
10149 if (!torture_open_connection(&cli
, 0)) {
10150 talloc_destroy(mem_ctx
);
10154 cli_unlink(cli
, fname
, FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
);
10156 status
= cli_ntcreate(cli
, fname
, 0,
10157 FIRST_DESIRED_ACCESS
, FILE_ATTRIBUTE_ARCHIVE
,
10158 FILE_SHARE_NONE
, FILE_OVERWRITE_IF
,
10159 0x4044, 0, &fnum
, NULL
);
10160 if (!NT_STATUS_IS_OK(status
)) {
10161 printf("open failed - %s\n", nt_errstr(status
));
10162 talloc_destroy(mem_ctx
);
10166 for (i
= 0; i
< 10; i
++) {
10167 fstring ea_name
, ea_val
;
10169 slprintf(ea_name
, sizeof(ea_name
), "EA_%zu", i
);
10170 memset(ea_val
, (char)i
+1, i
+1);
10171 status
= cli_set_ea_fnum(cli
, fnum
, ea_name
, ea_val
, i
+1);
10172 if (!NT_STATUS_IS_OK(status
)) {
10173 printf("ea_set of name %s failed - %s\n", ea_name
,
10174 nt_errstr(status
));
10175 talloc_destroy(mem_ctx
);
10180 cli_close(cli
, fnum
);
10181 for (i
= 0; i
< 10; i
++) {
10182 fstring ea_name
, ea_val
;
10184 slprintf(ea_name
, sizeof(ea_name
), "EA_%zu", i
+10);
10185 memset(ea_val
, (char)i
+1, i
+1);
10186 status
= cli_set_ea_path(cli
, fname
, ea_name
, ea_val
, i
+1);
10187 if (!NT_STATUS_IS_OK(status
)) {
10188 printf("ea_set of name %s failed - %s\n", ea_name
,
10189 nt_errstr(status
));
10190 talloc_destroy(mem_ctx
);
10195 status
= cli_get_ea_list_path(cli
, fname
, mem_ctx
, &num_eas
, &ea_list
);
10196 if (!NT_STATUS_IS_OK(status
)) {
10197 printf("ea_get list failed - %s\n", nt_errstr(status
));
10201 printf("num_eas = %d\n", (int)num_eas
);
10203 if (num_eas
!= 20) {
10204 printf("Should be 20 EA's stored... failing.\n");
10208 for (i
= 0; i
< num_eas
; i
++) {
10209 printf("%zu: ea_name = %s. Val = ", i
, ea_list
[i
].name
);
10210 dump_data(0, ea_list
[i
].value
.data
,
10211 ea_list
[i
].value
.length
);
10214 /* Setting EA's to zero length deletes them. Test this */
10215 printf("Now deleting all EA's - case independent....\n");
10218 cli_set_ea_path(cli
, fname
, "", "", 0);
10220 for (i
= 0; i
< 20; i
++) {
10222 slprintf(ea_name
, sizeof(ea_name
), "ea_%d", i
);
10223 status
= cli_set_ea_path(cli
, fname
, ea_name
, "", 0);
10224 if (!NT_STATUS_IS_OK(status
)) {
10225 printf("ea_set of name %s failed - %s\n", ea_name
,
10226 nt_errstr(status
));
10227 talloc_destroy(mem_ctx
);
10233 status
= cli_get_ea_list_path(cli
, fname
, mem_ctx
, &num_eas
, &ea_list
);
10234 if (!NT_STATUS_IS_OK(status
)) {
10235 printf("ea_get list failed - %s\n", nt_errstr(status
));
10239 printf("num_eas = %d\n", (int)num_eas
);
10240 for (i
= 0; i
< num_eas
; i
++) {
10241 printf("%zu: ea_name = %s. Val = ", i
, ea_list
[i
].name
);
10242 dump_data(0, ea_list
[i
].value
.data
,
10243 ea_list
[i
].value
.length
);
10246 if (num_eas
!= 0) {
10247 printf("deleting EA's failed.\n");
10251 /* Try and delete a non existent EA. */
10252 status
= cli_set_ea_path(cli
, fname
, "foo", "", 0);
10253 if (!NT_STATUS_IS_OK(status
)) {
10254 printf("deleting non-existent EA 'foo' should succeed. %s\n",
10255 nt_errstr(status
));
10259 talloc_destroy(mem_ctx
);
10260 if (!torture_close_connection(cli
)) {
10267 static bool run_dirtest1(int dummy
)
10270 static struct cli_state
*cli
;
10273 bool correct
= True
;
10275 printf("starting directory test\n");
10277 if (!torture_open_connection(&cli
, 0)) {
10281 smbXcli_conn_set_sockopt(cli
->conn
, sockops
);
10283 cli_list(cli
, "\\LISTDIR\\*", 0, del_fn
, cli
);
10284 cli_list(cli
, "\\LISTDIR\\*", FILE_ATTRIBUTE_DIRECTORY
, del_fn
, cli
);
10285 cli_rmdir(cli
, "\\LISTDIR");
10286 cli_mkdir(cli
, "\\LISTDIR");
10288 /* Create 1000 files and 1000 directories. */
10289 for (i
=0;i
<1000;i
++) {
10291 slprintf(fname
, sizeof(fname
), "\\LISTDIR\\f%d", i
);
10292 if (!NT_STATUS_IS_OK(cli_ntcreate(cli
, fname
, 0, GENERIC_ALL_ACCESS
, FILE_ATTRIBUTE_ARCHIVE
,
10293 FILE_SHARE_READ
|FILE_SHARE_WRITE
, FILE_OVERWRITE_IF
,
10294 0, 0, &fnum
, NULL
))) {
10295 fprintf(stderr
,"Failed to open %s\n", fname
);
10298 cli_close(cli
, fnum
);
10300 for (i
=0;i
<1000;i
++) {
10302 slprintf(fname
, sizeof(fname
), "\\LISTDIR\\d%d", i
);
10303 if (!NT_STATUS_IS_OK(cli_mkdir(cli
, fname
))) {
10304 fprintf(stderr
,"Failed to open %s\n", fname
);
10309 /* Now ensure that doing an old list sees both files and directories. */
10311 cli_list_old(cli
, "\\LISTDIR\\*", FILE_ATTRIBUTE_DIRECTORY
, list_fn
, &num_seen
);
10312 printf("num_seen = %d\n", num_seen
);
10313 /* We should see 100 files + 1000 directories + . and .. */
10314 if (num_seen
!= 2002)
10317 /* Ensure if we have the "must have" bits we only see the
10318 * relevant entries.
10321 cli_list_old(cli
, "\\LISTDIR\\*", (FILE_ATTRIBUTE_DIRECTORY
<<8)|FILE_ATTRIBUTE_DIRECTORY
, list_fn
, &num_seen
);
10322 printf("num_seen = %d\n", num_seen
);
10323 if (num_seen
!= 1002)
10327 cli_list_old(cli
, "\\LISTDIR\\*", (FILE_ATTRIBUTE_ARCHIVE
<<8)|FILE_ATTRIBUTE_DIRECTORY
, list_fn
, &num_seen
);
10328 printf("num_seen = %d\n", num_seen
);
10329 if (num_seen
!= 1000)
10332 /* Delete everything. */
10333 cli_list(cli
, "\\LISTDIR\\*", 0, del_fn
, cli
);
10334 cli_list(cli
, "\\LISTDIR\\*", FILE_ATTRIBUTE_DIRECTORY
, del_fn
, cli
);
10335 cli_rmdir(cli
, "\\LISTDIR");
10338 printf("Matched %d\n", cli_list(cli
, "a*.*", 0, list_fn
, NULL
));
10339 printf("Matched %d\n", cli_list(cli
, "b*.*", 0, list_fn
, NULL
));
10340 printf("Matched %d\n", cli_list(cli
, "xyzabc", 0, list_fn
, NULL
));
10343 if (!torture_close_connection(cli
)) {
10347 printf("finished dirtest1\n");
10352 static bool run_error_map_extract(int dummy
) {
10354 static struct cli_state
*c_dos
;
10355 static struct cli_state
*c_nt
;
10363 NTSTATUS nt_status
;
10367 /* NT-Error connection */
10369 disable_spnego
= true;
10370 if (!(c_nt
= open_nbt_connection())) {
10371 disable_spnego
= false;
10374 disable_spnego
= false;
10376 status
= smbXcli_negprot(c_nt
->conn
,
10384 if (!NT_STATUS_IS_OK(status
)) {
10385 printf("%s rejected the NT-error negprot (%s)\n", host
,
10386 nt_errstr(status
));
10387 cli_shutdown(c_nt
);
10391 status
= cli_session_setup_anon(c_nt
);
10392 if (!NT_STATUS_IS_OK(status
)) {
10393 printf("%s rejected the NT-error initial session setup (%s)\n",host
, nt_errstr(status
));
10397 /* DOS-Error connection */
10399 disable_spnego
= true;
10400 force_dos_errors
= true;
10401 if (!(c_dos
= open_nbt_connection())) {
10402 disable_spnego
= false;
10403 force_dos_errors
= false;
10406 disable_spnego
= false;
10407 force_dos_errors
= false;
10409 status
= smbXcli_negprot(c_dos
->conn
,
10416 if (!NT_STATUS_IS_OK(status
)) {
10417 printf("%s rejected the DOS-error negprot (%s)\n", host
,
10418 nt_errstr(status
));
10419 cli_shutdown(c_dos
);
10423 status
= cli_session_setup_anon(c_dos
);
10424 if (!NT_STATUS_IS_OK(status
)) {
10425 printf("%s rejected the DOS-error initial session setup (%s)\n",
10426 host
, nt_errstr(status
));
10430 c_nt
->map_dos_errors
= false;
10431 c_dos
->map_dos_errors
= false;
10433 for (error
=(0xc0000000 | 0x1); error
< (0xc0000000| 0xFFF); error
++) {
10434 struct cli_credentials
*user_creds
= NULL
;
10436 fstr_sprintf(user
, "%X", error
);
10438 user_creds
= cli_session_creds_init(talloc_tos(),
10443 false, /* use_kerberos */
10444 false, /* fallback_after_kerberos */
10445 false, /* use_ccache */
10446 false); /* password_is_nt_hash */
10447 if (user_creds
== NULL
) {
10448 printf("cli_session_creds_init(%s) failed\n", user
);
10452 status
= cli_session_setup_creds(c_nt
, user_creds
);
10453 if (NT_STATUS_IS_OK(status
)) {
10454 printf("/** Session setup succeeded. This shouldn't happen...*/\n");
10457 /* Case #1: 32-bit NT errors */
10458 if (!NT_STATUS_IS_DOS(status
)) {
10459 nt_status
= status
;
10461 printf("/** Dos error on NT connection! (%s) */\n",
10462 nt_errstr(status
));
10463 nt_status
= NT_STATUS(0xc0000000);
10466 status
= cli_session_setup_creds(c_dos
, user_creds
);
10467 if (NT_STATUS_IS_OK(status
)) {
10468 printf("/** Session setup succeeded. This shouldn't happen...*/\n");
10471 /* Case #1: 32-bit NT errors */
10472 if (NT_STATUS_IS_DOS(status
)) {
10473 printf("/** NT error on DOS connection! (%s) */\n",
10474 nt_errstr(status
));
10475 errnum
= errclass
= 0;
10477 errclass
= NT_STATUS_DOS_CLASS(status
);
10478 errnum
= NT_STATUS_DOS_CODE(status
);
10481 if (NT_STATUS_V(nt_status
) != error
) {
10482 printf("/*\t{ This NT error code was 'sqashed'\n\t from %s to %s \n\t during the session setup }\n*/\n",
10483 get_nt_error_c_code(talloc_tos(), NT_STATUS(error
)),
10484 get_nt_error_c_code(talloc_tos(), nt_status
));
10487 printf("\t{%s,\t%s,\t%s},\n",
10488 smb_dos_err_class(errclass
),
10489 smb_dos_err_name(errclass
, errnum
),
10490 get_nt_error_c_code(talloc_tos(), NT_STATUS(error
)));
10492 TALLOC_FREE(user_creds
);
10497 static bool run_sesssetup_bench(int dummy
)
10499 static struct cli_state
*c
;
10500 const char *fname
= "\\file.dat";
10505 if (!torture_open_connection(&c
, 0)) {
10509 status
= cli_ntcreate(c
, fname
, 0, GENERIC_ALL_ACCESS
|DELETE_ACCESS
,
10510 FILE_ATTRIBUTE_NORMAL
, 0, FILE_OVERWRITE_IF
,
10511 FILE_DELETE_ON_CLOSE
, 0, &fnum
, NULL
);
10512 if (!NT_STATUS_IS_OK(status
)) {
10513 d_printf("open %s failed: %s\n", fname
, nt_errstr(status
));
10517 for (i
=0; i
<torture_numops
; i
++) {
10518 status
= cli_session_setup_creds(c
, torture_creds
);
10519 if (!NT_STATUS_IS_OK(status
)) {
10520 d_printf("(%s) cli_session_setup_creds failed: %s\n",
10521 __location__
, nt_errstr(status
));
10525 d_printf("\r%d ", (int)cli_state_get_uid(c
));
10527 status
= cli_ulogoff(c
);
10528 if (!NT_STATUS_IS_OK(status
)) {
10529 d_printf("(%s) cli_ulogoff failed: %s\n",
10530 __location__
, nt_errstr(status
));
10538 static bool subst_test(const char *str
, const char *user
, const char *domain
,
10539 uid_t uid
, gid_t gid
, const char *expected
)
10542 bool result
= true;
10544 subst
= talloc_sub_specified(talloc_tos(), str
, user
, NULL
, domain
, uid
, gid
);
10546 if (strcmp(subst
, expected
) != 0) {
10547 printf("sub_specified(%s, %s, %s, %d, %d) returned [%s], expected "
10548 "[%s]\n", str
, user
, domain
, (int)uid
, (int)gid
, subst
,
10553 TALLOC_FREE(subst
);
10557 static void chain1_open_completion(struct tevent_req
*req
)
10561 status
= cli_openx_recv(req
, &fnum
);
10564 d_printf("cli_openx_recv returned %s: %d\n",
10566 NT_STATUS_IS_OK(status
) ? fnum
: -1);
10569 static void chain1_write_completion(struct tevent_req
*req
)
10573 status
= cli_write_andx_recv(req
, &written
);
10576 d_printf("cli_write_andx_recv returned %s: %d\n",
10578 NT_STATUS_IS_OK(status
) ? (int)written
: -1);
10581 static void chain1_close_completion(struct tevent_req
*req
)
10584 bool *done
= (bool *)tevent_req_callback_data_void(req
);
10586 status
= cli_close_recv(req
);
10591 d_printf("cli_close returned %s\n", nt_errstr(status
));
10594 static bool run_chain1(int dummy
)
10596 struct cli_state
*cli1
;
10597 struct tevent_context
*evt
= samba_tevent_context_init(NULL
);
10598 struct tevent_req
*reqs
[3], *smbreqs
[3];
10600 const char *str
= "foobar";
10601 const char *fname
= "\\test_chain";
10604 printf("starting chain1 test\n");
10605 if (!torture_open_connection(&cli1
, 0)) {
10609 smbXcli_conn_set_sockopt(cli1
->conn
, sockops
);
10611 cli_unlink(cli1
, fname
, FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
);
10613 reqs
[0] = cli_openx_create(talloc_tos(), evt
, cli1
, fname
,
10614 O_CREAT
|O_RDWR
, 0, &smbreqs
[0]);
10615 if (reqs
[0] == NULL
) return false;
10616 tevent_req_set_callback(reqs
[0], chain1_open_completion
, NULL
);
10619 reqs
[1] = cli_write_andx_create(talloc_tos(), evt
, cli1
, 0, 0,
10620 (const uint8_t *)str
, 0, strlen(str
)+1,
10621 smbreqs
, 1, &smbreqs
[1]);
10622 if (reqs
[1] == NULL
) return false;
10623 tevent_req_set_callback(reqs
[1], chain1_write_completion
, NULL
);
10625 reqs
[2] = cli_smb1_close_create(talloc_tos(), evt
, cli1
, 0, &smbreqs
[2]);
10626 if (reqs
[2] == NULL
) return false;
10627 tevent_req_set_callback(reqs
[2], chain1_close_completion
, &done
);
10629 status
= smb1cli_req_chain_submit(smbreqs
, ARRAY_SIZE(smbreqs
));
10630 if (!NT_STATUS_IS_OK(status
)) {
10635 tevent_loop_once(evt
);
10638 torture_close_connection(cli1
);
10642 static void chain2_sesssetup_completion(struct tevent_req
*req
)
10645 status
= cli_session_setup_guest_recv(req
);
10646 d_printf("sesssetup returned %s\n", nt_errstr(status
));
10649 static void chain2_tcon_completion(struct tevent_req
*req
)
10651 bool *done
= (bool *)tevent_req_callback_data_void(req
);
10653 status
= cli_tcon_andx_recv(req
);
10654 d_printf("tcon_and_x returned %s\n", nt_errstr(status
));
10658 static bool run_chain2(int dummy
)
10660 struct cli_state
*cli1
;
10661 struct tevent_context
*evt
= samba_tevent_context_init(NULL
);
10662 struct tevent_req
*reqs
[2], *smbreqs
[2];
10665 int flags
= CLI_FULL_CONNECTION_FORCE_SMB1
;
10667 printf("starting chain2 test\n");
10668 status
= cli_start_connection(talloc_tos(),
10674 SMB_SIGNING_DEFAULT
,
10676 if (!NT_STATUS_IS_OK(status
)) {
10680 smbXcli_conn_set_sockopt(cli1
->conn
, sockops
);
10682 reqs
[0] = cli_session_setup_guest_create(talloc_tos(), evt
, cli1
,
10684 if (reqs
[0] == NULL
) return false;
10685 tevent_req_set_callback(reqs
[0], chain2_sesssetup_completion
, NULL
);
10687 reqs
[1] = cli_tcon_andx_create(talloc_tos(), evt
, cli1
, "IPC$",
10688 "?????", NULL
, 0, &smbreqs
[1]);
10689 if (reqs
[1] == NULL
) return false;
10690 tevent_req_set_callback(reqs
[1], chain2_tcon_completion
, &done
);
10692 status
= smb1cli_req_chain_submit(smbreqs
, ARRAY_SIZE(smbreqs
));
10693 if (!NT_STATUS_IS_OK(status
)) {
10698 tevent_loop_once(evt
);
10701 torture_close_connection(cli1
);
10706 struct torture_createdel_state
{
10707 struct tevent_context
*ev
;
10708 struct cli_state
*cli
;
10711 static void torture_createdel_created(struct tevent_req
*subreq
);
10712 static void torture_createdel_closed(struct tevent_req
*subreq
);
10714 static struct tevent_req
*torture_createdel_send(TALLOC_CTX
*mem_ctx
,
10715 struct tevent_context
*ev
,
10716 struct cli_state
*cli
,
10719 struct tevent_req
*req
, *subreq
;
10720 struct torture_createdel_state
*state
;
10722 req
= tevent_req_create(mem_ctx
, &state
,
10723 struct torture_createdel_state
);
10730 subreq
= cli_ntcreate_send(
10731 state
, ev
, cli
, name
, 0,
10732 FILE_READ_DATA
|FILE_WRITE_DATA
|DELETE_ACCESS
,
10733 FILE_ATTRIBUTE_NORMAL
,
10734 FILE_SHARE_READ
|FILE_SHARE_WRITE
|FILE_SHARE_DELETE
,
10735 FILE_OPEN_IF
, FILE_DELETE_ON_CLOSE
,
10736 SMB2_IMPERSONATION_IMPERSONATION
, 0);
10738 if (tevent_req_nomem(subreq
, req
)) {
10739 return tevent_req_post(req
, ev
);
10741 tevent_req_set_callback(subreq
, torture_createdel_created
, req
);
10745 static void torture_createdel_created(struct tevent_req
*subreq
)
10747 struct tevent_req
*req
= tevent_req_callback_data(
10748 subreq
, struct tevent_req
);
10749 struct torture_createdel_state
*state
= tevent_req_data(
10750 req
, struct torture_createdel_state
);
10754 status
= cli_ntcreate_recv(subreq
, &fnum
, NULL
);
10755 TALLOC_FREE(subreq
);
10756 if (tevent_req_nterror(req
, status
)) {
10757 DEBUG(10, ("cli_ntcreate_recv returned %s\n",
10758 nt_errstr(status
)));
10762 subreq
= cli_close_send(state
, state
->ev
, state
->cli
, fnum
, 0);
10763 if (tevent_req_nomem(subreq
, req
)) {
10766 tevent_req_set_callback(subreq
, torture_createdel_closed
, req
);
10769 static void torture_createdel_closed(struct tevent_req
*subreq
)
10771 struct tevent_req
*req
= tevent_req_callback_data(
10772 subreq
, struct tevent_req
);
10775 status
= cli_close_recv(subreq
);
10776 if (tevent_req_nterror(req
, status
)) {
10777 DEBUG(10, ("cli_close_recv returned %s\n", nt_errstr(status
)));
10780 tevent_req_done(req
);
10783 static NTSTATUS
torture_createdel_recv(struct tevent_req
*req
)
10785 return tevent_req_simple_recv_ntstatus(req
);
10788 struct torture_createdels_state
{
10789 struct tevent_context
*ev
;
10790 struct cli_state
*cli
;
10791 const char *base_name
;
10795 struct tevent_req
**reqs
;
10798 static void torture_createdels_done(struct tevent_req
*subreq
);
10800 static struct tevent_req
*torture_createdels_send(TALLOC_CTX
*mem_ctx
,
10801 struct tevent_context
*ev
,
10802 struct cli_state
*cli
,
10803 const char *base_name
,
10807 struct tevent_req
*req
;
10808 struct torture_createdels_state
*state
;
10811 req
= tevent_req_create(mem_ctx
, &state
,
10812 struct torture_createdels_state
);
10818 state
->base_name
= talloc_strdup(state
, base_name
);
10819 if (tevent_req_nomem(state
->base_name
, req
)) {
10820 return tevent_req_post(req
, ev
);
10822 state
->num_files
= MAX(num_parallel
, num_files
);
10824 state
->received
= 0;
10826 state
->reqs
= talloc_array(state
, struct tevent_req
*, num_parallel
);
10827 if (tevent_req_nomem(state
->reqs
, req
)) {
10828 return tevent_req_post(req
, ev
);
10831 for (i
=0; i
<num_parallel
; i
++) {
10834 name
= talloc_asprintf(state
, "%s%8.8d", state
->base_name
,
10836 if (tevent_req_nomem(name
, req
)) {
10837 return tevent_req_post(req
, ev
);
10839 state
->reqs
[i
] = torture_createdel_send(
10840 state
->reqs
, state
->ev
, state
->cli
, name
);
10841 if (tevent_req_nomem(state
->reqs
[i
], req
)) {
10842 return tevent_req_post(req
, ev
);
10844 name
= talloc_move(state
->reqs
[i
], &name
);
10845 tevent_req_set_callback(state
->reqs
[i
],
10846 torture_createdels_done
, req
);
10852 static void torture_createdels_done(struct tevent_req
*subreq
)
10854 struct tevent_req
*req
= tevent_req_callback_data(
10855 subreq
, struct tevent_req
);
10856 struct torture_createdels_state
*state
= tevent_req_data(
10857 req
, struct torture_createdels_state
);
10858 size_t i
, num_parallel
= talloc_array_length(state
->reqs
);
10862 status
= torture_createdel_recv(subreq
);
10863 if (!NT_STATUS_IS_OK(status
)){
10864 DEBUG(10, ("torture_createdel_recv returned %s\n",
10865 nt_errstr(status
)));
10866 TALLOC_FREE(subreq
);
10867 tevent_req_nterror(req
, status
);
10871 for (i
=0; i
<num_parallel
; i
++) {
10872 if (subreq
== state
->reqs
[i
]) {
10876 if (i
== num_parallel
) {
10877 DEBUG(10, ("received something we did not send\n"));
10878 tevent_req_nterror(req
, NT_STATUS_INTERNAL_ERROR
);
10881 TALLOC_FREE(state
->reqs
[i
]);
10883 if (state
->sent
>= state
->num_files
) {
10884 tevent_req_done(req
);
10888 name
= talloc_asprintf(state
, "%s%8.8d", state
->base_name
,
10890 if (tevent_req_nomem(name
, req
)) {
10893 state
->reqs
[i
] = torture_createdel_send(state
->reqs
, state
->ev
,
10895 if (tevent_req_nomem(state
->reqs
[i
], req
)) {
10898 name
= talloc_move(state
->reqs
[i
], &name
);
10899 tevent_req_set_callback(state
->reqs
[i
], torture_createdels_done
, req
);
10903 static NTSTATUS
torture_createdels_recv(struct tevent_req
*req
)
10905 return tevent_req_simple_recv_ntstatus(req
);
10908 struct swallow_notify_state
{
10909 struct tevent_context
*ev
;
10910 struct cli_state
*cli
;
10912 uint32_t completion_filter
;
10914 bool (*fn
)(uint32_t action
, const char *name
, void *priv
);
10918 static void swallow_notify_done(struct tevent_req
*subreq
);
10920 static struct tevent_req
*swallow_notify_send(TALLOC_CTX
*mem_ctx
,
10921 struct tevent_context
*ev
,
10922 struct cli_state
*cli
,
10924 uint32_t completion_filter
,
10926 bool (*fn
)(uint32_t action
,
10931 struct tevent_req
*req
, *subreq
;
10932 struct swallow_notify_state
*state
;
10934 req
= tevent_req_create(mem_ctx
, &state
,
10935 struct swallow_notify_state
);
10941 state
->fnum
= fnum
;
10942 state
->completion_filter
= completion_filter
;
10943 state
->recursive
= recursive
;
10945 state
->priv
= priv
;
10947 subreq
= cli_notify_send(state
, state
->ev
, state
->cli
, state
->fnum
,
10948 0xffff, state
->completion_filter
,
10950 if (tevent_req_nomem(subreq
, req
)) {
10951 return tevent_req_post(req
, ev
);
10953 tevent_req_set_callback(subreq
, swallow_notify_done
, req
);
10957 static void swallow_notify_done(struct tevent_req
*subreq
)
10959 struct tevent_req
*req
= tevent_req_callback_data(
10960 subreq
, struct tevent_req
);
10961 struct swallow_notify_state
*state
= tevent_req_data(
10962 req
, struct swallow_notify_state
);
10964 uint32_t i
, num_changes
;
10965 struct notify_change
*changes
;
10967 status
= cli_notify_recv(subreq
, state
, &num_changes
, &changes
);
10968 TALLOC_FREE(subreq
);
10969 if (!NT_STATUS_IS_OK(status
)) {
10970 DEBUG(10, ("cli_notify_recv returned %s\n",
10971 nt_errstr(status
)));
10972 tevent_req_nterror(req
, status
);
10976 for (i
=0; i
<num_changes
; i
++) {
10977 state
->fn(changes
[i
].action
, changes
[i
].name
, state
->priv
);
10979 TALLOC_FREE(changes
);
10981 subreq
= cli_notify_send(state
, state
->ev
, state
->cli
, state
->fnum
,
10982 0xffff, state
->completion_filter
,
10984 if (tevent_req_nomem(subreq
, req
)) {
10987 tevent_req_set_callback(subreq
, swallow_notify_done
, req
);
10990 static bool print_notifies(uint32_t action
, const char *name
, void *priv
)
10992 if (DEBUGLEVEL
> 5) {
10993 d_printf("%d %s\n", (int)action
, name
);
10998 static void notify_bench_done(struct tevent_req
*req
)
11000 int *num_finished
= (int *)tevent_req_callback_data_void(req
);
11001 *num_finished
+= 1;
11004 static bool run_notify_bench(int dummy
)
11006 const char *dname
= "\\notify-bench";
11007 struct tevent_context
*ev
;
11010 struct tevent_req
*req1
;
11011 struct tevent_req
*req2
= NULL
;
11012 int i
, num_unc_names
;
11013 int num_finished
= 0;
11015 printf("starting notify-bench test\n");
11017 if (use_multishare_conn
) {
11019 unc_list
= file_lines_load(multishare_conn_fname
,
11020 &num_unc_names
, 0, NULL
);
11021 if (!unc_list
|| num_unc_names
<= 0) {
11022 d_printf("Failed to load unc names list from '%s'\n",
11023 multishare_conn_fname
);
11026 TALLOC_FREE(unc_list
);
11031 ev
= samba_tevent_context_init(talloc_tos());
11033 d_printf("tevent_context_init failed\n");
11037 for (i
=0; i
<num_unc_names
; i
++) {
11038 struct cli_state
*cli
;
11041 base_fname
= talloc_asprintf(talloc_tos(), "%s\\file%3.3d.",
11043 if (base_fname
== NULL
) {
11047 if (!torture_open_connection(&cli
, i
)) {
11051 status
= cli_ntcreate(cli
, dname
, 0,
11052 MAXIMUM_ALLOWED_ACCESS
,
11053 0, FILE_SHARE_READ
|FILE_SHARE_WRITE
|
11055 FILE_OPEN_IF
, FILE_DIRECTORY_FILE
, 0,
11058 if (!NT_STATUS_IS_OK(status
)) {
11059 d_printf("Could not create %s: %s\n", dname
,
11060 nt_errstr(status
));
11064 req1
= swallow_notify_send(talloc_tos(), ev
, cli
, dnum
,
11065 FILE_NOTIFY_CHANGE_FILE_NAME
|
11066 FILE_NOTIFY_CHANGE_DIR_NAME
|
11067 FILE_NOTIFY_CHANGE_ATTRIBUTES
|
11068 FILE_NOTIFY_CHANGE_LAST_WRITE
,
11069 false, print_notifies
, NULL
);
11070 if (req1
== NULL
) {
11071 d_printf("Could not create notify request\n");
11075 req2
= torture_createdels_send(talloc_tos(), ev
, cli
,
11076 base_fname
, 10, torture_numops
);
11077 if (req2
== NULL
) {
11078 d_printf("Could not create createdels request\n");
11081 TALLOC_FREE(base_fname
);
11083 tevent_req_set_callback(req2
, notify_bench_done
,
11087 while (num_finished
< num_unc_names
) {
11089 ret
= tevent_loop_once(ev
);
11091 d_printf("tevent_loop_once failed\n");
11096 if (!tevent_req_poll(req2
, ev
)) {
11097 d_printf("tevent_req_poll failed\n");
11100 status
= torture_createdels_recv(req2
);
11101 d_printf("torture_createdels_recv returned %s\n", nt_errstr(status
));
11106 static bool run_mangle1(int dummy
)
11108 struct cli_state
*cli
;
11109 const char *fname
= "this_is_a_long_fname_to_be_mangled.txt";
11114 printf("starting mangle1 test\n");
11115 if (!torture_open_connection(&cli
, 0)) {
11119 smbXcli_conn_set_sockopt(cli
->conn
, sockops
);
11121 status
= cli_ntcreate(cli
, fname
, 0, GENERIC_ALL_ACCESS
|DELETE_ACCESS
,
11122 FILE_ATTRIBUTE_NORMAL
, 0, FILE_OVERWRITE_IF
,
11123 0, 0, &fnum
, NULL
);
11124 if (!NT_STATUS_IS_OK(status
)) {
11125 d_printf("open %s failed: %s\n", fname
, nt_errstr(status
));
11128 cli_close(cli
, fnum
);
11130 status
= cli_qpathinfo_alt_name(cli
, fname
, alt_name
);
11131 if (!NT_STATUS_IS_OK(status
)) {
11132 d_printf("cli_qpathinfo_alt_name failed: %s\n",
11133 nt_errstr(status
));
11136 d_printf("alt_name: %s\n", alt_name
);
11138 status
= cli_openx(cli
, alt_name
, O_RDONLY
, DENY_NONE
, &fnum
);
11139 if (!NT_STATUS_IS_OK(status
)) {
11140 d_printf("cli_openx(%s) failed: %s\n", alt_name
,
11141 nt_errstr(status
));
11144 cli_close(cli
, fnum
);
11146 status
= cli_qpathinfo1(cli
, alt_name
, NULL
, NULL
, NULL
, NULL
, NULL
);
11147 if (!NT_STATUS_IS_OK(status
)) {
11148 d_printf("cli_qpathinfo1(%s) failed: %s\n", alt_name
,
11149 nt_errstr(status
));
11156 static NTSTATUS
mangle_illegal_list_shortname_fn(struct file_info
*f
,
11160 if (f
->short_name
== NULL
) {
11161 return NT_STATUS_OK
;
11164 if (strlen(f
->short_name
) == 0) {
11165 return NT_STATUS_OK
;
11168 printf("unexpected shortname: %s\n", f
->short_name
);
11170 return NT_STATUS_OBJECT_NAME_INVALID
;
11173 static NTSTATUS
mangle_illegal_list_name_fn(struct file_info
*f
,
11177 char *name
= state
;
11179 printf("name: %s\n", f
->name
);
11180 fstrcpy(name
, f
->name
);
11181 return NT_STATUS_OK
;
11184 static bool run_mangle_illegal(int dummy
)
11186 struct cli_state
*cli
= NULL
;
11187 struct cli_state
*cli_posix
= NULL
;
11188 const char *fname
= "\\MANGLE_ILLEGAL\\this_is_a_long_fname_to_be_mangled.txt";
11189 const char *illegal_fname
= "MANGLE_ILLEGAL/foo:bar";
11190 char *mangled_path
= NULL
;
11196 printf("starting mangle-illegal test\n");
11198 if (!torture_open_connection(&cli
, 0)) {
11202 smbXcli_conn_set_sockopt(cli
->conn
, sockops
);
11204 if (!torture_open_connection(&cli_posix
, 0)) {
11208 smbXcli_conn_set_sockopt(cli_posix
->conn
, sockops
);
11210 status
= torture_setup_unix_extensions(cli_posix
);
11211 if (!NT_STATUS_IS_OK(status
)) {
11215 cli_rmdir(cli
, "\\MANGLE_ILLEGAL");
11216 status
= cli_mkdir(cli
, "\\MANGLE_ILLEGAL");
11217 if (!NT_STATUS_IS_OK(status
)) {
11218 printf("mkdir1 failed : %s\n", nt_errstr(status
));
11223 * Create a file with illegal NTFS characters and test that we
11224 * get a usable mangled name
11227 cli_setatr(cli_posix
, illegal_fname
, 0, 0);
11228 cli_posix_unlink(cli_posix
, illegal_fname
);
11230 status
= cli_posix_open(cli_posix
, illegal_fname
, O_RDWR
|O_CREAT
|O_EXCL
,
11232 if (!NT_STATUS_IS_OK(status
)) {
11233 printf("POSIX create of %s failed (%s)\n",
11234 illegal_fname
, nt_errstr(status
));
11238 status
= cli_close(cli_posix
, fnum
);
11239 if (!NT_STATUS_IS_OK(status
)) {
11240 printf("close failed (%s)\n", nt_errstr(status
));
11244 status
= cli_list(cli
, "\\MANGLE_ILLEGAL\\*", 0, mangle_illegal_list_name_fn
, &name
);
11245 if (!NT_STATUS_IS_OK(status
)) {
11246 d_printf("cli_list failed: %s\n", nt_errstr(status
));
11250 mangled_path
= talloc_asprintf(talloc_tos(), "\\MANGLE_ILLEGAL\\%s", name
);
11251 if (mangled_path
== NULL
) {
11255 status
= cli_openx(cli
, mangled_path
, O_RDONLY
, DENY_NONE
, &fnum
);
11256 if (!NT_STATUS_IS_OK(status
)) {
11257 d_printf("cli_openx(%s) failed: %s\n", mangled_path
, nt_errstr(status
));
11258 TALLOC_FREE(mangled_path
);
11261 TALLOC_FREE(mangled_path
);
11262 cli_close(cli
, fnum
);
11264 cli_setatr(cli_posix
, illegal_fname
, 0, 0);
11265 cli_posix_unlink(cli_posix
, illegal_fname
);
11268 * Create a file with a long name and check that we got *no* short name.
11271 status
= cli_ntcreate(cli
, fname
, 0, GENERIC_ALL_ACCESS
|DELETE_ACCESS
,
11272 FILE_ATTRIBUTE_NORMAL
, 0, FILE_OVERWRITE_IF
,
11273 0, 0, &fnum
, NULL
);
11274 if (!NT_STATUS_IS_OK(status
)) {
11275 d_printf("open %s failed: %s\n", fname
, nt_errstr(status
));
11278 cli_close(cli
, fnum
);
11280 status
= cli_list(cli
, fname
, 0, mangle_illegal_list_shortname_fn
, &alt_name
);
11281 if (!NT_STATUS_IS_OK(status
)) {
11282 d_printf("cli_list failed\n");
11286 cli_unlink(cli
, fname
, 0);
11287 cli_rmdir(cli
, "\\MANGLE_ILLEGAL");
11289 if (!torture_close_connection(cli_posix
)) {
11293 if (!torture_close_connection(cli
)) {
11300 static size_t null_source(uint8_t *buf
, size_t n
, void *priv
)
11302 size_t *to_pull
= (size_t *)priv
;
11303 size_t thistime
= *to_pull
;
11305 thistime
= MIN(thistime
, n
);
11306 if (thistime
== 0) {
11310 memset(buf
, 0, thistime
);
11311 *to_pull
-= thistime
;
11315 static bool run_windows_write(int dummy
)
11317 struct cli_state
*cli1
;
11321 const char *fname
= "\\writetest.txt";
11322 struct timeval start_time
;
11327 printf("starting windows_write test\n");
11328 if (!torture_open_connection(&cli1
, 0)) {
11332 status
= cli_openx(cli1
, fname
, O_RDWR
|O_CREAT
|O_EXCL
, DENY_NONE
, &fnum
);
11333 if (!NT_STATUS_IS_OK(status
)) {
11334 printf("open failed (%s)\n", nt_errstr(status
));
11338 smbXcli_conn_set_sockopt(cli1
->conn
, sockops
);
11340 start_time
= timeval_current();
11342 for (i
=0; i
<torture_numops
; i
++) {
11344 off_t start
= i
* torture_blocksize
;
11345 size_t to_pull
= torture_blocksize
- 1;
11347 status
= cli_writeall(cli1
, fnum
, 0, &c
,
11348 start
+ torture_blocksize
- 1, 1, NULL
);
11349 if (!NT_STATUS_IS_OK(status
)) {
11350 printf("cli_write failed: %s\n", nt_errstr(status
));
11354 status
= cli_push(cli1
, fnum
, 0, i
* torture_blocksize
, torture_blocksize
,
11355 null_source
, &to_pull
);
11356 if (!NT_STATUS_IS_OK(status
)) {
11357 printf("cli_push returned: %s\n", nt_errstr(status
));
11362 seconds
= timeval_elapsed(&start_time
);
11363 kbytes
= (double)torture_blocksize
* torture_numops
;
11366 printf("Wrote %d kbytes in %.2f seconds: %d kb/sec\n", (int)kbytes
,
11367 (double)seconds
, (int)(kbytes
/seconds
));
11371 cli_close(cli1
, fnum
);
11372 cli_unlink(cli1
, fname
, FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
);
11373 torture_close_connection(cli1
);
11377 static size_t calc_expected_return(struct cli_state
*cli
, size_t len_requested
)
11379 size_t max_pdu
= 0x1FFFF;
11381 if (cli
->server_posix_capabilities
& CIFS_UNIX_LARGE_READ_CAP
) {
11382 max_pdu
= 0xFFFFFF;
11385 if (smb1cli_conn_signing_is_active(cli
->conn
)) {
11389 if (smb1cli_conn_encryption_on(cli
->conn
)) {
11390 max_pdu
= CLI_BUFFER_SIZE
;
11393 if ((len_requested
& 0xFFFF0000) == 0xFFFF0000) {
11394 len_requested
&= 0xFFFF;
11397 return MIN(len_requested
,
11398 max_pdu
- (MIN_SMB_SIZE
+ VWV(12) + 1 /* padding byte */));
11401 static bool check_read_call(struct cli_state
*cli
,
11404 size_t len_requested
)
11407 struct tevent_req
*subreq
= NULL
;
11408 ssize_t len_read
= 0;
11409 size_t len_expected
= 0;
11410 struct tevent_context
*ev
= NULL
;
11412 ev
= samba_tevent_context_init(talloc_tos());
11417 subreq
= cli_read_andx_send(talloc_tos(),
11424 if (!tevent_req_poll_ntstatus(subreq
, ev
, &status
)) {
11428 status
= cli_read_andx_recv(subreq
, &len_read
, &buf
);
11429 if (!NT_STATUS_IS_OK(status
)) {
11430 d_printf("cli_read_andx_recv failed: %s\n", nt_errstr(status
));
11434 TALLOC_FREE(subreq
);
11437 len_expected
= calc_expected_return(cli
, len_requested
);
11439 if (len_expected
> 0x10000 && len_read
== 0x10000) {
11440 /* Windows servers only return a max of 0x10000,
11441 doesn't matter if you set CAP_LARGE_READX in
11442 the client sessionsetupX call or not. */
11443 d_printf("Windows server - returned 0x10000 on a read of 0x%x\n",
11444 (unsigned int)len_requested
);
11445 } else if (len_read
!= len_expected
) {
11446 d_printf("read of 0x%x failed: got 0x%x, expected 0x%x\n",
11447 (unsigned int)len_requested
,
11448 (unsigned int)len_read
,
11449 (unsigned int)len_expected
);
11452 d_printf("Correct read reply.\n");
11458 /* Test large readX variants. */
11459 static bool large_readx_tests(struct cli_state
*cli
,
11463 /* A read of 0xFFFF0001 should *always* return 1 byte. */
11464 if (check_read_call(cli
, fnum
, buf
, 0xFFFF0001) == false) {
11467 /* A read of 0x10000 should return 0x10000 bytes. */
11468 if (check_read_call(cli
, fnum
, buf
, 0x10000) == false) {
11471 /* A read of 0x10000 should return 0x10001 bytes. */
11472 if (check_read_call(cli
, fnum
, buf
, 0x10001) == false) {
11475 /* A read of 0x1FFFF - (MIN_SMB_SIZE + VWV(12) should return
11476 the requested number of bytes. */
11477 if (check_read_call(cli
, fnum
, buf
, 0x1FFFF - (MIN_SMB_SIZE
+ VWV(12))) == false) {
11480 /* A read of 1MB should return 1MB bytes (on Samba). */
11481 if (check_read_call(cli
, fnum
, buf
, 0x100000) == false) {
11485 if (check_read_call(cli
, fnum
, buf
, 0x20001) == false) {
11488 if (check_read_call(cli
, fnum
, buf
, 0x22000001) == false) {
11491 if (check_read_call(cli
, fnum
, buf
, 0xFFFE0001) == false) {
11497 static bool run_large_readx(int dummy
)
11499 uint8_t *buf
= NULL
;
11500 struct cli_state
*cli1
= NULL
;
11501 struct cli_state
*cli2
= NULL
;
11502 bool correct
= false;
11503 const char *fname
= "\\large_readx.dat";
11505 uint16_t fnum1
= UINT16_MAX
;
11506 uint32_t normal_caps
= 0;
11507 size_t file_size
= 20*1024*1024;
11508 TALLOC_CTX
*frame
= talloc_stackframe();
11512 enum smb_signing_setting signing_setting
;
11513 enum protocol_types protocol
;
11517 .signing_setting
= SMB_SIGNING_IF_REQUIRED
,
11518 .protocol
= PROTOCOL_NT1
,
11520 .name
= "NT1 - SIGNING_REQUIRED",
11521 .signing_setting
= SMB_SIGNING_REQUIRED
,
11522 .protocol
= PROTOCOL_NT1
,
11526 printf("starting large_readx test\n");
11528 if (!torture_open_connection(&cli1
, 0)) {
11532 normal_caps
= smb1cli_conn_capabilities(cli1
->conn
);
11534 if (!(normal_caps
& CAP_LARGE_READX
)) {
11535 d_printf("Server doesn't have CAP_LARGE_READX 0x%x\n",
11536 (unsigned int)normal_caps
);
11540 /* Create a file of size 4MB. */
11541 status
= cli_ntcreate(cli1
, fname
, 0, GENERIC_ALL_ACCESS
,
11542 FILE_ATTRIBUTE_NORMAL
, 0, FILE_OVERWRITE_IF
,
11543 0, 0, &fnum1
, NULL
);
11545 if (!NT_STATUS_IS_OK(status
)) {
11546 d_printf("open %s failed: %s\n", fname
, nt_errstr(status
));
11550 /* Write file_size bytes. */
11551 buf
= talloc_zero_array(frame
, uint8_t, file_size
);
11556 status
= cli_writeall(cli1
,
11563 if (!NT_STATUS_IS_OK(status
)) {
11564 d_printf("cli_writeall failed: %s\n", nt_errstr(status
));
11568 status
= cli_close(cli1
, fnum1
);
11569 if (!NT_STATUS_IS_OK(status
)) {
11570 d_printf("cli_close failed: %s\n", nt_errstr(status
));
11574 fnum1
= UINT16_MAX
;
11576 for (i
=0; i
< ARRAY_SIZE(runs
); i
++) {
11577 enum smb_signing_setting saved_signing_setting
= signing_state
;
11578 uint16_t fnum2
= -1;
11581 (runs
[i
].signing_setting
== SMB_SIGNING_REQUIRED
))
11583 d_printf("skip[%u] - %s\n", (unsigned)i
, runs
[i
].name
);
11587 d_printf("run[%u] - %s\n", (unsigned)i
, runs
[i
].name
);
11589 signing_state
= runs
[i
].signing_setting
;
11590 cli2
= open_nbt_connection();
11591 signing_state
= saved_signing_setting
;
11592 if (cli2
== NULL
) {
11596 status
= smbXcli_negprot(cli2
->conn
,
11603 if (!NT_STATUS_IS_OK(status
)) {
11607 status
= cli_session_setup_creds(cli2
, torture_creds
);
11608 if (!NT_STATUS_IS_OK(status
)) {
11612 status
= cli_tree_connect(cli2
,
11616 if (!NT_STATUS_IS_OK(status
)) {
11620 cli_set_timeout(cli2
, 120000); /* set a really long timeout (2 minutes) */
11622 normal_caps
= smb1cli_conn_capabilities(cli2
->conn
);
11624 if (!(normal_caps
& CAP_LARGE_READX
)) {
11625 d_printf("Server doesn't have CAP_LARGE_READX 0x%x\n",
11626 (unsigned int)normal_caps
);
11631 if (force_cli_encryption(cli2
, share
) == false) {
11634 } else if (SERVER_HAS_UNIX_CIFS(cli2
)) {
11635 uint16_t major
, minor
;
11636 uint32_t caplow
, caphigh
;
11638 status
= cli_unix_extensions_version(cli2
,
11640 &caplow
, &caphigh
);
11641 if (!NT_STATUS_IS_OK(status
)) {
11646 status
= cli_ntcreate(cli2
, fname
, 0, FILE_READ_DATA
,
11647 FILE_ATTRIBUTE_NORMAL
, 0, FILE_OPEN
,
11648 0, 0, &fnum2
, NULL
);
11649 if (!NT_STATUS_IS_OK(status
)) {
11650 d_printf("Second open %s failed: %s\n", fname
, nt_errstr(status
));
11654 /* All reads must return less than file_size bytes. */
11655 if (!large_readx_tests(cli2
, fnum2
, buf
)) {
11659 status
= cli_close(cli2
, fnum2
);
11660 if (!NT_STATUS_IS_OK(status
)) {
11661 d_printf("cli_close failed: %s\n", nt_errstr(status
));
11666 if (!torture_close_connection(cli2
)) {
11673 printf("Success on large_readx test\n");
11678 if (!torture_close_connection(cli2
)) {
11684 if (fnum1
!= UINT16_MAX
) {
11685 status
= cli_close(cli1
, fnum1
);
11686 if (!NT_STATUS_IS_OK(status
)) {
11687 d_printf("cli_close failed: %s\n", nt_errstr(status
));
11689 fnum1
= UINT16_MAX
;
11692 status
= cli_unlink(cli1
, fname
,
11693 FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
);
11694 if (!NT_STATUS_IS_OK(status
)) {
11695 printf("unlink failed (%s)\n", nt_errstr(status
));
11698 if (!torture_close_connection(cli1
)) {
11703 TALLOC_FREE(frame
);
11705 printf("finished large_readx test\n");
11709 static NTSTATUS
msdfs_attribute_list_fn(struct file_info
*finfo
,
11711 void *private_data
)
11713 uint32_t *p_attr
= (uint32_t *)private_data
;
11715 if (strequal(finfo
->name
, test_filename
)) {
11716 *p_attr
= finfo
->attr
;
11719 return NT_STATUS_OK
;
11722 static bool run_msdfs_attribute(int dummy
)
11724 static struct cli_state
*cli
;
11725 bool correct
= false;
11729 printf("Starting MSDFS-ATTRIBUTE test\n");
11731 if (test_filename
== NULL
|| test_filename
[0] == '\0') {
11732 printf("MSDFS-ATTRIBUTE test "
11733 "needs -f filename-of-msdfs-link\n");
11738 * NB. We use torture_open_connection_flags() not
11739 * torture_open_connection() as the latter forces
11742 if (!torture_open_connection_flags(&cli
, 0, 0)) {
11746 smbXcli_conn_set_sockopt(cli
->conn
, sockops
);
11748 status
= cli_list(cli
,
11750 FILE_ATTRIBUTE_DIRECTORY
,
11751 msdfs_attribute_list_fn
,
11754 if (!NT_STATUS_IS_OK(status
)) {
11755 printf("cli_list failed with %s\n",
11756 nt_errstr(status
));
11759 if ((attr
& FILE_ATTRIBUTE_REPARSE_POINT
) == 0) {
11760 printf("file %s should have "
11761 "FILE_ATTRIBUTE_REPARSE_POINT set. attr = 0x%x\n",
11763 (unsigned int)attr
);
11767 if ((attr
& FILE_ATTRIBUTE_DIRECTORY
) == 0) {
11768 printf("file %s should have "
11769 "FILE_ATTRIBUTE_DIRECTORY set. attr = 0x%x\n",
11771 (unsigned int)attr
);
11779 torture_close_connection(cli
);
11783 static bool run_cli_echo(int dummy
)
11785 struct cli_state
*cli
;
11788 printf("starting cli_echo test\n");
11789 if (!torture_open_connection(&cli
, 0)) {
11792 smbXcli_conn_set_sockopt(cli
->conn
, sockops
);
11794 status
= cli_echo(cli
, 5, data_blob_const("hello", 5));
11796 d_printf("cli_echo returned %s\n", nt_errstr(status
));
11798 torture_close_connection(cli
);
11799 return NT_STATUS_IS_OK(status
);
11802 static int splice_status(off_t written
, void *priv
)
11807 static bool run_cli_splice(int dummy
)
11809 uint8_t *buf
= NULL
;
11810 struct cli_state
*cli1
= NULL
;
11811 bool correct
= false;
11812 const char *fname_src
= "\\splice_src.dat";
11813 const char *fname_dst
= "\\splice_dst.dat";
11815 uint16_t fnum1
= UINT16_MAX
;
11816 uint16_t fnum2
= UINT16_MAX
;
11817 size_t file_size
= 2*1024*1024;
11818 size_t splice_size
= 1*1024*1024 + 713;
11819 uint8_t digest1
[16], digest2
[16];
11822 TALLOC_CTX
*frame
= talloc_stackframe();
11824 printf("starting cli_splice test\n");
11826 if (!torture_open_connection(&cli1
, 0)) {
11830 cli_unlink(cli1
, fname_src
,
11831 FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
);
11832 cli_unlink(cli1
, fname_dst
,
11833 FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
);
11835 /* Create a file */
11836 status
= cli_ntcreate(cli1
, fname_src
, 0, GENERIC_ALL_ACCESS
,
11837 FILE_ATTRIBUTE_NORMAL
, 0, FILE_OVERWRITE_IF
,
11838 0, 0, &fnum1
, NULL
);
11840 if (!NT_STATUS_IS_OK(status
)) {
11841 d_printf("open %s failed: %s\n", fname_src
, nt_errstr(status
));
11845 /* Write file_size bytes - must be bigger than splice_size. */
11846 buf
= talloc_zero_array(frame
, uint8_t, file_size
);
11848 d_printf("talloc_fail\n");
11852 /* Fill it with random numbers. */
11853 generate_random_buffer(buf
, file_size
);
11855 /* MD5 the first 1MB + 713 bytes. */
11856 gnutls_hash_fast(GNUTLS_DIG_MD5
,
11861 status
= cli_writeall(cli1
,
11868 if (!NT_STATUS_IS_OK(status
)) {
11869 d_printf("cli_writeall failed: %s\n", nt_errstr(status
));
11873 status
= cli_ntcreate(cli1
, fname_dst
, 0, GENERIC_ALL_ACCESS
,
11874 FILE_ATTRIBUTE_NORMAL
, 0, FILE_OVERWRITE_IF
,
11875 0, 0, &fnum2
, NULL
);
11877 if (!NT_STATUS_IS_OK(status
)) {
11878 d_printf("open %s failed: %s\n", fname_dst
, nt_errstr(status
));
11882 /* Now splice 1MB + 713 bytes. */
11883 status
= cli_splice(cli1
,
11894 if (!NT_STATUS_IS_OK(status
)) {
11895 d_printf("cli_splice failed: %s\n", nt_errstr(status
));
11899 /* Clear the old buffer. */
11900 memset(buf
, '\0', file_size
);
11902 /* Read the new file. */
11903 status
= cli_read(cli1
, fnum2
, (char *)buf
, 0, splice_size
, &nread
);
11904 if (!NT_STATUS_IS_OK(status
)) {
11905 d_printf("cli_read failed: %s\n", nt_errstr(status
));
11908 if (nread
!= splice_size
) {
11909 d_printf("bad read of 0x%x, should be 0x%x\n",
11910 (unsigned int)nread
,
11911 (unsigned int)splice_size
);
11915 /* MD5 the first 1MB + 713 bytes. */
11916 gnutls_hash_fast(GNUTLS_DIG_MD5
,
11921 /* Must be the same. */
11922 if (memcmp(digest1
, digest2
, 16) != 0) {
11923 d_printf("bad MD5 compare\n");
11928 printf("Success on cli_splice test\n");
11933 if (fnum1
!= UINT16_MAX
) {
11934 cli_close(cli1
, fnum1
);
11936 if (fnum2
!= UINT16_MAX
) {
11937 cli_close(cli1
, fnum2
);
11940 cli_unlink(cli1
, fname_src
,
11941 FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
);
11942 cli_unlink(cli1
, fname_dst
,
11943 FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
);
11945 if (!torture_close_connection(cli1
)) {
11950 TALLOC_FREE(frame
);
11954 static bool run_uid_regression_test(int dummy
)
11956 static struct cli_state
*cli
;
11959 bool correct
= True
;
11960 struct smbXcli_tcon
*tcon_copy
= NULL
;
11963 printf("starting uid regression test\n");
11965 if (!torture_open_connection(&cli
, 0)) {
11969 smbXcli_conn_set_sockopt(cli
->conn
, sockops
);
11971 /* Ok - now save then logoff our current user. */
11972 old_vuid
= cli_state_get_uid(cli
);
11974 status
= cli_ulogoff(cli
);
11975 if (!NT_STATUS_IS_OK(status
)) {
11976 d_printf("(%s) cli_ulogoff failed: %s\n",
11977 __location__
, nt_errstr(status
));
11982 cli_state_set_uid(cli
, old_vuid
);
11984 /* Try an operation. */
11985 status
= cli_mkdir(cli
, "\\uid_reg_test");
11986 if (NT_STATUS_IS_OK(status
)) {
11987 d_printf("(%s) cli_mkdir succeeded\n",
11992 /* Should be bad uid. */
11993 if (!check_error(__LINE__
, status
, ERRSRV
, ERRbaduid
,
11994 NT_STATUS_USER_SESSION_DELETED
)) {
12000 old_cnum
= cli_state_get_tid(cli
);
12002 * This is an SMB1-only test.
12003 * Copy the tcon, not "save/restore".
12005 * In SMB1 the cli_tdis() below frees
12006 * cli->smb1.tcon so we need a copy
12007 * of the struct to put back for the
12008 * second tdis call with invalid vuid.
12010 * This is a test-only hack. Real client code
12011 * uses cli_state_save_tcon_share()/cli_state_restore_tcon_share().
12013 tcon_copy
= smbXcli_tcon_copy(cli
, cli
->smb1
.tcon
);
12014 if (tcon_copy
== NULL
) {
12019 /* Now try a SMBtdis with the invalid vuid set to zero. */
12020 cli_state_set_uid(cli
, 0);
12022 /* This should succeed. */
12023 status
= cli_tdis(cli
);
12025 if (NT_STATUS_IS_OK(status
)) {
12026 d_printf("First tdis with invalid vuid should succeed.\n");
12028 d_printf("First tdis failed (%s)\n", nt_errstr(status
));
12030 cli
->smb1
.tcon
= tcon_copy
;
12034 cli
->smb1
.tcon
= tcon_copy
;
12035 cli_state_set_uid(cli
, old_vuid
);
12036 cli_state_set_tid(cli
, old_cnum
);
12038 /* This should fail. */
12039 status
= cli_tdis(cli
);
12040 if (NT_STATUS_IS_OK(status
)) {
12041 d_printf("Second tdis with invalid vuid should fail - succeeded instead !.\n");
12045 /* Should be bad tid. */
12046 if (!check_error(__LINE__
, status
, ERRSRV
, ERRinvnid
,
12047 NT_STATUS_NETWORK_NAME_DELETED
)) {
12053 cli_rmdir(cli
, "\\uid_reg_test");
12062 static const char *illegal_chars
= "*\\/?<>|\":";
12063 static char force_shortname_chars
[] = " +,.[];=\177";
12065 static NTSTATUS
shortname_del_fn(struct file_info
*finfo
,
12066 const char *mask
, void *state
)
12068 struct cli_state
*pcli
= (struct cli_state
*)state
;
12070 NTSTATUS status
= NT_STATUS_OK
;
12072 slprintf(fname
, sizeof(fname
), "\\shortname\\%s", finfo
->name
);
12074 if (strcmp(finfo
->name
, ".") == 0 || strcmp(finfo
->name
, "..") == 0)
12075 return NT_STATUS_OK
;
12077 if (finfo
->attr
& FILE_ATTRIBUTE_DIRECTORY
) {
12078 status
= cli_rmdir(pcli
, fname
);
12079 if (!NT_STATUS_IS_OK(status
)) {
12080 printf("del_fn: failed to rmdir %s\n,", fname
);
12083 status
= cli_unlink(pcli
, fname
, FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
);
12084 if (!NT_STATUS_IS_OK(status
)) {
12085 printf("del_fn: failed to unlink %s\n,", fname
);
12097 static NTSTATUS
shortname_list_fn(struct file_info
*finfo
,
12098 const char *name
, void *state
)
12100 struct sn_state
*s
= (struct sn_state
*)state
;
12104 printf("shortname list: i = %d, name = |%s|, shortname = |%s|\n",
12105 i
, finfo
->name
, finfo
->short_name
);
12108 if (strchr(force_shortname_chars
, i
)) {
12109 if (!finfo
->short_name
) {
12110 /* Shortname not created when it should be. */
12111 d_printf("(%s) ERROR: Shortname was not created for file %s containing %d\n",
12112 __location__
, finfo
->name
, i
);
12115 } else if (finfo
->short_name
){
12116 /* Shortname created when it should not be. */
12117 d_printf("(%s) ERROR: Shortname %s was created for file %s\n",
12118 __location__
, finfo
->short_name
, finfo
->name
);
12122 return NT_STATUS_OK
;
12125 static bool run_shortname_test(int dummy
)
12127 static struct cli_state
*cli
;
12128 bool correct
= True
;
12134 printf("starting shortname test\n");
12136 if (!torture_open_connection(&cli
, 0)) {
12140 smbXcli_conn_set_sockopt(cli
->conn
, sockops
);
12142 cli_list(cli
, "\\shortname\\*", 0, shortname_del_fn
, cli
);
12143 cli_list(cli
, "\\shortname\\*", FILE_ATTRIBUTE_DIRECTORY
, shortname_del_fn
, cli
);
12144 cli_rmdir(cli
, "\\shortname");
12146 status
= cli_mkdir(cli
, "\\shortname");
12147 if (!NT_STATUS_IS_OK(status
)) {
12148 d_printf("(%s) cli_mkdir of \\shortname failed: %s\n",
12149 __location__
, nt_errstr(status
));
12154 if (strlcpy(fname
, "\\shortname\\", sizeof(fname
)) >= sizeof(fname
)) {
12158 if (strlcat(fname
, "test .txt", sizeof(fname
)) >= sizeof(fname
)) {
12165 for (i
= 32; i
< 128; i
++) {
12166 uint16_t fnum
= (uint16_t)-1;
12170 if (strchr(illegal_chars
, i
)) {
12175 status
= cli_ntcreate(cli
, fname
, 0, GENERIC_ALL_ACCESS
, FILE_ATTRIBUTE_NORMAL
,
12176 FILE_SHARE_READ
|FILE_SHARE_WRITE
,
12177 FILE_OVERWRITE_IF
, 0, 0, &fnum
, NULL
);
12178 if (!NT_STATUS_IS_OK(status
)) {
12179 d_printf("(%s) cli_nt_create of %s failed: %s\n",
12180 __location__
, fname
, nt_errstr(status
));
12184 cli_close(cli
, fnum
);
12187 status
= cli_list(cli
, "\\shortname\\test*.*", 0,
12188 shortname_list_fn
, &s
);
12189 if (s
.matched
!= 1) {
12190 d_printf("(%s) failed to list %s: %s\n",
12191 __location__
, fname
, nt_errstr(status
));
12196 status
= cli_unlink(cli
, fname
, FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
);
12197 if (!NT_STATUS_IS_OK(status
)) {
12198 d_printf("(%s) failed to delete %s: %s\n",
12199 __location__
, fname
, nt_errstr(status
));
12212 cli_list(cli
, "\\shortname\\*", 0, shortname_del_fn
, cli
);
12213 cli_list(cli
, "\\shortname\\*", FILE_ATTRIBUTE_DIRECTORY
, shortname_del_fn
, cli
);
12214 cli_rmdir(cli
, "\\shortname");
12215 torture_close_connection(cli
);
12219 TLDAPRC callback_code
;
12221 static void pagedsearch_cb(struct tevent_req
*req
)
12224 struct tldap_message
*msg
;
12227 rc
= tldap_search_paged_recv(req
, talloc_tos(), &msg
);
12228 if (!TLDAP_RC_IS_SUCCESS(rc
)) {
12229 d_printf("tldap_search_paged_recv failed: %s\n",
12230 tldap_rc2string(rc
));
12231 callback_code
= rc
;
12234 if (tldap_msg_type(msg
) != TLDAP_RES_SEARCH_ENTRY
) {
12238 if (!tldap_entry_dn(msg
, &dn
)) {
12239 d_printf("tldap_entry_dn failed\n");
12242 d_printf("%s\n", dn
);
12246 enum tldap_extended_val
{
12253 * Construct an extended dn control with either no value, 0 or 1
12255 * No value and 0 are equivalent (non-hyphenated GUID)
12256 * 1 has the hyphenated GUID
12258 static struct tldap_control
*
12259 tldap_build_extended_control(enum tldap_extended_val val
)
12261 struct tldap_control empty_control
;
12262 struct asn1_data
*data
;
12264 ZERO_STRUCT(empty_control
);
12266 if (val
!= EXTENDED_NONE
) {
12267 data
= asn1_init(talloc_tos(), ASN1_MAX_TREE_DEPTH
);
12273 if (!asn1_push_tag(data
, ASN1_SEQUENCE(0))) {
12277 if (!asn1_write_Integer(data
, (int)val
)) {
12281 if (!asn1_pop_tag(data
)) {
12285 if (!asn1_blob(data
, &empty_control
.value
)) {
12290 empty_control
.oid
= "1.2.840.113556.1.4.529";
12291 empty_control
.critical
= true;
12293 return tldap_add_control(talloc_tos(), NULL
, 0, &empty_control
);
12297 static bool tldap_test_dn_guid_format(struct tldap_context
*ld
, const char *basedn
,
12298 enum tldap_extended_val control_val
)
12300 struct tldap_control
*control
= tldap_build_extended_control(control_val
);
12302 struct tldap_message
**msg
;
12305 rc
= tldap_search(ld
, basedn
, TLDAP_SCOPE_BASE
,
12306 "(objectClass=*)", NULL
, 0, 0,
12308 0, 0, 0, 0, talloc_tos(), &msg
);
12309 if (!TLDAP_RC_IS_SUCCESS(rc
)) {
12310 d_printf("tldap_search for domain DN failed: %s\n",
12311 tldap_errstr(talloc_tos(), ld
, rc
));
12315 if (!tldap_entry_dn(msg
[0], &dn
)) {
12316 d_printf("tldap_search domain DN fetch failed: %s\n",
12317 tldap_errstr(talloc_tos(), ld
, rc
));
12321 d_printf("%s\n", dn
);
12324 uint32_t time_mid
, time_hi_and_version
;
12325 uint32_t clock_seq
[2];
12329 switch (control_val
) {
12330 case EXTENDED_NONE
:
12331 case EXTENDED_ZERO
:
12333 * When reading GUIDs with hyphens, scanf will treat
12334 * hyphen as a hex character (and counts as part of the
12335 * width). This creates leftover GUID string which we
12336 * check will for with 'next' and closing '>'.
12338 if (12 == sscanf(dn
, "<GUID=%08x%04x%04x%02x%02x%02x%02x%02x%02x%02x%02x>%c",
12339 &time_low
, &time_mid
,
12340 &time_hi_and_version
, &clock_seq
[0],
12341 &clock_seq
[1], &node
[0], &node
[1],
12342 &node
[2], &node
[3], &node
[4],
12343 &node
[5], &next
)) {
12344 /* This GUID is good */
12346 d_printf("GUID format in control (no hyphens) doesn't match output\n");
12352 if (12 == sscanf(dn
,
12353 "<GUID=%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x>%c",
12354 &time_low
, &time_mid
,
12355 &time_hi_and_version
, &clock_seq
[0],
12356 &clock_seq
[1], &node
[0], &node
[1],
12357 &node
[2], &node
[3], &node
[4],
12358 &node
[5], &next
)) {
12359 /* This GUID is good */
12361 d_printf("GUID format in control (with hyphens) doesn't match output\n");
12374 static bool run_tldap(int dummy
)
12376 struct tldap_context
*ld
;
12380 struct sockaddr_storage addr
;
12381 struct tevent_context
*ev
;
12382 struct tevent_req
*req
;
12384 const char *filter
;
12385 struct loadparm_context
*lp_ctx
= NULL
;
12386 int tcp_port
= 389;
12387 bool use_tls
= false;
12388 bool use_starttls
= false;
12389 int wrap_flags
= -1;
12390 uint32_t gensec_features
= 0;
12392 lp_ctx
= loadparm_init_s3(talloc_tos(), loadparm_s3_helpers());
12394 wrap_flags
= lpcfg_client_ldap_sasl_wrapping(lp_ctx
);
12396 if (wrap_flags
& ADS_AUTH_SASL_LDAPS
) {
12399 } else if (wrap_flags
& ADS_AUTH_SASL_STARTTLS
) {
12401 use_starttls
= true;
12403 if (wrap_flags
& ADS_AUTH_SASL_SEAL
) {
12404 gensec_features
|= GENSEC_FEATURE_SEAL
;
12406 if (wrap_flags
& ADS_AUTH_SASL_SIGN
) {
12407 gensec_features
|= GENSEC_FEATURE_SIGN
;
12410 if (gensec_features
!= 0) {
12411 gensec_features
|= GENSEC_FEATURE_LDAP_STYLE
;
12414 if (!resolve_name(host
, &addr
, 0, false)) {
12415 d_printf("could not find host %s\n", host
);
12418 status
= open_socket_out(&addr
, tcp_port
, 9999, &fd
);
12419 if (!NT_STATUS_IS_OK(status
)) {
12420 d_printf("open_socket_out failed: %s\n", nt_errstr(status
));
12424 ld
= tldap_context_create(talloc_tos(), fd
);
12427 d_printf("tldap_context_create failed\n");
12431 if (use_tls
&& !tldap_has_tls_tstream(ld
)) {
12432 struct tstream_tls_params
*tls_params
= NULL
;
12434 if (use_starttls
) {
12435 rc
= tldap_extended(ld
,
12436 LDB_EXTENDED_START_TLS_OID
,
12445 if (!TLDAP_RC_IS_SUCCESS(rc
)) {
12446 DBG_ERR("tldap_extended(%s) failed: %s\n",
12447 LDB_EXTENDED_START_TLS_OID
,
12448 tldap_errstr(talloc_tos(), ld
, rc
));
12453 status
= tstream_tls_params_client_lpcfg(talloc_tos(),
12457 if (!NT_STATUS_IS_OK(status
)) {
12458 DBG_ERR("tstream_tls_params_client_lpcfg failed: %s\n",
12459 nt_errstr(status
));
12463 rc
= tldap_tls_connect(ld
, tls_params
);
12464 if (!TLDAP_RC_IS_SUCCESS(rc
)) {
12465 DBG_ERR("tldap_tls_connect(%s) failed: %s\n",
12466 host
, tldap_errstr(talloc_tos(), ld
, rc
));
12471 rc
= tldap_fetch_rootdse(ld
);
12472 if (!TLDAP_RC_IS_SUCCESS(rc
)) {
12473 d_printf("tldap_fetch_rootdse failed: %s\n",
12474 tldap_errstr(talloc_tos(), ld
, rc
));
12478 basedn
= tldap_talloc_single_attribute(
12479 tldap_rootdse(ld
), "defaultNamingContext", talloc_tos());
12480 if (basedn
== NULL
) {
12481 d_printf("no defaultNamingContext\n");
12484 d_printf("defaultNamingContext: %s\n", basedn
);
12486 ev
= samba_tevent_context_init(talloc_tos());
12488 d_printf("tevent_context_init failed\n");
12492 rc
= tldap_gensec_bind(ld
, torture_creds
, "ldap", host
, NULL
,
12493 lp_ctx
, gensec_features
);
12494 if (!TLDAP_RC_IS_SUCCESS(rc
)) {
12495 d_printf("tldap_gensec_bind failed\n");
12499 callback_code
= TLDAP_SUCCESS
;
12501 req
= tldap_search_paged_send(talloc_tos(), ev
, ld
, basedn
,
12502 TLDAP_SCOPE_SUB
, "(objectclass=*)",
12504 NULL
, 0, NULL
, 0, 0, 0, 0, 5);
12506 d_printf("tldap_search_paged_send failed\n");
12509 tevent_req_set_callback(req
, pagedsearch_cb
, NULL
);
12511 tevent_req_poll(req
, ev
);
12515 rc
= callback_code
;
12517 if (!TLDAP_RC_IS_SUCCESS(rc
)) {
12518 d_printf("tldap_search with paging failed: %s\n",
12519 tldap_errstr(talloc_tos(), ld
, rc
));
12523 /* test search filters against rootDSE */
12524 filter
= "(&(|(name=samba)(nextRid<=10000000)(usnChanged>=10)(samba~=ambas)(!(name=s*m*a)))"
12525 "(|(name:=samba)(name:dn:2.5.13.5:=samba)(:dn:2.5.13.5:=samba)(!(name=*samba))))";
12527 rc
= tldap_search(ld
, "", TLDAP_SCOPE_BASE
, filter
,
12528 NULL
, 0, 0, NULL
, 0, NULL
, 0, 0, 0, 0,
12529 talloc_tos(), NULL
);
12530 if (!TLDAP_RC_IS_SUCCESS(rc
)) {
12531 d_printf("tldap_search with complex filter failed: %s\n",
12532 tldap_errstr(talloc_tos(), ld
, rc
));
12537 * Tests to check for regression of:
12539 * https://bugzilla.samba.org/show_bug.cgi?id=14029
12541 * TLDAP used here to pick apart the original string DN (with GUID)
12543 if (!tldap_test_dn_guid_format(ld
, basedn
, EXTENDED_NONE
)) {
12544 d_printf("tldap_search with extended dn (no val) failed: %s\n",
12545 tldap_errstr(talloc_tos(), ld
, rc
));
12548 if (!tldap_test_dn_guid_format(ld
, basedn
, EXTENDED_ZERO
)) {
12549 d_printf("tldap_search with extended dn (0) failed: %s\n",
12550 tldap_errstr(talloc_tos(), ld
, rc
));
12553 if (!tldap_test_dn_guid_format(ld
, basedn
, EXTENDED_ONE
)) {
12554 d_printf("tldap_search with extended dn (1) failed: %s\n",
12555 tldap_errstr(talloc_tos(), ld
, rc
));
12563 /* Torture test to ensure no regression of :
12564 https://bugzilla.samba.org/show_bug.cgi?id=7084
12567 static bool run_dir_createtime(int dummy
)
12569 struct cli_state
*cli
;
12570 const char *dname
= "\\testdir_createtime";
12571 const char *fname
= "\\testdir_createtime\\testfile";
12573 struct timespec create_time
;
12574 struct timespec create_time1
;
12579 if (!torture_open_connection(&cli
, 0)) {
12583 if (smbXcli_conn_protocol(cli
->conn
) >= PROTOCOL_SMB2_02
) {
12584 /* Ensure ino is zero, SMB2 gets a real one. */
12587 /* Ensure ino is -1, SMB1 never gets a real one. */
12588 ino
= (uint64_t)-1;
12591 cli_unlink(cli
, fname
, FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
);
12592 cli_rmdir(cli
, dname
);
12594 status
= cli_mkdir(cli
, dname
);
12595 if (!NT_STATUS_IS_OK(status
)) {
12596 printf("mkdir failed: %s\n", nt_errstr(status
));
12600 status
= cli_qpathinfo2(cli
,
12610 if (!NT_STATUS_IS_OK(status
)) {
12611 printf("cli_qpathinfo2 returned %s\n",
12612 nt_errstr(status
));
12616 if (smbXcli_conn_protocol(cli
->conn
) >= PROTOCOL_SMB2_02
) {
12617 /* SMB2 should always return an inode. */
12619 printf("SMB2 bad inode (0)\n");
12623 /* SMB1 must always return zero here. */
12625 printf("SMB1 bad inode (!0)\n");
12630 /* Sleep 3 seconds, then create a file. */
12633 status
= cli_openx(cli
, fname
, O_RDWR
| O_CREAT
| O_EXCL
,
12635 if (!NT_STATUS_IS_OK(status
)) {
12636 printf("cli_openx failed: %s\n", nt_errstr(status
));
12640 status
= cli_qpathinfo2(cli
,
12650 if (!NT_STATUS_IS_OK(status
)) {
12651 printf("cli_qpathinfo2 (2) returned %s\n",
12652 nt_errstr(status
));
12656 if (timespec_compare(&create_time1
, &create_time
)) {
12657 printf("run_dir_createtime: create time was updated (error)\n");
12659 printf("run_dir_createtime: create time was not updated (correct)\n");
12665 cli_unlink(cli
, fname
, FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
);
12666 cli_rmdir(cli
, dname
);
12667 if (!torture_close_connection(cli
)) {
12674 static bool run_streamerror(int dummy
)
12676 struct cli_state
*cli
;
12677 const char *dname
= "\\testdir_streamerror";
12678 const char *streamname
=
12679 "testdir_streamerror:{4c8cc155-6c1e-11d1-8e41-00c04fb9386d}:$DATA";
12681 time_t change_time
, access_time
, write_time
;
12687 if (!torture_open_connection(&cli
, 0)) {
12691 torture_deltree(cli
, dname
);
12693 status
= cli_mkdir(cli
, dname
);
12694 if (!NT_STATUS_IS_OK(status
)) {
12695 printf("mkdir failed: %s\n", nt_errstr(status
));
12699 status
= cli_qpathinfo1(cli
, streamname
, &change_time
, &access_time
,
12700 &write_time
, &size
, &attr
);
12701 if (!NT_STATUS_EQUAL(status
, NT_STATUS_OBJECT_NAME_NOT_FOUND
)) {
12702 printf("pathinfo returned %s, expected "
12703 "NT_STATUS_OBJECT_NAME_NOT_FOUND\n",
12704 nt_errstr(status
));
12708 status
= cli_ntcreate(cli
, streamname
, 0x16,
12709 FILE_READ_DATA
|FILE_READ_EA
|
12710 FILE_READ_ATTRIBUTES
|READ_CONTROL_ACCESS
,
12711 FILE_ATTRIBUTE_NORMAL
, FILE_SHARE_READ
,
12712 FILE_OPEN
, 0, 0, &fnum
, NULL
);
12714 if (!NT_STATUS_EQUAL(status
, NT_STATUS_OBJECT_NAME_NOT_FOUND
)) {
12715 printf("ntcreate returned %s, expected "
12716 "NT_STATUS_OBJECT_NAME_NOT_FOUND\n",
12717 nt_errstr(status
));
12722 cli_rmdir(cli
, dname
);
12726 struct pidtest_state
{
12732 static void pid_echo_done(struct tevent_req
*subreq
);
12734 static struct tevent_req
*pid_echo_send(TALLOC_CTX
*mem_ctx
,
12735 struct tevent_context
*ev
,
12736 struct cli_state
*cli
)
12738 struct tevent_req
*req
, *subreq
;
12739 struct pidtest_state
*state
;
12741 req
= tevent_req_create(mem_ctx
, &state
, struct pidtest_state
);
12746 SSVAL(state
->vwv
, 0, 1);
12747 state
->data
= data_blob_const("hello", 5);
12749 subreq
= smb1cli_req_send(state
,
12753 0, 0, /* *_flags */
12754 0, 0, /* *_flags2 */
12756 0xDEADBEEF, /* pid */
12758 NULL
, /* session */
12759 ARRAY_SIZE(state
->vwv
), state
->vwv
,
12760 state
->data
.length
, state
->data
.data
);
12762 if (tevent_req_nomem(subreq
, req
)) {
12763 return tevent_req_post(req
, ev
);
12765 tevent_req_set_callback(subreq
, pid_echo_done
, req
);
12769 static void pid_echo_done(struct tevent_req
*subreq
)
12771 struct tevent_req
*req
= tevent_req_callback_data(
12772 subreq
, struct tevent_req
);
12773 struct pidtest_state
*state
= tevent_req_data(
12774 req
, struct pidtest_state
);
12776 uint32_t num_bytes
;
12777 uint8_t *bytes
= NULL
;
12778 struct iovec
*recv_iov
= NULL
;
12779 uint8_t *phdr
= NULL
;
12780 uint16_t pidlow
= 0;
12781 uint16_t pidhigh
= 0;
12782 struct smb1cli_req_expected_response expected
[] = {
12784 .status
= NT_STATUS_OK
,
12789 status
= smb1cli_req_recv(subreq
, state
,
12794 NULL
, /* pvwv_offset */
12797 NULL
, /* pbytes_offset */
12799 expected
, ARRAY_SIZE(expected
));
12801 TALLOC_FREE(subreq
);
12803 if (!NT_STATUS_IS_OK(status
)) {
12804 tevent_req_nterror(req
, status
);
12808 if (num_bytes
!= state
->data
.length
) {
12809 tevent_req_nterror(req
, NT_STATUS_INVALID_NETWORK_RESPONSE
);
12813 if (memcmp(bytes
, state
->data
.data
, num_bytes
) != 0) {
12814 tevent_req_nterror(req
, NT_STATUS_INVALID_NETWORK_RESPONSE
);
12818 /* Check pid low/high == DEADBEEF */
12819 pidlow
= SVAL(phdr
, HDR_PID
);
12820 if (pidlow
!= 0xBEEF){
12821 printf("Incorrect pidlow 0x%x, should be 0xBEEF\n",
12822 (unsigned int)pidlow
);
12823 tevent_req_nterror(req
, NT_STATUS_INVALID_NETWORK_RESPONSE
);
12826 pidhigh
= SVAL(phdr
, HDR_PIDHIGH
);
12827 if (pidhigh
!= 0xDEAD){
12828 printf("Incorrect pidhigh 0x%x, should be 0xDEAD\n",
12829 (unsigned int)pidhigh
);
12830 tevent_req_nterror(req
, NT_STATUS_INVALID_NETWORK_RESPONSE
);
12834 tevent_req_done(req
);
12837 static NTSTATUS
pid_echo_recv(struct tevent_req
*req
)
12839 return tevent_req_simple_recv_ntstatus(req
);
12842 static bool run_pidhigh(int dummy
)
12844 bool success
= false;
12845 struct cli_state
*cli
= NULL
;
12847 struct tevent_context
*ev
= NULL
;
12848 struct tevent_req
*req
= NULL
;
12849 TALLOC_CTX
*frame
= talloc_stackframe();
12851 printf("starting pid high test\n");
12852 if (!torture_open_connection(&cli
, 0)) {
12855 smbXcli_conn_set_sockopt(cli
->conn
, sockops
);
12857 ev
= samba_tevent_context_init(frame
);
12862 req
= pid_echo_send(frame
, ev
, cli
);
12867 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
12871 status
= pid_echo_recv(req
);
12872 if (NT_STATUS_IS_OK(status
)) {
12873 printf("pid high test ok\n");
12879 TALLOC_FREE(frame
);
12880 torture_close_connection(cli
);
12885 Test Windows open on a bad POSIX symlink.
12887 static bool run_symlink_open_test(int dummy
)
12889 static struct cli_state
*cli
;
12890 const char *fname
= "non_existant_file";
12891 const char *sname
= "dangling_symlink";
12892 uint16_t fnum
= (uint16_t)-1;
12893 bool correct
= false;
12895 TALLOC_CTX
*frame
= NULL
;
12897 frame
= talloc_stackframe();
12899 printf("Starting Windows bad symlink open test\n");
12901 if (!torture_open_connection(&cli
, 0)) {
12902 TALLOC_FREE(frame
);
12906 smbXcli_conn_set_sockopt(cli
->conn
, sockops
);
12908 status
= torture_setup_unix_extensions(cli
);
12909 if (!NT_STATUS_IS_OK(status
)) {
12910 TALLOC_FREE(frame
);
12914 /* Ensure nothing exists. */
12915 cli_setatr(cli
, fname
, 0, 0);
12916 cli_posix_unlink(cli
, fname
);
12917 cli_setatr(cli
, sname
, 0, 0);
12918 cli_posix_unlink(cli
, sname
);
12920 /* Create a symlink pointing nowhere. */
12921 status
= cli_posix_symlink(cli
, fname
, sname
);
12922 if (!NT_STATUS_IS_OK(status
)) {
12923 printf("cli_posix_symlink of %s -> %s failed (%s)\n",
12926 nt_errstr(status
));
12930 /* Now ensure that a Windows open doesn't hang. */
12931 status
= cli_ntcreate(cli
,
12934 FILE_READ_DATA
|FILE_WRITE_DATA
,
12936 FILE_SHARE_READ
|FILE_SHARE_WRITE
|FILE_SHARE_DELETE
,
12944 * We get either NT_STATUS_OBJECT_NAME_NOT_FOUND or
12945 * NT_STATUS_OBJECT_PATH_NOT_FOUND depending on if
12946 * we use O_NOFOLLOW on the server or not.
12948 if (NT_STATUS_EQUAL(status
, NT_STATUS_OBJECT_NAME_NOT_FOUND
) ||
12949 NT_STATUS_EQUAL(status
, NT_STATUS_OBJECT_PATH_NOT_FOUND
))
12953 printf("cli_ntcreate of %s returned %s - should return"
12954 " either (%s) or (%s)\n",
12957 nt_errstr(NT_STATUS_OBJECT_NAME_NOT_FOUND
),
12958 nt_errstr(NT_STATUS_OBJECT_PATH_NOT_FOUND
));
12966 if (fnum
!= (uint16_t)-1) {
12967 cli_close(cli
, fnum
);
12968 fnum
= (uint16_t)-1;
12971 cli_setatr(cli
, sname
, 0, 0);
12972 cli_posix_unlink(cli
, sname
);
12973 cli_setatr(cli
, fname
, 0, 0);
12974 cli_posix_unlink(cli
, fname
);
12976 if (!torture_close_connection(cli
)) {
12980 TALLOC_FREE(frame
);
12984 static NTSTATUS
smb1_wild_mangle_list_fn(struct file_info
*finfo
,
12988 char **mangled_name_return
= (char **)state
;
12989 bool is_mangled
= strchr(finfo
->name
, '~');
12992 *mangled_name_return
= talloc_strdup(NULL
, finfo
->name
);
12993 if (*mangled_name_return
== NULL
) {
12994 return NT_STATUS_NO_MEMORY
;
12997 return NT_STATUS_OK
;
13000 static bool run_smb1_wild_mangle_unlink_test(int dummy
)
13002 static struct cli_state
*cli_posix
= NULL
;
13003 static struct cli_state
*cli
= NULL
;
13004 uint16_t fnum
= (uint16_t)-1;
13005 bool correct
= false;
13006 const char *dname
= "smb1_wild_mangle_unlink";
13007 const char *aname
= "smb1_wild_mangle_unlink/a";
13008 const char *star_name
= "smb1_wild_mangle_unlink/*";
13009 char *windows_unlink_name
= NULL
;
13010 char *mangled_name
= NULL
;
13013 printf("Starting SMB1 wild mangle unlink test\n");
13015 /* Open a Windows connection. */
13016 if (!torture_open_connection(&cli
, 0)) {
13020 smbXcli_conn_set_sockopt(cli
->conn
, sockops
);
13022 /* Open a POSIX connection. */
13023 if (!torture_open_connection(&cli_posix
, 0)) {
13027 smbXcli_conn_set_sockopt(cli_posix
->conn
, sockops
);
13029 status
= torture_setup_unix_extensions(cli_posix
);
13030 if (!NT_STATUS_IS_OK(status
)) {
13031 printf("server doesn't support POSIX\n");
13036 torture_deltree(cli
, dname
);
13039 * Create two files - 'a' and '*'.
13040 * We need POSIX extensions for this as '*'
13041 * is not a valid Windows name.
13044 status
= cli_mkdir(cli
, dname
);
13045 if (!NT_STATUS_IS_OK(status
)) {
13046 printf("cli_mkdir of %s returned %s\n",
13048 nt_errstr(status
));
13052 status
= cli_posix_open(cli_posix
,
13054 O_RDWR
|O_CREAT
|O_EXCL
,
13057 if (!NT_STATUS_IS_OK(status
)) {
13058 printf("cli_posix_open (create) of %s returned %s\n",
13060 nt_errstr(status
));
13063 status
= cli_close(cli_posix
, fnum
);
13064 if (!NT_STATUS_IS_OK(status
)) {
13067 status
= cli_posix_open(cli_posix
,
13069 O_RDWR
|O_CREAT
|O_EXCL
,
13072 if (!NT_STATUS_IS_OK(status
)) {
13073 printf("cli_posix_open (create) of %s returned %s\n",
13075 nt_errstr(status
));
13078 status
= cli_close(cli_posix
, fnum
);
13079 if (!NT_STATUS_IS_OK(status
)) {
13083 status
= cli_list(cli
,
13086 smb1_wild_mangle_list_fn
,
13088 if (!NT_STATUS_IS_OK(status
)) {
13089 printf("cli_list of %s returned %s\n",
13091 nt_errstr(status
));
13095 if (mangled_name
== NULL
) {
13099 printf("mangled_name = %s\n",
13103 * Try a Windows unlink with the mangled name.
13104 * This should *NOT* unlink the 'a' name.
13107 windows_unlink_name
= talloc_asprintf(cli_posix
,
13112 status
= cli_unlink(cli
, windows_unlink_name
, 0);
13113 if (!NT_STATUS_IS_OK(status
)) {
13114 printf("cli_unlink of %s returned %s\n",
13115 windows_unlink_name
,
13116 nt_errstr(status
));
13120 /* Does 'a' still exist ? */
13121 status
= cli_posix_open(cli_posix
,
13126 if (!NT_STATUS_IS_OK(status
)) {
13127 printf("cli_posix_open O_RNONLY of %s returned %s\n",
13129 nt_errstr(status
));
13133 status
= cli_close(cli_posix
, fnum
);
13134 if (!NT_STATUS_IS_OK(status
)) {
13142 TALLOC_FREE(windows_unlink_name
);
13143 TALLOC_FREE(mangled_name
);
13146 torture_deltree(cli
, dname
);
13147 torture_close_connection(cli
);
13150 if (cli_posix
!= NULL
) {
13151 torture_close_connection(cli_posix
);
13157 static bool run_smb1_wild_mangle_rename_test(int dummy
)
13159 static struct cli_state
*cli_posix
= NULL
;
13160 static struct cli_state
*cli
= NULL
;
13161 uint16_t fnum
= (uint16_t)-1;
13162 bool correct
= false;
13163 const char *dname
= "smb1_wild_mangle_rename";
13164 const char *fooname
= "smb1_wild_mangle_rename/foo";
13165 const char *foostar_name
= "smb1_wild_mangle_rename/fo*";
13166 const char *wild_name
= "smb1_wild_mangle_rename/*";
13167 char *windows_rename_src
= NULL
;
13168 const char *windows_rename_dst
= "smb1_wild_mangle_rename\\bar";
13169 char *mangled_name
= NULL
;
13172 printf("Starting SMB1 wild mangle rename test\n");
13174 if (!torture_open_connection(&cli_posix
, 0)) {
13178 smbXcli_conn_set_sockopt(cli_posix
->conn
, sockops
);
13180 status
= torture_setup_unix_extensions(cli_posix
);
13181 if (!NT_STATUS_IS_OK(status
)) {
13182 printf("server doesn't support POSIX\n");
13186 /* Open a Windows connection. */
13187 if (!torture_open_connection(&cli
, 0)) {
13191 smbXcli_conn_set_sockopt(cli
->conn
, sockops
);
13193 /* Ensure we start from fresh. */
13194 torture_deltree(cli
, dname
);
13197 * Create two files - 'foo' and 'fo*'.
13198 * We need POSIX extensions for this as 'fo*'
13199 * is not a valid Windows name.
13202 status
= cli_posix_mkdir(cli_posix
, dname
, 0770);
13203 if (!NT_STATUS_IS_OK(status
)) {
13204 printf("cli_posix_mkdir of %s returned %s\n",
13206 nt_errstr(status
));
13210 status
= cli_posix_open(cli_posix
,
13212 O_RDWR
|O_CREAT
|O_EXCL
,
13215 if (!NT_STATUS_IS_OK(status
)) {
13216 printf("cli_posix_open (create) of %s returned %s\n",
13218 nt_errstr(status
));
13221 status
= cli_close(cli_posix
, fnum
);
13222 if (!NT_STATUS_IS_OK(status
)) {
13225 status
= cli_posix_open(cli_posix
,
13227 O_RDWR
|O_CREAT
|O_EXCL
,
13230 if (!NT_STATUS_IS_OK(status
)) {
13231 printf("cli_posix_open (create) of %s returned %s\n",
13233 nt_errstr(status
));
13236 status
= cli_close(cli_posix
, fnum
);
13237 if (!NT_STATUS_IS_OK(status
)) {
13242 * Get the mangled name. We can re-use the
13243 * previous smb1_wild_mangle_list_fn for this.
13246 status
= cli_list(cli
,
13249 smb1_wild_mangle_list_fn
,
13251 if (!NT_STATUS_IS_OK(status
)) {
13252 printf("cli_list of %s returned %s\n",
13254 nt_errstr(status
));
13258 if (mangled_name
== NULL
) {
13262 printf("mangled_name = %s\n",
13266 * Try a Windows rename with the mangled name.
13267 * This should *NOT* rename the 'foo' name.
13270 windows_rename_src
= talloc_asprintf(cli_posix
,
13275 status
= cli_rename(cli
,
13276 windows_rename_src
,
13277 windows_rename_dst
,
13279 if (!NT_STATUS_IS_OK(status
)) {
13280 printf("cli_rename of %s -> %s returned %s\n",
13281 windows_rename_src
,
13282 windows_rename_dst
,
13283 nt_errstr(status
));
13287 /* Does 'foo' still exist ? */
13288 status
= cli_posix_open(cli_posix
,
13293 if (!NT_STATUS_IS_OK(status
)) {
13294 printf("cli_posix_open O_RNONLY of %s returned %s\n",
13296 nt_errstr(status
));
13300 status
= cli_close(cli_posix
, fnum
);
13301 if (!NT_STATUS_IS_OK(status
)) {
13309 TALLOC_FREE(mangled_name
);
13310 TALLOC_FREE(windows_rename_src
);
13313 torture_deltree(cli
, dname
);
13314 torture_close_connection(cli
);
13317 torture_close_connection(cli_posix
);
13323 * Only testing minimal time strings, as the others
13324 * need (locale-dependent) guessing at what strftime does and
13325 * even may differ in builds.
13327 static bool timesubst_test(void)
13329 TALLOC_CTX
*ctx
= NULL
;
13330 /* Sa 23. Dez 04:33:20 CET 2017 */
13331 const struct timeval tv
= { 1514000000, 123 };
13332 const char* expect_minimal
= "20171223_033320";
13333 const char* expect_minus
= "20171223_033320_000123";
13335 char *env_tz
, *orig_tz
= NULL
;
13336 bool result
= true;
13338 ctx
= talloc_new(NULL
);
13340 env_tz
= getenv("TZ");
13342 orig_tz
= talloc_strdup(ctx
, env_tz
);
13344 setenv("TZ", "UTC", 1);
13346 s
= minimal_timeval_string(ctx
, &tv
, false);
13348 if(!s
|| strcmp(s
, expect_minimal
)) {
13349 printf("minimal_timeval_string(ctx, tv, false) returned [%s], expected "
13350 "[%s]\n", s
? s
: "<nil>", expect_minimal
);
13354 s
= minimal_timeval_string(ctx
, &tv
, true);
13355 if(!s
|| strcmp(s
, expect_minus
)) {
13356 printf("minimal_timeval_string(ctx, tv, true) returned [%s], expected "
13357 "[%s]\n", s
? s
: "<nil>", expect_minus
);
13363 setenv("TZ", orig_tz
, 1);
13370 static bool run_local_substitute(int dummy
)
13374 ok
&= subst_test("%U", "bla", "", -1, -1, "bla");
13375 ok
&= subst_test("%u%U", "bla", "", -1, -1, "blabla");
13376 ok
&= subst_test("%g", "", "", -1, -1, "NO_GROUP");
13377 ok
&= subst_test("%G", "", "", -1, -1, "NO_GROUP");
13378 ok
&= subst_test("%g", "", "", -1, 0, gidtoname(0));
13379 ok
&= subst_test("%G", "", "", -1, 0, gidtoname(0));
13380 ok
&= subst_test("%D%u", "u", "dom", -1, 0, "domu");
13381 ok
&= subst_test("%i %I", "", "", -1, -1, "0.0.0.0 0.0.0.0");
13382 ok
&= subst_test("%j %J", "", "", -1, -1, "0_0_0_0 0_0_0_0");
13383 /* Substitution depends on current time, so better test the underlying
13384 formatting function. At least covers %t. */
13385 ok
&= timesubst_test();
13387 /* Different captialization rules in sub_basic... */
13389 ok
&= (strcmp(talloc_sub_basic(talloc_tos(), "BLA", "dom", "%U%D"),
13395 static bool run_local_base64(int dummy
)
13400 for (i
=1; i
<2000; i
++) {
13401 DATA_BLOB blob1
, blob2
;
13404 blob1
.data
= talloc_array(talloc_tos(), uint8_t, i
);
13406 generate_random_buffer(blob1
.data
, blob1
.length
);
13408 b64
= base64_encode_data_blob(talloc_tos(), blob1
);
13410 d_fprintf(stderr
, "base64_encode_data_blob failed "
13411 "for %d bytes\n", i
);
13414 blob2
= base64_decode_data_blob(b64
);
13417 if (data_blob_cmp(&blob1
, &blob2
)) {
13418 d_fprintf(stderr
, "data_blob_cmp failed for %d "
13422 TALLOC_FREE(blob1
.data
);
13423 data_blob_free(&blob2
);
13428 static void parse_fn(const struct gencache_timeout
*t
,
13430 void *private_data
)
13435 static bool run_local_gencache(int dummy
)
13441 struct memcache
*mem
;
13444 mem
= memcache_init(NULL
, 0);
13446 d_printf("%s: memcache_init failed\n", __location__
);
13449 memcache_set_global(mem
);
13451 if (!gencache_set("foo", "bar", time(NULL
) + 1000)) {
13452 d_printf("%s: gencache_set() failed\n", __location__
);
13456 if (!gencache_get("foo", NULL
, NULL
, NULL
)) {
13457 d_printf("%s: gencache_get() failed\n", __location__
);
13461 for (i
=0; i
<1000000; i
++) {
13462 gencache_parse("foo", parse_fn
, NULL
);
13465 if (!gencache_get("foo", talloc_tos(), &val
, &tm
)) {
13466 d_printf("%s: gencache_get() failed\n", __location__
);
13471 if (!gencache_get("foo", talloc_tos(), &val
, &tm
)) {
13472 d_printf("%s: gencache_get() failed\n", __location__
);
13476 if (strcmp(val
, "bar") != 0) {
13477 d_printf("%s: gencache_get() returned %s, expected %s\n",
13478 __location__
, val
, "bar");
13485 if (!gencache_del("foo")) {
13486 d_printf("%s: gencache_del() failed\n", __location__
);
13489 if (gencache_del("foo")) {
13490 d_printf("%s: second gencache_del() succeeded\n",
13495 if (gencache_get("foo", talloc_tos(), &val
, &tm
)) {
13496 d_printf("%s: gencache_get() on deleted entry "
13497 "succeeded\n", __location__
);
13501 blob
= data_blob_string_const_null("bar");
13502 tm
= time(NULL
) + 60;
13504 if (!gencache_set_data_blob("foo", blob
, tm
)) {
13505 d_printf("%s: gencache_set_data_blob() failed\n", __location__
);
13509 if (!gencache_get_data_blob("foo", talloc_tos(), &blob
, NULL
, NULL
)) {
13510 d_printf("%s: gencache_get_data_blob() failed\n", __location__
);
13514 if (strcmp((const char *)blob
.data
, "bar") != 0) {
13515 d_printf("%s: gencache_get_data_blob() returned %s, expected %s\n",
13516 __location__
, (const char *)blob
.data
, "bar");
13517 data_blob_free(&blob
);
13521 data_blob_free(&blob
);
13523 if (!gencache_del("foo")) {
13524 d_printf("%s: gencache_del() failed\n", __location__
);
13527 if (gencache_del("foo")) {
13528 d_printf("%s: second gencache_del() succeeded\n",
13533 if (gencache_get_data_blob("foo", talloc_tos(), &blob
, NULL
, NULL
)) {
13534 d_printf("%s: gencache_get_data_blob() on deleted entry "
13535 "succeeded\n", __location__
);
13540 blob
.data
= (uint8_t *)&v
;
13541 blob
.length
= sizeof(v
);
13543 if (!gencache_set_data_blob("blob", blob
, tm
)) {
13544 d_printf("%s: gencache_set_data_blob() failed\n",
13548 if (gencache_get("blob", talloc_tos(), &val
, &tm
)) {
13549 d_printf("%s: gencache_get succeeded\n", __location__
);
13556 static bool rbt_testflags(struct db_context
*db
, const char *key
,
13561 struct db_record
*rec
;
13563 rec
= dbwrap_fetch_locked(db
, db
, string_tdb_data(key
));
13565 d_fprintf(stderr
, "fetch_locked failed\n");
13569 status
= dbwrap_record_store(rec
, string_tdb_data(value
), TDB_MODIFY
);
13570 if (!NT_STATUS_EQUAL(status
, NT_STATUS_OBJECT_NAME_NOT_FOUND
)) {
13571 d_fprintf(stderr
, "store TDB_MODIFY unexpected status: %s\n",
13572 nt_errstr(status
));
13576 status
= dbwrap_record_store(rec
, string_tdb_data("overwriteme"),
13578 if (!NT_STATUS_IS_OK(status
)) {
13579 d_fprintf(stderr
, "store TDB_INSERT failed: %s\n",
13580 nt_errstr(status
));
13584 status
= dbwrap_record_store(rec
, string_tdb_data(value
), TDB_INSERT
);
13585 if (!NT_STATUS_EQUAL(status
, NT_STATUS_OBJECT_NAME_COLLISION
)) {
13586 d_fprintf(stderr
, "store TDB_INSERT unexpected status: %s\n",
13587 nt_errstr(status
));
13591 status
= dbwrap_record_store(rec
, string_tdb_data(value
), TDB_MODIFY
);
13592 if (!NT_STATUS_IS_OK(status
)) {
13593 d_fprintf(stderr
, "store TDB_MODIFY failed: %s\n",
13594 nt_errstr(status
));
13604 static bool rbt_testval(struct db_context
*db
, const char *key
,
13607 struct db_record
*rec
;
13608 TDB_DATA data
= string_tdb_data(value
);
13613 rec
= dbwrap_fetch_locked(db
, db
, string_tdb_data(key
));
13615 d_fprintf(stderr
, "fetch_locked failed\n");
13618 status
= dbwrap_record_store(rec
, data
, 0);
13619 if (!NT_STATUS_IS_OK(status
)) {
13620 d_fprintf(stderr
, "store failed: %s\n", nt_errstr(status
));
13625 rec
= dbwrap_fetch_locked(db
, db
, string_tdb_data(key
));
13627 d_fprintf(stderr
, "second fetch_locked failed\n");
13631 dbvalue
= dbwrap_record_get_value(rec
);
13632 if ((dbvalue
.dsize
!= data
.dsize
)
13633 || (memcmp(dbvalue
.dptr
, data
.dptr
, data
.dsize
) != 0)) {
13634 d_fprintf(stderr
, "Got wrong data back\n");
13644 static int local_rbtree_traverse_read(struct db_record
*rec
, void *private_data
)
13646 int *count2
= (int *)private_data
;
13651 static int local_rbtree_traverse_delete(struct db_record
*rec
, void *private_data
)
13653 int *count2
= (int *)private_data
;
13655 dbwrap_record_delete(rec
);
13659 static bool run_local_rbtree(int dummy
)
13661 struct db_context
*db
;
13668 db
= db_open_rbt(NULL
);
13671 d_fprintf(stderr
, "db_open_rbt failed\n");
13675 if (!rbt_testflags(db
, "firstkey", "firstval")) {
13679 for (i
= 0; i
< 999; i
++) {
13680 char key
[sizeof("key-9223372036854775807-1234")];
13681 char value
[sizeof("value-9223372036854775807-1234")];
13683 snprintf(key
, sizeof(key
), "key%ld-%d", random(), i
);
13684 snprintf(value
, sizeof(value
) ,"value%ld-%d", random(), i
);
13686 if (!rbt_testval(db
, key
, value
)) {
13690 snprintf(value
, sizeof(value
) ,"value%ld-%d", random(), i
+ 1);
13692 if (!rbt_testval(db
, key
, value
)) {
13698 count
= 0; count2
= 0;
13699 status
= dbwrap_traverse_read(db
, local_rbtree_traverse_read
,
13701 printf("%s: read1: %d %d, %s\n", __func__
, count
, count2
, nt_errstr(status
));
13702 if ((count
!= count2
) || (count
!= 1000)) {
13705 count
= 0; count2
= 0;
13706 status
= dbwrap_traverse(db
, local_rbtree_traverse_delete
,
13708 printf("%s: delete: %d %d, %s\n", __func__
, count
, count2
, nt_errstr(status
));
13709 if ((count
!= count2
) || (count
!= 1000)) {
13712 count
= 0; count2
= 0;
13713 status
= dbwrap_traverse_read(db
, local_rbtree_traverse_read
,
13715 printf("%s: read2: %d %d, %s\n", __func__
, count
, count2
, nt_errstr(status
));
13716 if ((count
!= count2
) || (count
!= 0)) {
13727 local test for character set functions
13729 This is a very simple test for the functionality in convert_string_error()
13731 static bool run_local_convert_string(int dummy
)
13733 TALLOC_CTX
*tmp_ctx
= talloc_new(NULL
);
13734 const char *test_strings
[2] = { "March", "M\303\244rz" };
13738 for (i
=0; i
<2; i
++) {
13739 const char *str
= test_strings
[i
];
13740 int len
= strlen(str
);
13741 size_t converted_size
;
13744 memset(dst
, 'X', sizeof(dst
));
13746 /* first try with real source length */
13747 ret
= convert_string_error(CH_UNIX
, CH_UTF8
,
13752 d_fprintf(stderr
, "Failed to convert '%s' to CH_DISPLAY\n", str
);
13756 if (converted_size
!= len
) {
13757 d_fprintf(stderr
, "Converted size of '%s' should be %d - got %d\n",
13758 str
, len
, (int)converted_size
);
13762 if (strncmp(str
, dst
, converted_size
) != 0) {
13763 d_fprintf(stderr
, "Expected '%s' to match '%s'\n", str
, dst
);
13767 if (strlen(str
) != converted_size
) {
13768 d_fprintf(stderr
, "Expected '%s' length %d - got %d\n", str
,
13769 (int)strlen(str
), (int)converted_size
);
13773 if (dst
[converted_size
] != 'X') {
13774 d_fprintf(stderr
, "Expected no termination of '%s'\n", dst
);
13778 /* now with srclen==-1, this causes the nul to be
13780 ret
= convert_string_error(CH_UNIX
, CH_UTF8
,
13785 d_fprintf(stderr
, "Failed to convert '%s' to CH_DISPLAY\n", str
);
13789 if (converted_size
!= len
+1) {
13790 d_fprintf(stderr
, "Converted size of '%s' should be %d - got %d\n",
13791 str
, len
, (int)converted_size
);
13795 if (strncmp(str
, dst
, converted_size
) != 0) {
13796 d_fprintf(stderr
, "Expected '%s' to match '%s'\n", str
, dst
);
13800 if (len
+1 != converted_size
) {
13801 d_fprintf(stderr
, "Expected '%s' length %d - got %d\n", str
,
13802 len
+1, (int)converted_size
);
13806 if (dst
[converted_size
] != 'X') {
13807 d_fprintf(stderr
, "Expected no termination of '%s'\n", dst
);
13814 TALLOC_FREE(tmp_ctx
);
13817 TALLOC_FREE(tmp_ctx
);
13821 static bool run_local_string_to_sid(int dummy
) {
13822 struct dom_sid sid
;
13824 if (string_to_sid(&sid
, "S--1-5-32-545")) {
13825 printf("allowing S--1-5-32-545\n");
13828 if (string_to_sid(&sid
, "S-1-5-32-+545")) {
13829 printf("allowing S-1-5-32-+545\n");
13832 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")) {
13833 printf("allowing S-1-2-3-4-5-6-7-8-9-0-1-2-3-4-5-6-7-8-9-0\n");
13836 if (string_to_sid(&sid
, "S-1-5-32-545-abc")) {
13837 printf("allowing S-1-5-32-545-abc\n");
13840 if (string_to_sid(&sid
, "S-300-5-32-545")) {
13841 printf("allowing S-300-5-32-545\n");
13844 if (string_to_sid(&sid
, "S-1-0xfffffffffffffe-32-545")) {
13845 printf("allowing S-1-0xfffffffffffffe-32-545\n");
13848 if (string_to_sid(&sid
, "S-1-0xffffffffffff-5294967297-545")) {
13849 printf("allowing S-1-0xffffffffffff-5294967297-545\n");
13852 if (!string_to_sid(&sid
, "S-1-0xfffffffffffe-32-545")) {
13853 printf("could not parse S-1-0xfffffffffffe-32-545\n");
13856 if (!string_to_sid(&sid
, "S-1-5-32-545")) {
13857 printf("could not parse S-1-5-32-545\n");
13860 if (!dom_sid_equal(&sid
, &global_sid_Builtin_Users
)) {
13861 struct dom_sid_buf buf
;
13862 printf("mis-parsed S-1-5-32-545 as %s\n",
13863 dom_sid_str_buf(&sid
, &buf
));
13869 static bool sid_to_string_test(const char *expected
) {
13872 struct dom_sid sid
;
13874 if (!string_to_sid(&sid
, expected
)) {
13875 printf("could not parse %s\n", expected
);
13879 str
= dom_sid_string(NULL
, &sid
);
13880 if (strcmp(str
, expected
)) {
13881 printf("Comparison failed (%s != %s)\n", str
, expected
);
13888 static bool run_local_sid_to_string(int dummy
) {
13889 if (!sid_to_string_test("S-1-0xffffffffffff-1-1-1-1-1-1-1-1-1-1-1-1"))
13891 if (!sid_to_string_test("S-1-545"))
13893 if (!sid_to_string_test("S-255-3840-1-1-1-1"))
13898 static bool run_local_binary_to_sid(int dummy
) {
13900 struct dom_sid
*sid
= talloc(NULL
, struct dom_sid
);
13901 static const uint8_t good_binary_sid
[] = {
13902 0x1, /* revision number */
13903 15, /* num auths */
13904 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, /* id_auth */
13905 0x1, 0x1, 0x1, 0x1, /* auth[0] */
13906 0x1, 0x1, 0x1, 0x1, /* auth[1] */
13907 0x1, 0x1, 0x1, 0x1, /* auth[2] */
13908 0x1, 0x1, 0x1, 0x1, /* auth[3] */
13909 0x1, 0x1, 0x1, 0x1, /* auth[4] */
13910 0x1, 0x1, 0x1, 0x1, /* auth[5] */
13911 0x1, 0x1, 0x1, 0x1, /* auth[6] */
13912 0x1, 0x1, 0x1, 0x1, /* auth[7] */
13913 0x1, 0x1, 0x1, 0x1, /* auth[8] */
13914 0x1, 0x1, 0x1, 0x1, /* auth[9] */
13915 0x1, 0x1, 0x1, 0x1, /* auth[10] */
13916 0x1, 0x1, 0x1, 0x1, /* auth[11] */
13917 0x1, 0x1, 0x1, 0x1, /* auth[12] */
13918 0x1, 0x1, 0x1, 0x1, /* auth[13] */
13919 0x1, 0x1, 0x1, 0x1, /* auth[14] */
13922 static const uint8_t long_binary_sid
[] = {
13923 0x1, /* revision number */
13924 15, /* num auths */
13925 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, /* id_auth */
13926 0x1, 0x1, 0x1, 0x1, /* auth[0] */
13927 0x1, 0x1, 0x1, 0x1, /* auth[1] */
13928 0x1, 0x1, 0x1, 0x1, /* auth[2] */
13929 0x1, 0x1, 0x1, 0x1, /* auth[3] */
13930 0x1, 0x1, 0x1, 0x1, /* auth[4] */
13931 0x1, 0x1, 0x1, 0x1, /* auth[5] */
13932 0x1, 0x1, 0x1, 0x1, /* auth[6] */
13933 0x1, 0x1, 0x1, 0x1, /* auth[7] */
13934 0x1, 0x1, 0x1, 0x1, /* auth[8] */
13935 0x1, 0x1, 0x1, 0x1, /* auth[9] */
13936 0x1, 0x1, 0x1, 0x1, /* auth[10] */
13937 0x1, 0x1, 0x1, 0x1, /* auth[11] */
13938 0x1, 0x1, 0x1, 0x1, /* auth[12] */
13939 0x1, 0x1, 0x1, 0x1, /* auth[13] */
13940 0x1, 0x1, 0x1, 0x1, /* auth[14] */
13941 0x1, 0x1, 0x1, 0x1, /* auth[15] */
13942 0x1, 0x1, 0x1, 0x1, /* auth[16] */
13943 0x1, 0x1, 0x1, 0x1, /* auth[17] */
13946 static const uint8_t long_binary_sid2
[] = {
13947 0x1, /* revision number */
13948 32, /* num auths */
13949 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, /* id_auth */
13950 0x1, 0x1, 0x1, 0x1, /* auth[0] */
13951 0x1, 0x1, 0x1, 0x1, /* auth[1] */
13952 0x1, 0x1, 0x1, 0x1, /* auth[2] */
13953 0x1, 0x1, 0x1, 0x1, /* auth[3] */
13954 0x1, 0x1, 0x1, 0x1, /* auth[4] */
13955 0x1, 0x1, 0x1, 0x1, /* auth[5] */
13956 0x1, 0x1, 0x1, 0x1, /* auth[6] */
13957 0x1, 0x1, 0x1, 0x1, /* auth[7] */
13958 0x1, 0x1, 0x1, 0x1, /* auth[8] */
13959 0x1, 0x1, 0x1, 0x1, /* auth[9] */
13960 0x1, 0x1, 0x1, 0x1, /* auth[10] */
13961 0x1, 0x1, 0x1, 0x1, /* auth[11] */
13962 0x1, 0x1, 0x1, 0x1, /* auth[12] */
13963 0x1, 0x1, 0x1, 0x1, /* auth[13] */
13964 0x1, 0x1, 0x1, 0x1, /* auth[14] */
13965 0x1, 0x1, 0x1, 0x1, /* auth[15] */
13966 0x1, 0x1, 0x1, 0x1, /* auth[16] */
13967 0x1, 0x1, 0x1, 0x1, /* auth[17] */
13968 0x1, 0x1, 0x1, 0x1, /* auth[18] */
13969 0x1, 0x1, 0x1, 0x1, /* auth[19] */
13970 0x1, 0x1, 0x1, 0x1, /* auth[20] */
13971 0x1, 0x1, 0x1, 0x1, /* auth[21] */
13972 0x1, 0x1, 0x1, 0x1, /* auth[22] */
13973 0x1, 0x1, 0x1, 0x1, /* auth[23] */
13974 0x1, 0x1, 0x1, 0x1, /* auth[24] */
13975 0x1, 0x1, 0x1, 0x1, /* auth[25] */
13976 0x1, 0x1, 0x1, 0x1, /* auth[26] */
13977 0x1, 0x1, 0x1, 0x1, /* auth[27] */
13978 0x1, 0x1, 0x1, 0x1, /* auth[28] */
13979 0x1, 0x1, 0x1, 0x1, /* auth[29] */
13980 0x1, 0x1, 0x1, 0x1, /* auth[30] */
13981 0x1, 0x1, 0x1, 0x1, /* auth[31] */
13984 ret
= sid_parse(good_binary_sid
, sizeof(good_binary_sid
), sid
);
13988 ret
= sid_parse(long_binary_sid2
, sizeof(long_binary_sid2
), sid
);
13992 ret
= sid_parse(long_binary_sid
, sizeof(long_binary_sid
), sid
);
13999 /* Split a path name into filename and stream name components. Canonicalise
14000 * such that an implicit $DATA token is always explicit.
14002 * The "specification" of this function can be found in the
14003 * run_local_stream_name() function in torture.c, I've tried those
14004 * combinations against a W2k3 server.
14007 static NTSTATUS
split_ntfs_stream_name(TALLOC_CTX
*mem_ctx
, const char *fname
,
14008 char **pbase
, char **pstream
)
14011 char *stream
= NULL
;
14012 char *sname
; /* stream name */
14013 const char *stype
; /* stream type */
14015 DEBUG(10, ("split_ntfs_stream_name called for [%s]\n", fname
));
14017 sname
= strchr_m(fname
, ':');
14019 if (sname
== NULL
) {
14020 if (pbase
!= NULL
) {
14021 base
= talloc_strdup(mem_ctx
, fname
);
14022 NT_STATUS_HAVE_NO_MEMORY(base
);
14027 if (pbase
!= NULL
) {
14028 base
= talloc_strndup(mem_ctx
, fname
, PTR_DIFF(sname
, fname
));
14029 NT_STATUS_HAVE_NO_MEMORY(base
);
14034 stype
= strchr_m(sname
, ':');
14036 if (stype
== NULL
) {
14037 sname
= talloc_strdup(mem_ctx
, sname
);
14041 if (strcasecmp_m(stype
, ":$DATA") != 0) {
14043 * If there is an explicit stream type, so far we only
14044 * allow $DATA. Is there anything else allowed? -- vl
14046 DEBUG(10, ("[%s] is an invalid stream type\n", stype
));
14048 return NT_STATUS_OBJECT_NAME_INVALID
;
14050 sname
= talloc_strndup(mem_ctx
, sname
, PTR_DIFF(stype
, sname
));
14054 if (sname
== NULL
) {
14056 return NT_STATUS_NO_MEMORY
;
14059 if (sname
[0] == '\0') {
14061 * no stream name, so no stream
14066 if (pstream
!= NULL
) {
14067 stream
= talloc_asprintf(mem_ctx
, "%s:%s", sname
, stype
);
14068 if (stream
== NULL
) {
14069 TALLOC_FREE(sname
);
14071 return NT_STATUS_NO_MEMORY
;
14074 * upper-case the type field
14076 (void)strupper_m(strchr_m(stream
, ':')+1);
14080 if (pbase
!= NULL
) {
14083 if (pstream
!= NULL
) {
14086 return NT_STATUS_OK
;
14089 static bool test_stream_name(const char *fname
, const char *expected_base
,
14090 const char *expected_stream
,
14091 NTSTATUS expected_status
)
14095 char *stream
= NULL
;
14097 status
= split_ntfs_stream_name(talloc_tos(), fname
, &base
, &stream
);
14098 if (!NT_STATUS_EQUAL(status
, expected_status
)) {
14102 if (!NT_STATUS_IS_OK(status
)) {
14106 if (base
== NULL
) goto error
;
14108 if (strcmp(expected_base
, base
) != 0) goto error
;
14110 if ((expected_stream
!= NULL
) && (stream
== NULL
)) goto error
;
14111 if ((expected_stream
== NULL
) && (stream
!= NULL
)) goto error
;
14113 if ((stream
!= NULL
) && (strcmp(expected_stream
, stream
) != 0))
14117 TALLOC_FREE(stream
);
14121 d_fprintf(stderr
, "Do test_stream(%s, %s, %s, %s)\n",
14122 fname
, expected_base
? expected_base
: "<NULL>",
14123 expected_stream
? expected_stream
: "<NULL>",
14124 nt_errstr(expected_status
));
14125 d_fprintf(stderr
, "-> base=%s, stream=%s, status=%s\n",
14126 base
? base
: "<NULL>", stream
? stream
: "<NULL>",
14127 nt_errstr(status
));
14129 TALLOC_FREE(stream
);
14133 static bool run_local_stream_name(int dummy
)
14137 ret
&= test_stream_name(
14138 "bla", "bla", NULL
, NT_STATUS_OK
);
14139 ret
&= test_stream_name(
14140 "bla::$DATA", "bla", NULL
, NT_STATUS_OK
);
14141 ret
&= test_stream_name(
14142 "bla:blub:", "bla", NULL
, NT_STATUS_OBJECT_NAME_INVALID
);
14143 ret
&= test_stream_name(
14144 "bla::", NULL
, NULL
, NT_STATUS_OBJECT_NAME_INVALID
);
14145 ret
&= test_stream_name(
14146 "bla::123", "bla", NULL
, NT_STATUS_OBJECT_NAME_INVALID
);
14147 ret
&= test_stream_name(
14148 "bla:$DATA", "bla", "$DATA:$DATA", NT_STATUS_OK
);
14149 ret
&= test_stream_name(
14150 "bla:x:$DATA", "bla", "x:$DATA", NT_STATUS_OK
);
14151 ret
&= test_stream_name(
14152 "bla:x", "bla", "x:$DATA", NT_STATUS_OK
);
14157 static bool data_blob_equal(DATA_BLOB a
, DATA_BLOB b
)
14159 if (a
.length
!= b
.length
) {
14160 printf("a.length=%d != b.length=%d\n",
14161 (int)a
.length
, (int)b
.length
);
14164 if (memcmp(a
.data
, b
.data
, a
.length
) != 0) {
14165 printf("a.data and b.data differ\n");
14171 static bool run_local_memcache(int dummy
)
14173 struct memcache
*cache
;
14174 DATA_BLOB k1
, k2
, k3
, k4
, k5
;
14178 TALLOC_CTX
*mem_ctx
;
14184 size_t size1
, size2
;
14187 mem_ctx
= talloc_init("foo");
14188 if (mem_ctx
== NULL
) {
14192 /* STAT_CACHE TESTS */
14194 cache
= memcache_init(NULL
, sizeof(void *) == 8 ? 200 : 100);
14196 if (cache
== NULL
) {
14197 printf("memcache_init failed\n");
14201 d1
= data_blob_const("d1", 2);
14202 d3
= data_blob_const("d3", 2);
14204 k1
= data_blob_const("d1", 2);
14205 k2
= data_blob_const("d2", 2);
14206 k3
= data_blob_const("d3", 2);
14207 k4
= data_blob_const("d4", 2);
14208 k5
= data_blob_const("d5", 2);
14210 memcache_add(cache
, STAT_CACHE
, k1
, d1
);
14212 if (!memcache_lookup(cache
, STAT_CACHE
, k1
, &v1
)) {
14213 printf("could not find k1\n");
14216 if (!data_blob_equal(d1
, v1
)) {
14220 memcache_add(cache
, STAT_CACHE
, k1
, d3
);
14222 if (!memcache_lookup(cache
, STAT_CACHE
, k1
, &v3
)) {
14223 printf("could not find replaced k1\n");
14226 if (!data_blob_equal(d3
, v3
)) {
14230 TALLOC_FREE(cache
);
14232 /* GETWD_CACHE TESTS */
14233 str1
= talloc_strdup(mem_ctx
, "string1");
14234 if (str1
== NULL
) {
14237 ptr2
= str1
; /* Keep an alias for comparison. */
14239 str2
= talloc_strdup(mem_ctx
, "string2");
14240 if (str2
== NULL
) {
14244 cache
= memcache_init(NULL
, sizeof(void *) == 8 ? 200 : 100);
14245 if (cache
== NULL
) {
14246 printf("memcache_init failed\n");
14250 memcache_add_talloc(cache
, GETWD_CACHE
, k2
, &str1
);
14251 /* str1 == NULL now. */
14252 ptr1
= memcache_lookup_talloc(cache
, GETWD_CACHE
, k2
);
14253 if (ptr1
== NULL
) {
14254 printf("could not find k2\n");
14257 if (ptr1
!= ptr2
) {
14258 printf("fetch of k2 got wrong string\n");
14262 /* Add a blob to ensure k2 gets purged. */
14263 d3
= data_blob_talloc_zero(mem_ctx
, 180);
14264 memcache_add(cache
, STAT_CACHE
, k3
, d3
);
14266 ptr2
= memcache_lookup_talloc(cache
, GETWD_CACHE
, k2
);
14267 if (ptr2
!= NULL
) {
14268 printf("Did find k2, should have been purged\n");
14273 * Test that talloc size also is accounted in memcache and
14274 * causes purge of other object.
14277 str1
= talloc_zero_size(mem_ctx
, 100);
14278 str2
= talloc_zero_size(mem_ctx
, 100);
14280 memcache_add_talloc(cache
, GETWD_CACHE
, k4
, &str1
);
14281 memcache_add_talloc(cache
, GETWD_CACHE
, k5
, &str1
);
14283 ptr3
= memcache_lookup_talloc(cache
, GETWD_CACHE
, k4
);
14284 if (ptr3
!= NULL
) {
14285 printf("Did find k4, should have been purged\n");
14290 * Test that adding a duplicate non-talloced
14291 * key/value on top of a talloced key/value takes account
14292 * of the talloc_freed value size.
14294 TALLOC_FREE(cache
);
14295 TALLOC_FREE(mem_ctx
);
14297 mem_ctx
= talloc_init("key_replace");
14298 if (mem_ctx
== NULL
) {
14302 cache
= memcache_init(NULL
, sizeof(void *) == 8 ? 200 : 100);
14303 if (cache
== NULL
) {
14308 * Add a 100 byte talloced string. This will
14309 * store a (4 or 8 byte) pointer and record the
14310 * total talloced size.
14312 str1
= talloc_zero_size(mem_ctx
, 100);
14313 memcache_add_talloc(cache
, GETWD_CACHE
, k4
, &str1
);
14315 * Now overwrite with a small talloced
14316 * value. This should fit in the existing size
14317 * and the total talloced size should be removed
14318 * from the cache size.
14320 str1
= talloc_zero_size(mem_ctx
, 2);
14321 memcache_add_talloc(cache
, GETWD_CACHE
, k4
, &str1
);
14323 * Now store a 20 byte string. If the
14324 * total talloced size wasn't accounted for
14325 * and removed in the overwrite, then this
14328 str2
= talloc_zero_size(mem_ctx
, 20);
14329 memcache_add_talloc(cache
, GETWD_CACHE
, k5
, &str2
);
14331 ptr3
= memcache_lookup_talloc(cache
, GETWD_CACHE
, k4
);
14332 if (ptr3
== NULL
) {
14333 printf("Did not find k4, should not have been purged\n");
14337 TALLOC_FREE(cache
);
14338 TALLOC_FREE(mem_ctx
);
14340 mem_ctx
= talloc_init("foo");
14341 if (mem_ctx
== NULL
) {
14345 cache
= memcache_init(NULL
, 0);
14346 if (cache
== NULL
) {
14350 str1
= talloc_strdup(mem_ctx
, "string1");
14351 if (str1
== NULL
) {
14354 str2
= talloc_strdup(mem_ctx
, "string2");
14355 if (str2
== NULL
) {
14358 memcache_add_talloc(cache
, SINGLETON_CACHE_TALLOC
,
14359 data_blob_string_const("torture"), &str1
);
14360 size1
= talloc_total_size(cache
);
14362 memcache_add_talloc(cache
, SINGLETON_CACHE_TALLOC
,
14363 data_blob_string_const("torture"), &str2
);
14364 size2
= talloc_total_size(cache
);
14366 printf("size1=%d, size2=%d\n", (int)size1
, (int)size2
);
14368 if (size2
> size1
) {
14369 printf("memcache leaks memory!\n");
14375 TALLOC_FREE(cache
);
14379 static void wbclient_done(struct tevent_req
*req
)
14382 struct winbindd_response
*wb_resp
;
14383 int *i
= (int *)tevent_req_callback_data_void(req
);
14385 wbc_err
= wb_trans_recv(req
, req
, &wb_resp
);
14388 d_printf("wb_trans_recv %d returned %s\n", *i
, wbcErrorString(wbc_err
));
14391 static bool run_wbclient_multi_ping(int dummy
)
14393 struct tevent_context
*ev
;
14394 struct wb_context
**wb_ctx
;
14395 struct winbindd_request wb_req
;
14396 bool result
= false;
14399 BlockSignals(True
, SIGPIPE
);
14401 ev
= tevent_context_init(talloc_tos());
14406 wb_ctx
= talloc_array(ev
, struct wb_context
*, torture_nprocs
);
14407 if (wb_ctx
== NULL
) {
14411 ZERO_STRUCT(wb_req
);
14412 wb_req
.cmd
= WINBINDD_PING
;
14414 d_printf("torture_nprocs=%d, numops=%d\n", (int)torture_nprocs
, (int)torture_numops
);
14416 for (i
=0; i
<torture_nprocs
; i
++) {
14417 wb_ctx
[i
] = wb_context_init(ev
, NULL
);
14418 if (wb_ctx
[i
] == NULL
) {
14421 for (j
=0; j
<torture_numops
; j
++) {
14422 struct tevent_req
*req
;
14423 req
= wb_trans_send(ev
, ev
, wb_ctx
[i
],
14424 (j
% 2) == 0, &wb_req
);
14428 tevent_req_set_callback(req
, wbclient_done
, &i
);
14434 while (i
< torture_nprocs
* torture_numops
) {
14435 tevent_loop_once(ev
);
14444 static bool dbtrans_inc(struct db_context
*db
)
14446 struct db_record
*rec
;
14452 rec
= dbwrap_fetch_locked(db
, db
, string_term_tdb_data("transtest"));
14454 printf(__location__
"fetch_lock failed\n");
14458 value
= dbwrap_record_get_value(rec
);
14460 if (value
.dsize
!= sizeof(uint32_t)) {
14461 printf(__location__
"value.dsize = %d\n",
14466 memcpy(&val
, value
.dptr
, sizeof(val
));
14469 status
= dbwrap_record_store(
14470 rec
, make_tdb_data((uint8_t *)&val
, sizeof(val
)), 0);
14471 if (!NT_STATUS_IS_OK(status
)) {
14472 printf(__location__
"store failed: %s\n",
14473 nt_errstr(status
));
14483 static bool run_local_dbtrans(int dummy
)
14485 struct db_context
*db
;
14486 struct db_record
*rec
;
14492 db
= db_open(talloc_tos(), "transtest.tdb", 0, TDB_DEFAULT
,
14493 O_RDWR
|O_CREAT
, 0600, DBWRAP_LOCK_ORDER_1
,
14496 printf("Could not open transtest.db\n");
14500 res
= dbwrap_transaction_start(db
);
14502 printf(__location__
"transaction_start failed\n");
14506 rec
= dbwrap_fetch_locked(db
, db
, string_term_tdb_data("transtest"));
14508 printf(__location__
"fetch_lock failed\n");
14512 value
= dbwrap_record_get_value(rec
);
14514 if (value
.dptr
== NULL
) {
14516 status
= dbwrap_record_store(
14517 rec
, make_tdb_data((uint8_t *)&initial
,
14520 if (!NT_STATUS_IS_OK(status
)) {
14521 printf(__location__
"store returned %s\n",
14522 nt_errstr(status
));
14529 res
= dbwrap_transaction_commit(db
);
14531 printf(__location__
"transaction_commit failed\n");
14536 uint32_t val
, val2
;
14539 res
= dbwrap_transaction_start(db
);
14541 printf(__location__
"transaction_start failed\n");
14545 status
= dbwrap_fetch_uint32_bystring(db
, "transtest", &val
);
14546 if (!NT_STATUS_IS_OK(status
)) {
14547 printf(__location__
"dbwrap_fetch_uint32 failed: %s\n",
14548 nt_errstr(status
));
14552 for (i
=0; i
<10; i
++) {
14553 if (!dbtrans_inc(db
)) {
14558 status
= dbwrap_fetch_uint32_bystring(db
, "transtest", &val2
);
14559 if (!NT_STATUS_IS_OK(status
)) {
14560 printf(__location__
"dbwrap_fetch_uint32 failed: %s\n",
14561 nt_errstr(status
));
14565 if (val2
!= val
+ 10) {
14566 printf(__location__
"val=%d, val2=%d\n",
14567 (int)val
, (int)val2
);
14571 printf("val2=%d\r", val2
);
14573 res
= dbwrap_transaction_commit(db
);
14575 printf(__location__
"transaction_commit failed\n");
14585 * Just a dummy test to be run under a debugger. There's no real way
14586 * to inspect the tevent_poll specific function from outside of
14590 static bool run_local_tevent_poll(int dummy
)
14592 struct tevent_context
*ev
;
14593 struct tevent_fd
*fd1
, *fd2
;
14594 bool result
= false;
14596 ev
= tevent_context_init_byname(NULL
, "poll");
14598 d_fprintf(stderr
, "tevent_context_init_byname failed\n");
14602 fd1
= tevent_add_fd(ev
, ev
, 2, 0, NULL
, NULL
);
14604 d_fprintf(stderr
, "tevent_add_fd failed\n");
14607 fd2
= tevent_add_fd(ev
, ev
, 3, 0, NULL
, NULL
);
14609 d_fprintf(stderr
, "tevent_add_fd failed\n");
14614 fd2
= tevent_add_fd(ev
, ev
, 1, 0, NULL
, NULL
);
14616 d_fprintf(stderr
, "tevent_add_fd failed\n");
14626 static bool run_local_hex_encode_buf(int dummy
)
14632 for (i
=0; i
<sizeof(src
); i
++) {
14635 hex_encode_buf(buf
, src
, sizeof(src
));
14636 if (strcmp(buf
, "0001020304050607") != 0) {
14639 hex_encode_buf(buf
, NULL
, 0);
14640 if (buf
[0] != '\0') {
14646 static const char *remove_duplicate_addrs2_test_strings_vector
[] = {
14668 "1001:1111:1111:1000:0:1111:1111:1111",
14677 static const char *remove_duplicate_addrs2_test_strings_result
[] = {
14691 "1001:1111:1111:1000:0:1111:1111:1111"
14694 static bool run_local_remove_duplicate_addrs2(int dummy
)
14696 struct samba_sockaddr test_vector
[28];
14699 /* Construct the sockaddr_storage test vector. */
14700 for (i
= 0; i
< 28; i
++) {
14701 struct addrinfo hints
;
14702 struct addrinfo
*res
= NULL
;
14705 memset(&hints
, '\0', sizeof(hints
));
14706 hints
.ai_flags
= AI_NUMERICHOST
;
14707 ret
= getaddrinfo(remove_duplicate_addrs2_test_strings_vector
[i
],
14712 fprintf(stderr
, "getaddrinfo failed on [%s]\n",
14713 remove_duplicate_addrs2_test_strings_vector
[i
]);
14716 memset(&test_vector
[i
], '\0', sizeof(test_vector
[i
]));
14717 memcpy(&test_vector
[i
].u
.ss
,
14723 count
= remove_duplicate_addrs2(test_vector
, i
);
14726 fprintf(stderr
, "count wrong (%zu) should be 14\n",
14731 for (i
= 0; i
< count
; i
++) {
14732 char addr
[INET6_ADDRSTRLEN
];
14734 print_sockaddr(addr
, sizeof(addr
), &test_vector
[i
].u
.ss
);
14736 if (strcmp(addr
, remove_duplicate_addrs2_test_strings_result
[i
]) != 0) {
14737 fprintf(stderr
, "mismatch on [%zu] [%s] [%s]\n",
14740 remove_duplicate_addrs2_test_strings_result
[i
]);
14745 printf("run_local_remove_duplicate_addrs2: success\n");
14749 static bool run_local_tdb_opener(int dummy
)
14755 t
= tdb_open("test.tdb", 1000, TDB_CLEAR_IF_FIRST
,
14756 O_RDWR
|O_CREAT
, 0755);
14758 perror("tdb_open failed");
14769 static bool run_local_tdb_writer(int dummy
)
14775 t
= tdb_open("test.tdb", 1000, 0, O_RDWR
|O_CREAT
, 0755);
14777 perror("tdb_open failed");
14781 val
.dptr
= (uint8_t *)&v
;
14782 val
.dsize
= sizeof(v
);
14788 ret
= tdb_store(t
, val
, val
, 0);
14790 printf("%s\n", tdb_errorstr(t
));
14795 data
= tdb_fetch(t
, val
);
14796 if (data
.dptr
!= NULL
) {
14797 SAFE_FREE(data
.dptr
);
14803 static bool run_local_canonicalize_path(int dummy
)
14805 const char *src
[] = {
14812 ".././././../../../boo",
14824 "/foo/bar/../baz/",
14825 "////////////////",
14826 "/////////./././././.",
14827 "/./.././../.boo/../baz",
14828 "/a/component/path",
14829 "/a/component/path/",
14830 "/a/component/path/..",
14831 "/a/component/../path/",
14832 "///a/./././///component/../////path/",
14835 const char *dst
[] = {
14858 "/a/component/path",
14859 "/a/component/path",
14867 for (i
= 0; src
[i
] != NULL
; i
++) {
14868 char *d
= canonicalize_absolute_path(talloc_tos(), src
[i
]);
14870 perror("talloc fail\n");
14873 if (strcmp(d
, dst
[i
]) != 0) {
14875 "canonicalize mismatch %s -> %s != %s",
14876 src
[i
], d
, dst
[i
]);
14883 struct session_setup_nt1_truncated_state
{
14888 static void smb1_session_setup_nt1_truncated_done(struct tevent_req
*subreq
);
14890 static struct tevent_req
*smb1_session_setup_nt1_truncated_send(
14891 TALLOC_CTX
*mem_ctx
,
14892 struct tevent_context
*ev
,
14893 struct smbXcli_conn
*conn
)
14895 uint16_t *vwv
= NULL
;
14896 uint8_t *bytes
= NULL
;
14897 const char *pass
= "12345678";
14898 const char *uname
= "z";
14899 struct session_setup_nt1_truncated_state
*state
= NULL
;
14900 struct tevent_req
*req
= NULL
;
14901 struct tevent_req
*subreq
= NULL
;
14903 req
= tevent_req_create(mem_ctx
,
14905 struct session_setup_nt1_truncated_state
);
14909 vwv
= &state
->vwv
[0];
14910 bytes
= &state
->bytes
[0];
14912 SCVAL(vwv
+0, 0, 0xff);
14913 SCVAL(vwv
+0, 1, 0);
14914 SSVAL(vwv
+1, 0, 0);
14915 SSVAL(vwv
+2, 0, 8192);
14916 SSVAL(vwv
+3, 0, 2);
14917 SSVAL(vwv
+4, 0, 1);
14918 SIVAL(vwv
+5, 0, 0);
14919 SSVAL(vwv
+7, 0, strlen(pass
)); /* OEMPasswordLen */
14920 SSVAL(vwv
+8, 0, 0); /* UnicodePasswordLen */
14921 SSVAL(vwv
+9, 0, 0); /* reserved */
14922 SSVAL(vwv
+10, 0, 0); /* reserved */
14923 SIVAL(vwv
+11, 0, CAP_STATUS32
);
14925 memcpy(bytes
, pass
, strlen(pass
));
14926 bytes
+= strlen(pass
);
14927 memcpy(bytes
, uname
, strlen(uname
)+1);
14929 subreq
= smb1cli_req_send(state
, ev
, conn
,
14931 0, /* additional_flags */
14932 0, /* clear_flags */
14933 0, /* additional_flags2 */
14934 0, /* clear_flags2 */
14935 10000, /* timeout_msec */
14938 NULL
, /* session */
14941 strlen(pass
), /* Truncate length at password. */
14943 if (tevent_req_nomem(subreq
, req
)) {
14944 return tevent_req_post(req
, ev
);
14946 tevent_req_set_callback(subreq
,
14947 smb1_session_setup_nt1_truncated_done
,
14952 static void smb1_session_setup_nt1_truncated_done(struct tevent_req
*subreq
)
14954 struct tevent_req
*req
=
14955 tevent_req_callback_data(subreq
,
14956 struct tevent_req
);
14957 struct session_setup_nt1_truncated_state
*state
=
14958 tevent_req_data(req
,
14959 struct session_setup_nt1_truncated_state
);
14961 struct smb1cli_req_expected_response expected
[] = {
14963 .status
= NT_STATUS_OK
,
14968 status
= smb1cli_req_recv(subreq
, state
,
14973 NULL
, /* pvwv_offset */
14976 NULL
, /* pbytes_offset */
14978 expected
, ARRAY_SIZE(expected
));
14979 TALLOC_FREE(subreq
);
14980 if (tevent_req_nterror(req
, status
)) {
14983 tevent_req_done(req
);
14986 static NTSTATUS
smb1_session_setup_nt1_truncated_recv(struct tevent_req
*req
)
14988 return tevent_req_simple_recv_ntstatus(req
);
14991 static bool run_smb1_truncated_sesssetup(int dummy
)
14993 struct tevent_context
*ev
;
14994 struct tevent_req
*req
;
14995 struct smbXcli_conn
*conn
;
14996 struct sockaddr_storage ss
;
15001 printf("Starting send truncated SMB1 sesssetup.\n");
15003 ok
= resolve_name(host
, &ss
, 0x20, true);
15005 d_fprintf(stderr
, "Could not resolve name %s\n", host
);
15009 status
= open_socket_out(&ss
, 445, 10000, &fd
);
15010 if (!NT_STATUS_IS_OK(status
)) {
15011 d_fprintf(stderr
, "open_socket_out failed: %s\n",
15012 nt_errstr(status
));
15016 conn
= smbXcli_conn_create(talloc_tos(), fd
, host
, SMB_SIGNING_OFF
, 0,
15018 if (conn
== NULL
) {
15019 d_fprintf(stderr
, "smbXcli_conn_create failed\n");
15023 status
= smbXcli_negprot(conn
,
15030 if (!NT_STATUS_IS_OK(status
)) {
15031 d_fprintf(stderr
, "smbXcli_negprot failed!\n");
15035 ev
= samba_tevent_context_init(talloc_tos());
15037 d_fprintf(stderr
, "samba_tevent_context_init failed\n");
15041 req
= smb1_session_setup_nt1_truncated_send(ev
, ev
, conn
);
15043 d_fprintf(stderr
, "smb1_session_setup_nt1_truncated_send failed\n");
15047 ok
= tevent_req_poll_ntstatus(req
, ev
, &status
);
15049 d_fprintf(stderr
, "tevent_req_poll failed with status %s\n",
15050 nt_errstr(status
));
15054 status
= smb1_session_setup_nt1_truncated_recv(req
);
15055 if (!NT_STATUS_IS_OK(status
)) {
15056 d_fprintf(stderr
, "smb1_session_setup_nt1_truncated_recv returned "
15057 "%s, expected NT_STATUS_OK\n",
15058 nt_errstr(status
));
15066 struct smb1_negotiate_exit_state
{
15070 static void smb1_negotiate_exit_done(struct tevent_req
*subreq
);
15072 static struct tevent_req
*smb1_negotiate_exit_send(
15073 TALLOC_CTX
*mem_ctx
,
15074 struct tevent_context
*ev
,
15075 struct smbXcli_conn
*conn
)
15077 struct smb1_negotiate_exit_state
*state
= NULL
;
15078 struct tevent_req
*req
= NULL
;
15079 struct tevent_req
*subreq
= NULL
;
15081 req
= tevent_req_create(mem_ctx
,
15083 struct smb1_negotiate_exit_state
);
15087 subreq
= smb1cli_req_send(state
, ev
, conn
,
15089 0, /* additional_flags */
15090 0, /* clear_flags */
15091 0, /* additional_flags2 */
15092 0, /* clear_flags2 */
15093 10000, /* timeout_msec */
15096 NULL
, /* session */
15101 if (tevent_req_nomem(subreq
, req
)) {
15102 return tevent_req_post(req
, ev
);
15104 tevent_req_set_callback(subreq
,
15105 smb1_negotiate_exit_done
,
15110 static void smb1_negotiate_exit_done(struct tevent_req
*subreq
)
15112 struct tevent_req
*req
=
15113 tevent_req_callback_data(subreq
,
15114 struct tevent_req
);
15115 struct smb1_negotiate_exit_state
*state
=
15116 tevent_req_data(req
,
15117 struct smb1_negotiate_exit_state
);
15119 struct smb1cli_req_expected_response expected
[] = {
15121 .status
= NT_STATUS_OK
,
15126 status
= smb1cli_req_recv(subreq
, state
,
15131 NULL
, /* pvwv_offset */
15134 NULL
, /* pbytes_offset */
15136 expected
, ARRAY_SIZE(expected
));
15137 TALLOC_FREE(subreq
);
15138 if (tevent_req_nterror(req
, status
)) {
15141 tevent_req_done(req
);
15144 static NTSTATUS
smb1_negotiate_exit_recv(struct tevent_req
*req
)
15146 return tevent_req_simple_recv_ntstatus(req
);
15149 static bool do_smb1_exit(TALLOC_CTX
*mem_ctx
,
15150 struct tevent_context
*ev
,
15151 struct smbXcli_conn
*conn
)
15153 struct tevent_req
*req
;
15156 NTSTATUS expected_status
= NT_STATUS_DOS(ERRSRV
, ERRinvnid
);;
15158 req
= smb1_negotiate_exit_send(ev
, ev
, conn
);
15160 d_fprintf(stderr
, "smb1_negotiate_exit_send failed\n");
15164 ok
= tevent_req_poll_ntstatus(req
, ev
, &status
);
15166 d_fprintf(stderr
, "tevent_req_poll failed with status %s\n",
15167 nt_errstr(status
));
15171 status
= smb1_negotiate_exit_recv(req
);
15172 if (!NT_STATUS_EQUAL(status
, expected_status
)) {
15173 d_fprintf(stderr
, "smb1_negotiate_exit_recv returned "
15174 "%s, expected ERRSRV, ERRinvnid\n",
15175 nt_errstr(status
));
15181 static bool run_smb1_negotiate_exit(int dummy
)
15183 struct tevent_context
*ev
;
15184 struct smbXcli_conn
*conn
;
15185 struct sockaddr_storage ss
;
15190 printf("Starting send SMB1 negotiate+exit.\n");
15192 ok
= resolve_name(host
, &ss
, 0x20, true);
15194 d_fprintf(stderr
, "Could not resolve name %s\n", host
);
15198 status
= open_socket_out(&ss
, 445, 10000, &fd
);
15199 if (!NT_STATUS_IS_OK(status
)) {
15200 d_fprintf(stderr
, "open_socket_out failed: %s\n",
15201 nt_errstr(status
));
15205 conn
= smbXcli_conn_create(talloc_tos(), fd
, host
, SMB_SIGNING_OFF
, 0,
15207 if (conn
== NULL
) {
15208 d_fprintf(stderr
, "smbXcli_conn_create failed\n");
15212 status
= smbXcli_negprot(conn
,
15219 if (!NT_STATUS_IS_OK(status
)) {
15220 d_fprintf(stderr
, "smbXcli_negprot failed!\n");
15224 ev
= samba_tevent_context_init(talloc_tos());
15226 d_fprintf(stderr
, "samba_tevent_context_init failed\n");
15231 * Call do_smb1_exit twice to catch a server crash, the
15232 * server sends the first return code then crashes.
15234 ok
= do_smb1_exit(ev
, ev
, conn
);
15236 d_fprintf(stderr
, "do_smb1_exit (1) failed\n");
15239 ok
= do_smb1_exit(ev
, ev
, conn
);
15241 d_fprintf(stderr
, "do_smb1_exit (2) failed\n");
15249 static bool run_smb1_negotiate_tcon(int dummy
)
15251 struct cli_state
*cli
= NULL
;
15253 uint16_t max_xmit
= 0;
15256 printf("Starting send SMB1 negotiate+tcon.\n");
15257 cli
= open_nbt_connection();
15259 d_fprintf(stderr
, "open_nbt_connection failed!\n");
15262 smbXcli_conn_set_sockopt(cli
->conn
, sockops
);
15264 status
= smbXcli_negprot(cli
->conn
,
15271 if (!NT_STATUS_IS_OK(status
)) {
15272 d_fprintf(stderr
, "smbXcli_negprot failed %s!\n",
15273 nt_errstr(status
));
15276 status
= cli_raw_tcon(cli
,
15282 if (!NT_STATUS_EQUAL(status
, NT_STATUS_ACCESS_DENIED
)) {
15283 d_fprintf(stderr
, "cli_raw_tcon failed - got %s "
15284 "(should get NT_STATUS_ACCESS_DENIED)!\n",
15285 nt_errstr(status
));
15291 static bool run_ign_bad_negprot(int dummy
)
15293 struct tevent_context
*ev
;
15294 struct tevent_req
*req
;
15295 struct smbXcli_conn
*conn
;
15296 struct sockaddr_storage ss
;
15301 printf("starting ignore bad negprot\n");
15303 ok
= resolve_name(host
, &ss
, 0x20, true);
15305 d_fprintf(stderr
, "Could not resolve name %s\n", host
);
15309 status
= open_socket_out(&ss
, 445, 10000, &fd
);
15310 if (!NT_STATUS_IS_OK(status
)) {
15311 d_fprintf(stderr
, "open_socket_out failed: %s\n",
15312 nt_errstr(status
));
15316 conn
= smbXcli_conn_create(talloc_tos(), fd
, host
, SMB_SIGNING_OFF
, 0,
15318 if (conn
== NULL
) {
15319 d_fprintf(stderr
, "smbXcli_conn_create failed\n");
15323 status
= smbXcli_negprot(conn
,
15330 if (NT_STATUS_IS_OK(status
)) {
15331 d_fprintf(stderr
, "smbXcli_negprot succeeded!\n");
15335 ev
= samba_tevent_context_init(talloc_tos());
15337 d_fprintf(stderr
, "samba_tevent_context_init failed\n");
15341 req
= smb1cli_session_setup_nt1_send(
15342 ev
, ev
, conn
, 0, getpid(), NULL
, 65503, 2, 1, 0, "", "",
15343 data_blob_null
, data_blob_null
, 0x40,
15344 "Windows 2000 2195", "Windows 2000 5.0");
15346 d_fprintf(stderr
, "smb1cli_session_setup_nt1_send failed\n");
15350 ok
= tevent_req_poll_ntstatus(req
, ev
, &status
);
15352 d_fprintf(stderr
, "tevent_req_poll failed\n");
15356 status
= smb1cli_session_setup_nt1_recv(req
, NULL
, NULL
, NULL
, NULL
,
15358 if (!NT_STATUS_EQUAL(status
, NT_STATUS_CONNECTION_RESET
)) {
15359 d_fprintf(stderr
, "smb1cli_session_setup_nt1_recv returned "
15360 "%s, expected NT_STATUS_CONNECTION_RESET\n",
15361 nt_errstr(status
));
15367 printf("starting ignore bad negprot\n");
15373 static double create_procs(bool (*fn
)(int), bool *result
)
15376 volatile pid_t
*child_status
;
15377 volatile bool *child_status_out
;
15380 struct timeval start
;
15384 child_status
= (volatile pid_t
*)anonymous_shared_allocate(sizeof(pid_t
)*torture_nprocs
);
15385 if (!child_status
) {
15386 printf("Failed to setup shared memory\n");
15390 child_status_out
= (volatile bool *)anonymous_shared_allocate(sizeof(bool)*torture_nprocs
);
15391 if (!child_status_out
) {
15392 printf("Failed to setup result status shared memory\n");
15396 for (i
= 0; i
< torture_nprocs
; i
++) {
15397 child_status
[i
] = 0;
15398 child_status_out
[i
] = True
;
15401 start
= timeval_current();
15403 for (i
=0;i
<torture_nprocs
;i
++) {
15406 pid_t mypid
= getpid();
15407 sys_srandom(((int)mypid
) ^ ((int)time(NULL
)));
15409 slprintf(myname
,sizeof(myname
),"CLIENT%d", i
);
15412 if (torture_open_connection(¤t_cli
, i
)) break;
15413 if (tries
-- == 0) {
15414 printf("pid %d failed to start\n", (int)getpid());
15420 child_status
[i
] = getpid();
15422 while (child_status
[i
] && timeval_elapsed(&start
) < 5) smb_msleep(2);
15424 child_status_out
[i
] = fn(i
);
15431 for (i
=0;i
<torture_nprocs
;i
++) {
15432 if (child_status
[i
]) synccount
++;
15434 if (synccount
== torture_nprocs
) break;
15436 } while (timeval_elapsed(&start
) < 30);
15438 if (synccount
!= torture_nprocs
) {
15439 printf("FAILED TO START %d CLIENTS (started %d)\n", torture_nprocs
, synccount
);
15441 return timeval_elapsed(&start
);
15444 /* start the client load */
15445 start
= timeval_current();
15447 for (i
=0;i
<torture_nprocs
;i
++) {
15448 child_status
[i
] = 0;
15451 printf("%d clients started\n", torture_nprocs
);
15453 for (i
=0;i
<torture_nprocs
;i
++) {
15454 while (waitpid(0, &status
, 0) == -1 && errno
== EINTR
) /* noop */ ;
15459 for (i
=0;i
<torture_nprocs
;i
++) {
15460 if (!child_status_out
[i
]) {
15464 return timeval_elapsed(&start
);
15467 #define FLAG_MULTIPROC 1
15473 } torture_ops
[] = {
15476 .fn
= run_fdpasstest
,
15480 .fn
= run_locktest1
,
15484 .fn
= run_locktest2
,
15488 .fn
= run_locktest3
,
15492 .fn
= run_locktest4
,
15496 .fn
= run_locktest5
,
15500 .fn
= run_locktest6
,
15504 .fn
= run_locktest7
,
15508 .fn
= run_locktest8
,
15512 .fn
= run_locktest9a
,
15516 .fn
= run_locktest9b
,
15520 .fn
= run_locktest10
,
15524 .fn
= run_locktest11
,
15528 .fn
= run_locktest12
,
15532 .fn
= run_locktest13
,
15536 .fn
= run_unlinktest
,
15540 .fn
= run_browsetest
,
15544 .fn
= run_attrtest
,
15548 .fn
= run_trans2test
,
15552 .fn
= run_maxfidtest
,
15553 .flags
= FLAG_MULTIPROC
,
15558 .flags
= FLAG_MULTIPROC
,
15561 .name
= "RANDOMIPC",
15562 .fn
= run_randomipc
,
15565 .name
= "NEGNOWAIT",
15566 .fn
= run_negprot_nowait
,
15588 #ifdef HAVE_KERNEL_OPLOCKS_LINUX
15600 .fn
= run_dirtest1
,
15603 .name
= "DIR-CREATETIME",
15604 .fn
= run_dir_createtime
,
15608 .fn
= torture_denytest1
,
15612 .fn
= torture_denytest2
,
15616 .fn
= run_tcon_test
,
15620 .fn
= run_tcon_devtype_test
,
15624 .fn
= run_readwritetest
,
15628 .fn
= run_readwritemulti
,
15629 .flags
= FLAG_MULTIPROC
15633 .fn
= run_readwritelarge
,
15636 .name
= "RW-SIGNING",
15637 .fn
= run_readwritelarge_signtest
,
15641 .fn
= run_opentest
,
15645 .fn
= run_simple_posix_open_test
,
15648 .name
= "POSIX-APPEND",
15649 .fn
= run_posix_append
,
15652 .name
= "POSIX-SYMLINK-ACL",
15653 .fn
= run_acl_symlink_test
,
15656 .name
= "POSIX-SYMLINK-EA",
15657 .fn
= run_ea_symlink_test
,
15660 .name
= "POSIX-STREAM-DELETE",
15661 .fn
= run_posix_stream_delete
,
15664 .name
= "POSIX-OFD-LOCK",
15665 .fn
= run_posix_ofd_lock_test
,
15668 .name
= "POSIX-BLOCKING-LOCK",
15669 .fn
= run_posix_blocking_lock
,
15672 .name
= "POSIX-MKDIR",
15673 .fn
= run_posix_mkdir_test
,
15676 .name
= "POSIX-ACL-OPLOCK",
15677 .fn
= run_posix_acl_oplock_test
,
15680 .name
= "POSIX-ACL-SHAREROOT",
15681 .fn
= run_posix_acl_shareroot_test
,
15684 .name
= "POSIX-LS-WILDCARD",
15685 .fn
= run_posix_ls_wildcard_test
,
15688 .name
= "POSIX-LS-SINGLE",
15689 .fn
= run_posix_ls_single_test
,
15692 .name
= "POSIX-READLINK",
15693 .fn
= run_posix_readlink_test
,
15696 .name
= "POSIX-STAT",
15697 .fn
= run_posix_stat_test
,
15700 .name
= "POSIX-SYMLINK-PARENT",
15701 .fn
= run_posix_symlink_parent_test
,
15704 .name
= "POSIX-SYMLINK-CHMOD",
15705 .fn
= run_posix_symlink_chmod_test
,
15708 .name
= "POSIX-SYMLINK-RENAME",
15709 .fn
= run_posix_symlink_rename_test
,
15712 .name
= "POSIX-DIR-DEFAULT-ACL",
15713 .fn
= run_posix_dir_default_acl_test
,
15716 .name
= "POSIX-SYMLINK-GETPATHINFO",
15717 .fn
= run_posix_symlink_getpathinfo_test
,
15720 .name
= "POSIX-SYMLINK-SETPATHINFO",
15721 .fn
= run_posix_symlink_setpathinfo_test
,
15724 .name
= "WINDOWS-BAD-SYMLINK",
15725 .fn
= run_symlink_open_test
,
15728 .name
= "SMB1-WILD-MANGLE-UNLINK",
15729 .fn
= run_smb1_wild_mangle_unlink_test
,
15732 .name
= "SMB1-WILD-MANGLE-RENAME",
15733 .fn
= run_smb1_wild_mangle_rename_test
,
15736 .name
= "CASE-INSENSITIVE-CREATE",
15737 .fn
= run_case_insensitive_create
,
15740 .name
= "ASYNC-ECHO",
15741 .fn
= run_async_echo
,
15744 .name
= "UID-REGRESSION-TEST",
15745 .fn
= run_uid_regression_test
,
15748 .name
= "SHORTNAME-TEST",
15749 .fn
= run_shortname_test
,
15752 .name
= "ADDRCHANGE",
15753 .fn
= run_addrchange
,
15757 .name
= "OPENATTR",
15758 .fn
= run_openattrtest
,
15770 .name
= "RENAME-ACCESS",
15771 .fn
= run_rename_access
,
15774 .name
= "OWNER-RIGHTS",
15775 .fn
= run_owner_rights
,
15779 .fn
= run_deletetest
,
15782 .name
= "DELETE-STREAM",
15783 .fn
= run_delete_stream
,
15786 .name
= "DELETE-PRINT",
15787 .fn
= run_delete_print_test
,
15790 .name
= "DELETE-LN",
15791 .fn
= run_deletetest_ln
,
15794 .name
= "PROPERTIES",
15795 .fn
= run_properties
,
15799 .fn
= torture_mangle
,
15806 .name
= "MANGLE-ILLEGAL",
15807 .fn
= run_mangle_illegal
,
15814 .name
= "TRANS2SCAN",
15815 .fn
= torture_trans2_scan
,
15818 .name
= "NTTRANSSCAN",
15819 .fn
= torture_nttrans_scan
,
15823 .fn
= torture_utable
,
15826 .name
= "CASETABLE",
15827 .fn
= torture_casetable
,
15830 .name
= "ERRMAPEXTRACT",
15831 .fn
= run_error_map_extract
,
15834 .name
= "PIPE_NUMBER",
15835 .fn
= run_pipe_number
,
15839 .fn
= run_tcon2_test
,
15843 .fn
= torture_ioctl_test
,
15847 .fn
= torture_chkpath_test
,
15851 .fn
= run_fdsesstest
,
15858 .name
= "SESSSETUP_BENCH",
15859 .fn
= run_sesssetup_bench
,
15874 .name
= "WINDOWS-WRITE",
15875 .fn
= run_windows_write
,
15878 .name
= "LARGE_READX",
15879 .fn
= run_large_readx
,
15882 .name
= "MSDFS-ATTRIBUTE",
15883 .fn
= run_msdfs_attribute
,
15886 .name
= "NTTRANS-CREATE",
15887 .fn
= run_nttrans_create
,
15890 .name
= "NTTRANS-FSCTL",
15891 .fn
= run_nttrans_fsctl
,
15894 .name
= "CLI_ECHO",
15895 .fn
= run_cli_echo
,
15898 .name
= "CLI_SPLICE",
15899 .fn
= run_cli_splice
,
15906 .name
= "STREAMERROR",
15907 .fn
= run_streamerror
,
15910 .name
= "NOTIFY-BENCH",
15911 .fn
= run_notify_bench
,
15914 .name
= "NOTIFY-BENCH2",
15915 .fn
= run_notify_bench2
,
15918 .name
= "NOTIFY-BENCH3",
15919 .fn
= run_notify_bench3
,
15922 .name
= "BAD-NBT-SESSION",
15923 .fn
= run_bad_nbt_session
,
15926 .name
= "IGN-BAD-NEGPROT",
15927 .fn
= run_ign_bad_negprot
,
15930 .name
= "SMB-ANY-CONNECT",
15931 .fn
= run_smb_any_connect
,
15934 .name
= "NOTIFY-ONLINE",
15935 .fn
= run_notify_online
,
15938 .name
= "SMB2-BASIC",
15939 .fn
= run_smb2_basic
,
15942 .name
= "SMB2-NEGPROT",
15943 .fn
= run_smb2_negprot
,
15946 .name
= "SMB2-ANONYMOUS",
15947 .fn
= run_smb2_anonymous
,
15950 .name
= "SMB2-SESSION-RECONNECT",
15951 .fn
= run_smb2_session_reconnect
,
15954 .name
= "SMB2-TCON-DEPENDENCE",
15955 .fn
= run_smb2_tcon_dependence
,
15958 .name
= "SMB2-MULTI-CHANNEL",
15959 .fn
= run_smb2_multi_channel
,
15962 .name
= "SMB2-SESSION-REAUTH",
15963 .fn
= run_smb2_session_reauth
,
15966 .name
= "SMB2-FTRUNCATE",
15967 .fn
= run_smb2_ftruncate
,
15970 .name
= "SMB2-DIR-FSYNC",
15971 .fn
= run_smb2_dir_fsync
,
15974 .name
= "SMB2-PATH-SLASH",
15975 .fn
= run_smb2_path_slash
,
15978 .name
= "SMB1-SYSTEM-SECURITY",
15979 .fn
= run_smb1_system_security
,
15982 .name
= "SMB2-SACL",
15983 .fn
= run_smb2_sacl
,
15986 .name
= "SMB2-QUOTA1",
15987 .fn
= run_smb2_quota1
,
15990 .name
= "SMB2-INVALID-PIPENAME",
15991 .fn
= run_smb2_invalid_pipename
,
15994 .name
= "SMB2-STREAM-ACL",
15995 .fn
= run_smb2_stream_acl
,
15998 .name
= "SMB2-LIST-DIR-ASYNC",
15999 .fn
= run_list_dir_async_test
,
16002 .name
= "SMB2-DEL-ON-CLOSE-NONEMPTY",
16003 .fn
= run_delete_on_close_non_empty
,
16006 .name
= "SMB2-DEL-ON-CLOSE-NONWRITE-DELETE-YES",
16007 .fn
= run_delete_on_close_nonwrite_delete_yes_test
,
16010 .name
= "SMB2-DEL-ON-CLOSE-NONWRITE-DELETE-NO",
16011 .fn
= run_delete_on_close_nonwrite_delete_no_test
,
16014 .name
= "SMB2-DFS-PATHS",
16015 .fn
= run_smb2_dfs_paths
,
16018 .name
= "SMB2-NON-DFS-SHARE",
16019 .fn
= run_smb2_non_dfs_share
,
16022 .name
= "SMB2-DFS-SHARE-NON-DFS-PATH",
16023 .fn
= run_smb2_dfs_share_non_dfs_path
,
16026 .name
= "SMB2-DFS-FILENAME-LEADING-BACKSLASH",
16027 .fn
= run_smb2_dfs_filename_leading_backslash
,
16030 .name
= "SMB2-PIPE-READ-ASYNC-DISCONNECT",
16031 .fn
= run_smb2_pipe_read_async_disconnect
,
16034 .name
= "SMB1-TRUNCATED-SESSSETUP",
16035 .fn
= run_smb1_truncated_sesssetup
,
16038 .name
= "SMB1-NEGOTIATE-EXIT",
16039 .fn
= run_smb1_negotiate_exit
,
16042 .name
= "SMB1-NEGOTIATE-TCON",
16043 .fn
= run_smb1_negotiate_tcon
,
16046 .name
= "SMB1-DFS-PATHS",
16047 .fn
= run_smb1_dfs_paths
,
16050 .name
= "SMB1-DFS-SEARCH-PATHS",
16051 .fn
= run_smb1_dfs_search_paths
,
16054 .name
= "SMB1-DFS-OPERATIONS",
16055 .fn
= run_smb1_dfs_operations
,
16058 .name
= "SMB1-DFS-BADPATH",
16059 .fn
= run_smb1_dfs_check_badpath
,
16062 .name
= "CLEANUP1",
16063 .fn
= run_cleanup1
,
16066 .name
= "CLEANUP2",
16067 .fn
= run_cleanup2
,
16070 .name
= "CLEANUP4",
16071 .fn
= run_cleanup4
,
16074 .name
= "OPLOCK-CANCEL",
16075 .fn
= run_oplock_cancel
,
16082 .name
= "LOCAL-SUBSTITUTE",
16083 .fn
= run_local_substitute
,
16086 .name
= "LOCAL-GENCACHE",
16087 .fn
= run_local_gencache
,
16090 .name
= "LOCAL-DBWRAP-WATCH1",
16091 .fn
= run_dbwrap_watch1
,
16094 .name
= "LOCAL-DBWRAP-WATCH2",
16095 .fn
= run_dbwrap_watch2
,
16098 .name
= "LOCAL-DBWRAP-WATCH3",
16099 .fn
= run_dbwrap_watch3
,
16102 .name
= "LOCAL-DBWRAP-WATCH4",
16103 .fn
= run_dbwrap_watch4
,
16106 .name
= "LOCAL-DBWRAP-DO-LOCKED1",
16107 .fn
= run_dbwrap_do_locked1
,
16110 .name
= "LOCAL-MESSAGING-READ1",
16111 .fn
= run_messaging_read1
,
16114 .name
= "LOCAL-MESSAGING-READ2",
16115 .fn
= run_messaging_read2
,
16118 .name
= "LOCAL-MESSAGING-READ3",
16119 .fn
= run_messaging_read3
,
16122 .name
= "LOCAL-MESSAGING-READ4",
16123 .fn
= run_messaging_read4
,
16126 .name
= "LOCAL-MESSAGING-FDPASS1",
16127 .fn
= run_messaging_fdpass1
,
16130 .name
= "LOCAL-MESSAGING-FDPASS2",
16131 .fn
= run_messaging_fdpass2
,
16134 .name
= "LOCAL-MESSAGING-FDPASS2a",
16135 .fn
= run_messaging_fdpass2a
,
16138 .name
= "LOCAL-MESSAGING-FDPASS2b",
16139 .fn
= run_messaging_fdpass2b
,
16142 .name
= "LOCAL-MESSAGING-SEND-ALL",
16143 .fn
= run_messaging_send_all
,
16146 .name
= "LOCAL-BASE64",
16147 .fn
= run_local_base64
,
16150 .name
= "LOCAL-RBTREE",
16151 .fn
= run_local_rbtree
,
16154 .name
= "LOCAL-MEMCACHE",
16155 .fn
= run_local_memcache
,
16158 .name
= "LOCAL-STREAM-NAME",
16159 .fn
= run_local_stream_name
,
16162 .name
= "LOCAL-STR-MATCH-MSWILD",
16163 .fn
= run_str_match_mswild
,
16166 .name
= "LOCAL-STR-MATCH-REGEX-SUB1",
16167 .fn
= run_str_match_regex_sub1
,
16170 .name
= "WBCLIENT-MULTI-PING",
16171 .fn
= run_wbclient_multi_ping
,
16174 .name
= "LOCAL-string_to_sid",
16175 .fn
= run_local_string_to_sid
,
16178 .name
= "LOCAL-sid_to_string",
16179 .fn
= run_local_sid_to_string
,
16182 .name
= "LOCAL-binary_to_sid",
16183 .fn
= run_local_binary_to_sid
,
16186 .name
= "LOCAL-DBTRANS",
16187 .fn
= run_local_dbtrans
,
16190 .name
= "LOCAL-TEVENT-POLL",
16191 .fn
= run_local_tevent_poll
,
16194 .name
= "LOCAL-CONVERT-STRING",
16195 .fn
= run_local_convert_string
,
16198 .name
= "LOCAL-CONV-AUTH-INFO",
16199 .fn
= run_local_conv_auth_info
,
16202 .name
= "LOCAL-hex_encode_buf",
16203 .fn
= run_local_hex_encode_buf
,
16206 .name
= "LOCAL-IDMAP-TDB-COMMON",
16207 .fn
= run_idmap_tdb_common_test
,
16210 .name
= "LOCAL-remove_duplicate_addrs2",
16211 .fn
= run_local_remove_duplicate_addrs2
,
16214 .name
= "local-tdb-opener",
16215 .fn
= run_local_tdb_opener
,
16218 .name
= "local-tdb-writer",
16219 .fn
= run_local_tdb_writer
,
16222 .name
= "LOCAL-DBWRAP-CTDB1",
16223 .fn
= run_local_dbwrap_ctdb1
,
16226 .name
= "LOCAL-BENCH-PTHREADPOOL",
16227 .fn
= run_bench_pthreadpool
,
16230 .name
= "LOCAL-PTHREADPOOL-TEVENT",
16231 .fn
= run_pthreadpool_tevent
,
16234 .name
= "LOCAL-G-LOCK1",
16238 .name
= "LOCAL-G-LOCK2",
16242 .name
= "LOCAL-G-LOCK3",
16246 .name
= "LOCAL-G-LOCK4",
16250 .name
= "LOCAL-G-LOCK4A",
16251 .fn
= run_g_lock4a
,
16254 .name
= "LOCAL-G-LOCK5",
16258 .name
= "LOCAL-G-LOCK6",
16262 .name
= "LOCAL-G-LOCK7",
16266 .name
= "LOCAL-G-LOCK8",
16270 .name
= "LOCAL-G-LOCK-PING-PONG",
16271 .fn
= run_g_lock_ping_pong
,
16274 .name
= "LOCAL-CANONICALIZE-PATH",
16275 .fn
= run_local_canonicalize_path
,
16278 .name
= "LOCAL-NAMEMAP-CACHE1",
16279 .fn
= run_local_namemap_cache1
,
16282 .name
= "LOCAL-IDMAP-CACHE1",
16283 .fn
= run_local_idmap_cache1
,
16286 .name
= "qpathinfo-bufsize",
16287 .fn
= run_qpathinfo_bufsize
,
16290 .name
= "hide-new-files-timeout",
16291 .fn
= run_hidenewfiles
,
16294 .name
= "hide-new-files-timeout-showdirs",
16295 .fn
= run_hidenewfiles_showdirs
,
16297 #ifdef CLUSTER_SUPPORT
16299 .name
= "ctdbd-conn1",
16300 .fn
= run_ctdbd_conn1
,
16304 .name
= "readdir-timestamp",
16305 .fn
= run_readdir_timestamp
,
16308 .name
= "rpc-scale",
16309 .fn
= run_rpc_scale
,
16312 .name
= "LOCAL-TDB-VALIDATE",
16313 .fn
= run_tdb_validate
,
16320 /****************************************************************************
16321 run a specified test or "ALL"
16322 ****************************************************************************/
16323 static bool run_test(const char *name
)
16326 bool result
= True
;
16327 bool found
= False
;
16330 if (strequal(name
,"ALL")) {
16331 for (i
=0;torture_ops
[i
].name
;i
++) {
16332 run_test(torture_ops
[i
].name
);
16337 for (i
=0;torture_ops
[i
].name
;i
++) {
16338 fstr_sprintf(randomfname
, "\\XX%x",
16339 (unsigned)random());
16341 if (strequal(name
, torture_ops
[i
].name
)) {
16343 printf("Running %s\n", name
);
16344 if (torture_ops
[i
].flags
& FLAG_MULTIPROC
) {
16345 t
= create_procs(torture_ops
[i
].fn
, &result
);
16348 printf("TEST %s FAILED!\n", name
);
16351 struct timeval start
;
16352 start
= timeval_current();
16353 if (!torture_ops
[i
].fn(0)) {
16355 printf("TEST %s FAILED!\n", name
);
16357 t
= timeval_elapsed(&start
);
16359 printf("%s took %g secs\n\n", name
, t
);
16364 printf("Did not find a test named %s\n", name
);
16372 static void usage(void)
16376 printf("WARNING samba4 test suite is much more complete nowadays.\n");
16377 printf("Please use samba4 torture.\n\n");
16379 printf("Usage: smbtorture //server/share <options> TEST1 TEST2 ...\n");
16381 printf("\t-d debuglevel\n");
16382 printf("\t-U user%%pass\n");
16383 printf("\t-k use kerberos\n");
16384 printf("\t-N numprocs\n");
16385 printf("\t-n my_netbios_name\n");
16386 printf("\t-W workgroup\n");
16387 printf("\t-o num_operations\n");
16388 printf("\t-O socket_options\n");
16389 printf("\t-m maximum protocol\n");
16390 printf("\t-L use oplocks\n");
16391 printf("\t-c CLIENT.TXT specify client load file for NBENCH\n");
16392 printf("\t-A showall\n");
16393 printf("\t-p port\n");
16394 printf("\t-s seed\n");
16395 printf("\t-b unclist_filename specify multiple shares for multiple connections\n");
16396 printf("\t-f filename filename to test\n");
16397 printf("\t-e encrypt\n");
16398 printf("\t-T 'OPTION=VALUE' smb.conf option line\n");
16401 printf("tests are:");
16402 for (i
=0;torture_ops
[i
].name
;i
++) {
16403 printf(" %s", torture_ops
[i
].name
);
16407 printf("default test is ALL\n");
16412 /****************************************************************************
16414 ****************************************************************************/
16415 int main(int argc
,char *argv
[])
16421 bool correct
= True
;
16422 TALLOC_CTX
*frame
= talloc_stackframe();
16423 int seed
= time(NULL
);
16424 struct loadparm_context
*lp_ctx
= NULL
;
16426 #ifdef HAVE_SETBUFFER
16427 setbuffer(stdout
, NULL
, 0);
16430 setup_logging("smbtorture", DEBUG_STDOUT
);
16435 lp_ctx
= loadparm_init_s3(frame
, loadparm_s3_helpers());
16436 if (lp_ctx
== NULL
) {
16438 "Failed to initialise the global parameter structure.\n");
16442 if (is_default_dyn_CONFIGFILE()) {
16443 if(getenv("SMB_CONF_PATH")) {
16444 set_dyn_CONFIGFILE(getenv("SMB_CONF_PATH"));
16447 lp_load_global(get_dyn_CONFIGFILE());
16454 for(p
= argv
[1]; *p
; p
++)
16458 if (strncmp(argv
[1], "//", 2)) {
16462 fstrcpy(host
, &argv
[1][2]);
16463 p
= strchr_m(&host
[2],'/');
16468 fstrcpy(share
, p
+1);
16470 fstrcpy(myname
, get_myname(talloc_tos()));
16472 fprintf(stderr
, "Failed to get my hostname.\n");
16476 if (*username
== 0 && getenv("LOGNAME")) {
16477 fstrcpy(username
,getenv("LOGNAME"));
16483 fstrcpy(workgroup
, lp_workgroup());
16485 while ((opt
= getopt(argc
, argv
, "p:hW:U:n:N:O:o:m:Ll:d:Aec:ks:b:B:f:T:"))
16489 port_to_use
= atoi(optarg
);
16492 seed
= atoi(optarg
);
16495 fstrcpy(workgroup
,optarg
);
16498 lpcfg_set_cmdline(lp_ctx
, "client max protocol", optarg
);
16501 torture_nprocs
= atoi(optarg
);
16504 torture_numops
= atoi(optarg
);
16507 lpcfg_set_cmdline(lp_ctx
, "log level", optarg
);
16513 use_oplocks
= True
;
16516 local_path
= optarg
;
16519 torture_showall
= True
;
16522 fstrcpy(myname
, optarg
);
16525 client_txt
= optarg
;
16532 use_kerberos
= True
;
16534 d_printf("No kerberos support compiled in\n");
16540 fstrcpy(username
,optarg
);
16541 p
= strchr_m(username
,'%');
16544 fstrcpy(password
, p
+1);
16549 fstrcpy(multishare_conn_fname
, optarg
);
16550 use_multishare_conn
= True
;
16553 torture_blocksize
= atoi(optarg
);
16556 test_filename
= SMB_STRDUP(optarg
);
16559 lpcfg_set_option(lp_ctx
, optarg
);
16562 printf("Unknown option %c (%d)\n", (char)opt
, opt
);
16567 d_printf("using seed %d\n", seed
);
16571 if(use_kerberos
&& !gotuser
) gotpass
= True
;
16574 char pwd
[256] = {0};
16577 rc
= samba_getpass("Password:", pwd
, sizeof(pwd
), false, false);
16579 fstrcpy(password
, pwd
);
16586 printf("host=%s share=%s user=%s myname=%s\n",
16587 host
, share
, username
, myname
);
16589 torture_creds
= cli_session_creds_init(frame
,
16595 false, /* fallback_after_kerberos */
16596 false, /* use_ccache */
16597 false); /* password_is_nt_hash */
16598 if (torture_creds
== NULL
) {
16599 d_printf("cli_session_creds_init() failed.\n");
16603 if (argc
== optind
) {
16604 correct
= run_test("ALL");
16606 for (i
=optind
;i
<argc
;i
++) {
16607 if (!run_test(argv
[i
])) {
16613 TALLOC_FREE(frame
);